diff --git a/.esformatter b/.esformatter deleted file mode 100644 index a53a9ecb8..000000000 --- a/.esformatter +++ /dev/null @@ -1,33 +0,0 @@ -{ - "plugins": [ - "esformatter-quotes", - "esformatter-braces", - "esformatter-semicolons" - ], - "quotes": { - "type": "single", - "avoidEscape": false - }, - "whiteSpace": { - "before": { - "ParameterList": -1, - "ParameterComma": -1, - "FunctionDeclarationOpeningBrace": -1, - "FunctionDeclarationClosingBrace": -1, - "ForStatementExpressionOpening": -1 - }, - "after": { - "FunctionName": -1, - "ParameterComma": 1, - "FunctionReservedWord": -1, - "ParameterList": -1, - "FunctionDeclarationOpeningBrace": -1, - "PropertyName": -1 - } - }, - "lineBreak": { - "before": { - "EndOfFile": 1 - } - } -} diff --git a/.eslintrc b/.eslintrc index edd2566d8..a618f3642 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,7 @@ { "env": { - "es6": true + "node": true, + "browser": true }, "parserOptions": { "ecmaVersion": 6, @@ -11,7 +12,7 @@ }, "rules": { "no-cond-assign": 2, - "no-var": 0, + "no-var": 1, "prefer-const": 0, "no-extra-parens": 0, "no-dupe-keys": 2, @@ -34,6 +35,7 @@ "no-octal-escape": 2, "no-constant-condition": 1, "no-unused-expressions": 2, - "no-undefined": 0 + "no-undefined": 0, + "no-undef": 2 } } diff --git a/.gitignore b/.gitignore index 383db7e1f..8b9247097 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,6 @@ node_modules/ coverage/ -scripts/bower/bower-* -bower_components/ -tmp/ -viz/ - .DS_Store -.jshintrc .env .nyc_output/ - -*.iml -*.log -*.stackdump -*.swp -*~ -compromise.js.tmproj -compromise.xcodeproj -npm-debug.log -pennTreebank.js -compiled_tests.js -package-lock.json -coverage.lcov +.vscode \ No newline at end of file diff --git a/.npmignore b/.npmignore index 7eed469bb..ed6ed6eea 100644 --- a/.npmignore +++ b/.npmignore @@ -1,14 +1,12 @@ data demo +plugins scripts src -test -.esformatter +tests .eslintrc -.babelrc .gitignore -TODO.MD -viz changelog.md -fixme.md +hmm.md +rollup.config.js scratch.js diff --git a/LICENSE b/LICENSE index 324efbb63..6e3ff28f5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) 2017 compromise +Copyright (c) 2019 Spencer Kelly Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ 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. +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index ecfb92de7..c9a905674 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,23 @@
- +
compromise
+ +
modest natural language processing
+
npm install compromise
+
+ + by + Spencer Kelly and + + many contributors + + +
+
+
- +
+ @@ -11,456 +26,684 @@ -
modest natural-language processing in javascript
- - by - Spencer Kelly and - - many contributors - - +
-
- - + + - - - - - - -
- - - - - - - -
+
+ - compromise tries its best. +
+ +
+ + it is + small, + quick, + and usually good-enough. +
+ + + + +
+ + Welcome to v12! - Release Notes here 👍 + +
+ + + + +### .match(): + +compromise makes it simple to interpret and match text: -save yourself from **regex-whackamole**🤞: ```js -nlp(entireNovel).sentences().if('the #Adjective of times').out() +let doc = nlp(entireNovel) + +doc.if('the #Adjective of times').text() // "it was the blurst of times??" ``` -move things around: ```js -nlp('she sells seashells by the seashore.').sentences().toFutureTense().out() -// 'she will sell seashells...' -``` -respond to text input: -```js -if( doc.has('^simon says (shoot|fire) #Determiner lazer') ){ - fireLazer() -} else { - dontFire() +if (doc.has('^simon says #Verb+')) { + return doc.match('#Verb .*').text() //'fire the lazer ..' } ``` +
+ match docs +
- compromise is not the cleverest. -
- but it is - small, - quick, - and good-enough for a bunch of stuff. +
----- +### .verbs(): + +conjugate and negate verbs in any tense: + +```js +let doc = nlp('she sells seashells by the seashore.') +doc.verbs().toPastTense() +doc.text() +// 'she sold seashells by the seashore.' +``` - +
+ verb docs +
- - - - - - - -
- - <script src> - -
-         one javascript file         -
-
- 🙏 -
-     npm install compromise     -
-
-
- - - 86% - - -
-     on the Penn treebank     -
-
- IE9+ -
-       caniuse, youbetcha       -
-
+
- -#### ⚡️ on the Client-side -```html - - -``` +### .nouns(): -#### 🌋 Server-side! -```javascript -var nlp = require('compromise') +transform nouns to plural and possessive forms: -var doc = nlp('London is calling') -doc.sentences().toNegative() -// 'London is not calling' +```js +let doc = nlp('the purple dinosaur') +doc.nouns().toPlural() +doc.text() +// 'the purple dinosaurs' ``` - +
+ noun docs +
- Get the hang of things: +
- - - - - - -
-
- -           Tutorial #1           - -
-
- Input → output -
-
-
- -           Tutorial #2           - -
-
- Match & transform -
-
-
- -           Tutorial #3           - -
-
- Making a bot -
-
+### .numbers(): +interpret plaintext numbers -
- Detailed docs: -
- - - - - - - - -
-
- -           API           - -
-
-
- -           Full Tagset           - -
-
-
- -           Plugins           - -
-
-
- -           Outputs           - -
-
-
- -           Match Syntax           - -
-
- -## Examples: - - - - - - - - - - - - -
-
- -           Part-of-Speech tagging           - -
-
- nouns! verbs! adjectives! -
-
-
- -                 Named-entities                 - -
-
- people, places, organizations -
-
-
- -                 Number parsing                 - -
-
- seven hundred and fifty == 750 -
-
-
- -         Grammar-match         - -
-
- like a regex for a sentence -
-
-
- -           Verb conjugation           - -
-
- all your base are belong -
-
-
- -           Normalization           - -
-
- case, whitespace, contractions.. -
-
- -* Plural/singular: - grab the noun-phrases, make em plural: ```js -doc = nlp('a bottle of beer on the wall.') -doc.nouns(0).toPlural() -doc.out('text') -//'The bottles of beer on the wall.' -``` +nlp.extend(require('compromise-numbers')) -* Number parsing: - parse written-out numbers, and change their form: -```js -doc = nlp('ninety five thousand and fifty two') -doc.values().toNumber().out() -// '95052' - -doc = nlp('the 23rd of December') -doc.values().add(2).toText() -doc.out('text') -// 'the twenty fifth of December' +let doc = nlp('ninety five thousand and fifty two') +doc.numbers().add(2) +doc.text() +// 'ninety five thousand and fifty four' ``` -* Normalization: - handle looseness & variety of random text: -```js -doc = nlp("the guest-singer's björk at seven thirty.").normalize().out('text') -// 'The guest singer is Bjork at 7:30.' -``` +
+ number docs +
+
+ +
-* Tense: - switch to/from conjugations of any verb -```js -let doc = nlp('she sells seashells by the seashore.') -doc.sentences().toFutureTense().out('text') -//'she will sell seashells...' - -doc.verbs().conjugate() -// [{ PastTense: 'sold', -// Infinitive: 'sell', -// Gerund: 'selling', ... -// }] -``` +### .topics(): -* Contractions: - grab, expand and contract: -```js -doc = nlp("we're not gonna take it, no we ain't gonna take it.") -doc.has('going') // true -doc.match('are not').length // == 2 -doc.contractions().expand().out() -//'we are not going to take it, no we are not going to take it' -``` +grab subjects in a text: -* Named-entities: - get the people, places, organizations: ```js +let doc = nlp(buddyHolly) +doc + .people() + .if('mary') + .json() +// [{text:'Mary Tyler Moore'}] + +let doc = nlp(freshPrince) +doc + .places() + .first() + .text() +// 'West Phillidelphia' + doc = nlp('the opera about richard nixon visiting china') -doc.topics().data() +doc.topics().json() // [ // { text: 'richard nixon' }, // { text: 'china' } // ] ``` -* Custom lexicon: - make it do what you'd like: +
+ topics docs +
+ +
+ +
+ +### .contractions(): + +work with contracted and implicit words: + ```js -var lexicon={ - 'boston': 'MusicalGroup' -} -doc = nlp('i heard Boston\'s set in Chicago', lexicon) +let doc = nlp("we're not gonna take it, no we ain't gonna take it.") + +// match an implicit term +doc.has('going') // true + +// transform +doc.contractions().expand() +dox.text() +// 'we are not going to take it, no we are not going to take it.' +``` + +
+ contraction docs +
+
+ + + +
+ +Use it on the client-side: + +```html + + + +``` + +or as an es-module: -//alternatively, fix it 'in-post': -doc.match('heard #Possessive set').terms(1).tag('MusicalGroup') +```typescript +import nlp from 'compromise' + +var doc = nlp('London is calling') +doc.verbs().toNegative() +// 'London is not calling' ``` -* Handy outputs: - get sensible data: + + + +compromise is **170kb** (minified): + +
+ + + + +
+ +it's pretty fast. It can run on keypress: + +
+ + + +
+ +it works mainly by conjugating many forms of a basic word list. + +The final lexicon is ~14,000 words: + +
+ +
+ +you can read more about how it works, [here](https://observablehq.com/@spencermountain/compromise-internals). + + + +
+ +
+ +### .extend(): + +set a custom interpretation of your own words: + ```js -doc = nlp('We like Roy! We like Roy!').sentences().out('array') -// ['We like Roy!', 'We like Roy!'] - -doc = nlp('Tony Hawk').out('html') -/* - - Tony -   - Hawk - -*/ +let myWords = { + kermit: 'FirstName', + fozzie: 'FirstName', +} +let doc = nlp(muppetText, myWords) ``` - -* Plugins: - allow adding vocabulary, fixing errors, and setting context quickly: +or make more changes with a [compromise-plugin](https://observablehq.com/@spencermountain/compromise-plugins). + ```js -var plugin = { - tags:{ - Character:{ - isA: 'Noun' - } - }, - words:{ - itchy: 'Character', - scratchy: 'Character' +const nlp = require('compromise') + +nlp.extend((Doc, world) => { + // add new tags + world.addTags({ + Character: { + isA: 'Person', + notA: 'Adjective', + }, + }) + + // add or change words in the lexicon + world.addWords({ + kermit: 'Character', + gonzo: 'Character', + }) + + // add methods to run after the tagger + world.postProcess(doc => { + doc.match('light the lights').tag('#Verb . #Plural') + }) + + // add a whole new method + Doc.prototype.kermitVoice = function() { + this.sentences().prepend('well,') + this.match('i [(am|was)]').prepend('um,') + return this } -} -nlp.plugin(plugin) -nlp(`Couldn't Itchy share his pie with Scratchy?`).debug() -/* - couldn't - #Modal, #Verb - itchy - #Character, #Noun - share - #Infinitive, #Verb - ... -*/ +}) ``` -

- of course, there's a lot more stuff. -

-

- Join in - - we're fun, using semver, and moving fast: -

- - - - - - - - - -
- - -
        Twitter        
-
-
- - -
      Gitter chat      
-
-
- - -
      Stackoverflow      
-
-
- - -
        Projects        
-
-
- - -
      Pull-requests      
-
-
+
+ .extend() docs +
+
+ +
-
- - - - - - +### API: + +##### Constructor + +_(these methods are on the `nlp` object)_ + +- **[.tokenize()](https://observablehq.com/@spencermountain/compromise-tokenization)** - parse text without running POS-tagging +- **[.extend()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - mix in a compromise-plugin +- **[.load()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - re-generate a Doc object from .export() results +- **[.verbose()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - log our decision-making for debugging +- **[.version()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - current semver version of the library + +##### Utils + +- **[.all()](https://observablehq.com/@spencermountain/compromise-utils)** - return the whole original document ('zoom out') +- **[.found](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - is this document empty? +- **[.parent()](https://observablehq.com/@spencermountain/compromise-utils)** - return the previous result +- **[.parents()](https://observablehq.com/@spencermountain/compromise-utils)** - return all of the previous results +- **[.tagger()](https://observablehq.com/@spencermountain/compromise-tagger)** - (re-)run the part-of-speech tagger on this document +- **[.wordCount()](https://observablehq.com/@spencermountain/compromise-utils)** - count the # of terms in the document +- **[.length](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - count the # of characters in the document (string length) +- **[.clone()](https://observablehq.com/@spencermountain/compromise-utils)** - deep-copy the document, so that no references remain +- **[.cache({})](https://observablehq.com/@spencermountain/compromise-cache)** - freeze the current state of the document, for speed-purposes +- **[.uncache()](https://observablehq.com/@spencermountain/compromise-cache)** - un-freezes the current state of the document, so it may be transformed + +##### Accessors + +- **[.first(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - use only the first result(s) +- **[.last(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - use only the last result(s) +- **[.slice(n,n)](https://observablehq.com/@spencermountain/compromise-accessors)** - grab a subset of the results +- **[.eq(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - use only the nth result +- **[.firstTerm()](https://observablehq.com/@spencermountain/compromise-accessors)** - get the first word in each match +- **[.lastTerm()](https://observablehq.com/@spencermountain/compromise-accessors)** - get the end word in each match +- **[.termList()](https://observablehq.com/@spencermountain/compromise-accessors)** - return a flat list of all Term objects in match + +##### Match + +_(all match methods use the [match-syntax](https://docs.compromise.cool/compromise-match-syntax).)_ + +- **[.match('')](https://observablehq.com/@spencermountain/compromise-match)** - return a new Doc, with this one as a parent +- **[.not('')](https://observablehq.com/@spencermountain/compromise-match)** - return all results except for this +- **[.matchOne('')](https://observablehq.com/@spencermountain/compromise-match)** - return only the first match +- **[.if('')](https://observablehq.com/@spencermountain/compromise-match)** - return each current phrase, only if it contains this match ('only') +- **[.ifNo('')](https://observablehq.com/@spencermountain/compromise-match)** - Filter-out any current phrases that have this match ('notIf') +- **[.has('')](https://observablehq.com/@spencermountain/compromise-match)** - Return a boolean if this match exists +- **[.lookBehind('')](https://observablehq.com/@spencermountain/compromise-match)** - search through earlier terms, in the sentence +- **[.lookAhead('')](https://observablehq.com/@spencermountain/compromise-match)** - search through following terms, in the sentence +- **[.before('')](https://observablehq.com/@spencermountain/compromise-match)** - return all terms before a match, in each phrase +- **[.after('')](https://observablehq.com/@spencermountain/compromise-match)** - return all terms after a match, in each phrase +- **[.lookup([])](https://observablehq.com/@spencermountain/compromise-match)** - quick find for an array of string matches + +##### Case + +- **[.toLowerCase()](https://observablehq.com/@spencermountain/compromise-case)** - turn every letter of every term to lower-cse +- **[.toUpperCase()](https://observablehq.com/@spencermountain/compromise-case)** - turn every letter of every term to upper case +- **[.toTitleCase()](https://observablehq.com/@spencermountain/compromise-case)** - upper-case the first letter of each term +- **[.toCamelCase()](https://observablehq.com/@spencermountain/compromise-case)** - remove whitespace and title-case each term + +##### Whitespace + +- **[.pre('')](https://observablehq.com/@spencermountain/compromise-whitespace)** - add this punctuation or whitespace before each match +- **[.post('')](https://observablehq.com/@spencermountain/compromise-whitespace)** - add this punctuation or whitespace after each match +- **[.trim()](https://observablehq.com/@spencermountain/compromise-whitespace)** - remove start and end whitespace +- **[.hyphenate()](https://observablehq.com/@spencermountain/compromise-whitespace)** - connect words with hyphen, and remove whitespace +- **[.dehyphenate()](https://observablehq.com/@spencermountain/compromise-whitespace)** - remove hyphens between words, and set whitespace +- **[.toQuotations()](https://observablehq.com/@spencermountain/compromise-whitespace)** - add quotation marks around these matches +- **[.toParentheses()](https://observablehq.com/@spencermountain/compromise-whitespace)** - add brackets around these matches + +##### Tag + +- **[.tag('')](https://observablehq.com/@spencermountain/compromise-tagger)** - Give all terms the given tag +- **[.tagSafe('')](https://observablehq.com/@spencermountain/compromise-tagger)** - Only apply tag to terms if it is consistent with current tags +- **[.unTag('')](https://observablehq.com/@spencermountain/compromise-tagger)** - Remove this term from the given terms +- **[.canBe('')](https://observablehq.com/@spencermountain/compromise-tagger)** - return only the terms that can be this tag + +##### Loops + +- **[.map(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - run each phrase through a function, and create a new document +- **[.forEach(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - run a function on each phrase, as an individual document +- **[.filter(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - return only the phrases that return true +- **[.find(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - return a document with only the first phrase that matches +- **[.some(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - return true or false if there is one matching phrase +- **[.random(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - sample a subset of the results + +##### Insert + +- **[.replace(match, replace)](https://observablehq.com/@spencermountain/compromise-insert)** - search and replace match with new content +- **[.replaceWith(replace)](https://observablehq.com/@spencermountain/compromise-insert)** - substitute-in new text +- **[.delete()](https://observablehq.com/@spencermountain/compromise-insert)** - fully remove these terms from the document +- **[.append(str)](https://observablehq.com/@spencermountain/compromise-insert)** - add these new terms to the end (insertAfter) +- **[.prepend(str)](https://observablehq.com/@spencermountain/compromise-insert)** - add these new terms to the front (insertBefore) +- **[.concat()](https://observablehq.com/@spencermountain/compromise-insert)** - add these new things to the end + +##### Transform + +- **[.sort('method')](https://observablehq.com/@spencermountain/compromise-sorting)** - re-arrange the order of the matches (in place) +- **[.reverse()](https://observablehq.com/@spencermountain/compromise-sorting)** - reverse the order of the matches, but not the words +- **[.normalize({})](https://observablehq.com/@spencermountain/compromise-normalization)** - clean-up the text in various ways +- **[.unique()](https://observablehq.com/@spencermountain/compromise-sorting)** - remove any duplicate matches +- **[.split('')](https://observablehq.com/@spencermountain/compromise-split)** - return a Document with three parts for every match ('splitOn') +- **[.splitBefore('')](https://observablehq.com/@spencermountain/compromise-split)** - partition a phrase before each matching segment +- **[.splitAfter('')](https://observablehq.com/@spencermountain/compromise-split)** - partition a phrase after each matching segment +- **[.segment({})](https://observablehq.com/@spencermountain/compromise-split)** - split a document into labeled sections +- **[.join('')](https://observablehq.com/@spencermountain/compromise-split)** - make all phrases into one phrase + +##### Output + +- **[.text('method')](https://observablehq.com/@spencermountain/compromise-output)** - return the document as text +- **[.json({})](https://observablehq.com/@spencermountain/compromise-json)** - pull out desired metadata from the document +- **[.out('array|offset|terms')](https://observablehq.com/@spencermountain/compromise-output)** - some named output formats (deprecated) +- **[.debug()](https://observablehq.com/@spencermountain/compromise-output)** - pretty-print the current document and its tags +- **[.export()](https://observablehq.com/@spencermountain/compromise-export)** - store a parsed document for later use + +##### Selections + +- **[.terms()](https://observablehq.com/@spencermountain/compromise-selections)** - split-up results by each individual term +- **[.clauses()](https://observablehq.com/@spencermountain/compromise-selections)** - split-up sentences into multi-term phrases +- **[.hyphenated()](https://observablehq.com/@spencermountain/compromise-selections)** - all terms connected with a hyphen or dash like `'wash-out'` +- **[.phoneNumbers()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'(939) 555-0113'` +- **[.hashTags()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'#nlp'` +- **[.emails()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'hi@compromise.cool'` +- **[.emoticons()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `:)` +- **[.emojis()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `💋` +- **[.atMentions()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'@nlp_compromise'` +- **[.urls()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'compromise.cool'` +- **[.adverbs()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'quickly'` +- **[.pronouns()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'he'` +- **[.conjunctions()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'but'` +- **[.prepositions()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'of'` +- **[.abbreviations()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'Mrs.'` + +##### Subsets + +- **[.contractions()](https://observablehq.com/@spencermountain/compromise-contractions)** - things like "didn't" +- **[.contractions().expand()](https://observablehq.com/@spencermountain/compromise-contractions)** - things like "didn't" +- **[.contract()](https://observablehq.com/@spencermountain/compromise-contractions)** - `"she would"` -> `"she'd"` +- **[.parentheses()](https://observablehq.com/@spencermountain/compromise-selections)** - return anything inside (parentheses) +- **[.possessives()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `"Spencer's"` +- **[.quotations()](https://observablehq.com/@spencermountain/compromise-selections)** - return any terms inside quotation marks +- **[.acronyms()](https://observablehq.com/@spencermountain/compromise-selections)** - things like `'FBI'` +- **[.lists()](https://observablehq.com/@spencermountain/compromise-lists)** - things like `'eats, shoots, and leaves'` + - **[.lists().items()](https://observablehq.com/@spencermountain/compromise-lists)** - return the partitioned things in the list + - **[.lists().add()](https://observablehq.com/@spencermountain/compromise-lists)** - put a new item in the list +- **[.nouns()](https://observablehq.com/@spencermountain/nouns)** - return any subsequent terms tagged as a Noun + - **[.nouns().json()](https://observablehq.com/@spencermountain/nouns)** - overloaded output with noun metadata + - **[.nouns().toPlural()](https://observablehq.com/@spencermountain/nouns)** - `'football captain' → 'football captains'` + - **[.nouns().toSingular()](https://observablehq.com/@spencermountain/nouns)** - `'turnovers' → 'turnover'` + - **[.nouns().isPlural()](https://observablehq.com/@spencermountain/nouns)** - return only plural nouns + - **[.nouns().isSingular()](https://observablehq.com/@spencermountain/nouns)** - return only singular nouns + - **[.nouns().hasPlural()](https://observablehq.com/@spencermountain/nouns)** - return only nouns that _can be_ inflected as plural + - **[.nouns().toPossessive()](https://observablehq.com/@spencermountain/nouns)** - add a `'s` to the end, in a safe manner. +- **[.verbs()](https://observablehq.com/@spencermountain/verbs)** - return any subsequent terms tagged as a Verb + - **[.verbs().json()](https://observablehq.com/@spencermountain/verbs)** - overloaded output with verb metadata + - **[.verbs().conjugate()](https://observablehq.com/@spencermountain/verbs)** - return all forms of these verbs + - **[.verbs().toPastTense()](https://observablehq.com/@spencermountain/verbs)** - `'will go' → 'went'` + - **[.verbs().toPresentTense()](https://observablehq.com/@spencermountain/verbs)** - `'walked' → 'walks'` + - **[.verbs().toFutureTense()](https://observablehq.com/@spencermountain/verbs)** - `'walked' → 'will walk'` + - **[.verbs().toInfinitive()](https://observablehq.com/@spencermountain/verbs)** - `'walks' → 'walk'` + - **[.verbs().toGerund()](https://observablehq.com/@spencermountain/verbs)** - `'walks' → 'walking'` + - **[.verbs().toNegative()](https://observablehq.com/@spencermountain/verbs)** - `'went' → 'did not go'` + - **[.verbs().toPositive()](https://observablehq.com/@spencermountain/verbs)** - `"didn't study" → 'studied'` + - **[.verbs().isNegative()](https://observablehq.com/@spencermountain/verbs)** - return verbs with 'not' + - **[.verbs().isPositive()](https://observablehq.com/@spencermountain/verbs)** - only verbs without 'not' + - **[.verbs().isPlural()](https://observablehq.com/@spencermountain/verbs)** - return plural verbs like 'we walk' + - **[.verbs().isSingular()](https://observablehq.com/@spencermountain/verbs)** - return singular verbs like 'spencer walks' + - **[.verbs().adverbs()](https://observablehq.com/@spencermountain/verbs)** - return the adverbs describing this verb. + +
+ +
+ +### Plugins: + +These are some helpful extensions: + +##### Adjectives + +`npm install compromise-adjectives` + +- **[.adjectives()](https://observablehq.com/@spencermountain/compromise-adjectives)** - like `quick` + - **[.adjectives().json()](https://observablehq.com/@spencermountain/compromise-adjectives)** - overloaded output with adjective metadata + - **[.adjectives().conjugate()](https://observablehq.com/@spencermountain/compromise-adjectives)** - return all conjugated forms of this adjective + - **[.adjectives().toSuperlative()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickest` + - **[.adjectives().toComparative()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickest` + - **[.adjectives().toAdverb()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickly` + - **[.adjectives().toVerb()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quicken` + - **[.adjectives().toNoun()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickness` + +##### Dates + +`npm install compromise-dates` + +- **[.dates()](https://observablehq.com/@spencermountain/compromise-dates)** - find dates like `June 8th` or `03/03/18` + - **[.dates().json()](https://observablehq.com/@spencermountain/compromise-dates)** - overloaded output with date metadata + - **[.dates().format('')](https://observablehq.com/@spencermountain/compromise-dates)** - convert the dates to specific formats + - **[.dates().toShortForm('')](https://observablehq.com/@spencermountain/compromise-dates)** - convert 'Wednesday' to 'Wed', etc + - **[.dates().toLongForm('')](https://observablehq.com/@spencermountain/compromise-dates)** - convert 'Feb' to 'February', etc + +##### Topics + +`npm install compromise-topics` + +- **[.people()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - names like 'John F. Kennedy' +- **[.places()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - like 'Paris, France' +- **[.organizations()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - like 'Google, Inc' +- **[.topics()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - `people()` + `places()` + `organizations()` + +##### Numbers + +`npm install compromise-numbers` + +- **[.numbers()](https://observablehq.com/@spencermountain/compromise-values)** - grab all written and numeric values + - **[.numbers().json()](https://observablehq.com/@spencermountain/compromise-values)** - overloaded output with number metadata + - **[.numbers().units()](https://observablehq.com/@spencermountain/compromise-values)** - grab 'kilos' from `25 kilos'` + - **[.numbers().money()](https://observablehq.com/@spencermountain/compromise-values)** - things like `'$2.50'` + - **[.numbers().fractions()](https://observablehq.com/@spencermountain/compromise-values)** - things like `1/3rd` + - **[.numbers().toText()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `five` or `fifth` + - **[.numbers().toNumber()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `5` or `5th` + - **[.numbers().toOrdinal()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `fifth` or `5th` + - **[.numbers().toCardinal()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `five` or `5` + - **[.numbers().set(n)](https://observablehq.com/@spencermountain/compromise-values)** - set number to n + - **[.numbers().add(n)](https://observablehq.com/@spencermountain/compromise-values)** - increase number by n + - **[.numbers().subtract(n)](https://observablehq.com/@spencermountain/compromise-values)** - decrease number by n + - **[.numbers().increment()](https://observablehq.com/@spencermountain/compromise-values)** - increase number by 1 + - **[.numbers().decrement()](https://observablehq.com/@spencermountain/compromise-values)** - decrease number by 1 + - **[.numbers().isEqual(n)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers with this value + - **[.numbers().greaterThan(min)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers bigger than n + - **[.numbers().lessThan(max)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers smaller than n + - **[.numbers().between(min, max)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers between min and max + - **[.numbers().isOrdinal()](https://observablehq.com/@spencermountain/compromise-values)** - return only ordinal numbers + - **[.numbers().isCardinal()](https://observablehq.com/@spencermountain/compromise-values)** - return only cardinal numbers + - **[.numbers().toLocaleString()](https://observablehq.com/@spencermountain/compromise-values)** - add commas, or nicer formatting for numbers + +##### Ngrams + +`npm install compromise-ngrams` + +- **[.ngrams({})](https://observablehq.com/@spencermountain/compromise-ngram)** - list all repeating sub-phrases, by word-count +- **[.unigrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - n-grams with one word +- **[.bigrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - n-grams with two words +- **[.trigrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - n-grams with three words +- **[.startgrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - n-grams including the first term of a phrase +- **[.endgrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - n-grams including the last term of a phrase +- **[.edgegrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - n-grams including the first or last term of a phrase + +##### Output + +`npm install compromise-output` + +- **[.hash()](#)** - generate an md5 hash from the document+tags +- **[.html({})]()** - generate sanitized html from the document + +##### Paragraphs + +`npm install compromise-paragraphs` +this plugin creates a wrapper around the default sentence objects. + +- **[.paragraphs()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - return groups of sentences + - **[.paragraphs().json()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - output metadata for each paragraph + - **[.paragraphs().sentences()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - go back to a regular Doc object + - **[.paragraphs().terms()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().eq()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().first()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().last()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().match()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().not()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().if()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().ifNo()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().has()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().forEach()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().map()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + - **[.paragraphs().filter()](https://observablehq.com/@spencermountain/compromise-paragraphs)** - + +##### Sentences + +`npm install compromise-sentences` + +- **[.sentences()](#)** - return a sentence class with additional methods + - **[.sentences().json()](#)** - overloaded output with sentence metadata + - **[.sentences().subjects()](#)** - return the main noun of each sentence + - **[.sentences().toPastTense()](#)** - `he walks` -> `he walked` + - **[.sentences().toPresentTense()](#)** - `he walked` -> `he walks` + - **[.sentences().toFutureTense()](#)** -- `he walks` -> `he will walk` + - **[.sentences().toNegative()](#)** - - `he walks` -> `he didn't walk` + - **[.sentences().toPositive()](#)** - `he doesn't walk` -> `he walks` + - **[.sentences().isPassive()](#)** - return only sentences with a passive-voice + - **[.sentences().isQuestion()](#)** - return questions with a `?` + - **[.sentences().isExclamation()](#)** - return sentences with a `!` + - **[.sentences().isStatement()](#)** - return sentences without `?` or `!` + - **[.sentences().prepend()](#)** - smarter prepend that repairs whitespace + titlecasing + - **[.sentences().append()](#)** - smarter append that repairs sentence punctuation + - **[.sentences().toExclamation()](#)** - end sentence with a `!` + - **[.sentences().toQuestion()](#)** - end sentence with a `?` + - **[.sentences().toStatement()](#)** - end sentence with a `.` + + +##### Syllables + +`npm install compromise-syllables` + +- **[.syllables()](https://observablehq.com/@spencermountain/compromise-syllables)** - split each term by its typical pronounciation + + +
+ +
+ +
+ + +
+ +
+ +### Docs: + +##### Tutorials: + +- **[Tutorial #1](https://docs.compromise.cool/tutorial-1)** - Input → output +- **[Tutorial #2](https://docs.compromise.cool/compromise-tutorial-2)** - Match & transform +- **[Tutorial #3](https://docs.compromise.cool/compromise-making-a-bot)** - Making a chat-bot + + +##### 3rd party: + +- **[Geocoding Social Conversations with NLP and JavaScript](http://compromise.cool)** - by Microsoft +- **[Microservice Recipe](https://eventn.com/recipes/text-parsing-with-nlp-compromise)** - by Eventn +- **[Building Text-Based Games](https://killalldefects.com/2019/09/24/building-text-based-games-with-compromise-nlp/)** - by Matt Eland +- **[Fun with javascript in BigQuery](https://medium.com/@hoffa/new-in-bigquery-persistent-udfs-c9ea4100fd83#6e09)** - by Felipe Hoffa + +##### Talks: + +- **[Language as an Interface](https://www.youtube.com/watch?v=WuPVS2tCg8s)** - by Spencer Kelly +- **[Coding Chat Bots](https://www.youtube.com/watch?v=c_hmwFwvO0U)** - by KahWee Teng + +
+
-

+##### Some fun Applications: + +- **[Chat dialogue framework](http://superscriptjs.com/)** - by Rob Ellis +- **[Automated Bechdel Test](https://github.com/guardian/bechdel-test)** - by The Guardian +- **[Story generation framework](https://perchance.org/welcome)** - by Jose Phrocca +- **[Tumbler blog of lists](https://leanstooneside.tumblr.com/)** - horse-ebooks-like lists - by Michael Paulukonis +- **[Video Editing from Transcription](https://newtheory.io/)** - by New Theory +- **[Browser extension Fact-checking](https://github.com/AlexanderKidd/FactoidL)** - by Alexander Kidd +- **[Siri shortcut](https://routinehub.co/shortcut/3260)** - by Michael Byrns +- **[Amazon skill](https://github.com/tajddin/voiceplay)** - by Tajddin Maghni +- **[Tasking Slack-bot](https://github.com/kevinsuh/toki)** - by Kevin Suh + + +
+ +
+
+ +#### Limitations: + +- **slash-support:** + We currently split slashes up as different words, like we do for hyphens. so things like this don't work: + nlp('the koala eats/shoots/leaves').has('koala leaves') //false + +- **inter-sentence match:** + By default, sentences are the top-level abstraction. + Inter-sentence, or multi-sentence matches aren't supported: + nlp("that's it. Back to Winnipeg!").has('it back')//false + +- **nested match syntax:** + the danger beauty of regex is that you can recurse indefinitely. + Our match syntax is much weaker. Things like this are not (yet) possible: + doc.match('(modern (major|minor))? general') + complex matches must be achieved with successive **.match()** statements. + +- **dependency parsing:** + Proper sentence transformation requires understanding the [syntax tree](https://en.wikipedia.org/wiki/Parse_tree) of a sentence, which we don't currently do. + We should! Help wanted with this. + +##### FAQ + -
+
+ +
-### Also: -*   **[naturalNode](https://github.com/NaturalNode/natural)** - fancier statistical nlp in javascript -*   **[superScript](http://superscriptjs.com/)** - clever conversation engine in js -*   **[nodeBox Linguistics](https://www.nodebox.net/code/index.php/Linguistics)** - conjugation, inflection in javascript -*   **[reText](https://github.com/wooorm/retext)** - very impressive [text utilities](https://github.com/wooorm/retext/blob/master/doc/plugins.md) in javascript -*   **[jsPos](https://code.google.com/archive/p/jspos/)** - javascript build of the time-tested Brill-tagger -*   **[spaCy](https://spacy.io/)** - speedy, multilingual tagger in C/python +#### See Also: -For the former promise-library, see [jnewman/compromise](https://github.com/jnewman/compromise) -(Thanks [Joshua](https://github.com/jnewman)!) +-   **[naturalNode](https://github.com/NaturalNode/natural)** - fancier statistical nlp in javascript +-   **[superScript](http://superscriptjs.com/)** - clever conversation engine in js +-   **[nodeBox linguistics](https://www.nodebox.net/code/index.php/Linguistics)** - conjugation, inflection in javascript +-   **[reText](https://github.com/wooorm/retext)** - very impressive [text utilities](https://github.com/wooorm/retext/blob/master/doc/plugins.md) in javascript +-   **[jsPos](https://code.google.com/archive/p/jspos/)** - javascript build of the time-tested Brill-tagger +-   **[spaCy](https://spacy.io/)** - speedy, multilingual tagger in C/python -
-(and don't forget 🙇 -NLTK, -GATE, -Stanford, -and -Illinois libs -) -
+ + +MIT + +
by spencermountain
diff --git a/builds/compromise.es6.js b/builds/compromise.es6.js deleted file mode 100644 index f2f8f5853..000000000 --- a/builds/compromise.es6.js +++ /dev/null @@ -1,14127 +0,0 @@ -/* compromise v11.14.3 - http://compromise.cool - MIT -*/ - -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.nlp = f()}})(function(){var define,module,exports;return (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=e;n-=e,o++,e*=36);for(;o--;){const o=n%36;t=String.fromCharCode((o<10?48:55)+o)+t,n=(n-o)/36}return t},fromAlphaCode=function(n){if(void 0!==cache[n])return cache[n];let o=0,e=1,t=36,r=1;for(;e=0;e--,r*=36){let t=n.charCodeAt(e)-48;t>10&&(t-=7),o+=t*r}return o};var encoding={toAlphaCode:toAlphaCode,fromAlphaCode:fromAlphaCode},symbols=function(n){const o=new RegExp("([0-9A-Z]+):([0-9A-Z]+)");for(let e=0;e{let s=n.nodes[t];"!"===s[0]&&(o.push(r),s=s.slice(1));const c=s.split(/([A-Z0-9,]+)/g);for(let s=0;s{const e=o.split("¦");return n[e[0]]=e[1],n},{}),e={};return Object.keys(o).forEach(function(n){const t=unpack_1(o[n]);"true"===n&&(n=!0);for(let o=0;o (http://spencermounta.in)", - "name": "compromise", - "description": "natural language processing in the browser", - "version": "11.14.3", - "main": "./builds/compromise.js", - "unpkg": "./builds/compromise.min.js", - "types": "types", - "repository": { - "type": "git", - "url": "git://github.com/nlp-compromise/compromise.git" - }, - "scripts": { - "test": "tape \"./test/unit/**/*.test.js\" | tap-dancer", - "test:spec": "tape \"./test/unit/**/*.test.js\" | tap-spec", - "testb": "TESTENV=prod tape \"./test/unit/**/*.test.js\" | tap-dancer", - "buildTest": "TESTENV=prod node ./scripts/test.js", - "test:types": "dtslint types", - "browserTest": "node ./scripts/browserTest.js", - "benchmark": "node ./scripts/benchmark.js", - "build": "node ./scripts/build/index.js", - "pack": "node ./scripts/pack.js", - "prepublishOnly": "node ./scripts/prepublish && npm run test:types", - "postpublish": "node ./scripts/postpublish", - "watch": "amble ./scratch.js", - "filesize": "node ./scripts/lib/filesize.js", - "coverage": "node ./scripts/postpublish/coverage.js", - "lint": "node ./scripts/prepublish/linter.js" - }, - "files": [ - "builds/", - "docs/", - "types/index.d.ts" - ], - "prettier": { - "trailingComma": "none", - "tabWidth": 2, - "semi": true, - "singleQuote": true, - "printWidth": 100 - }, - "dependencies": { - "efrt-unpack": "2.2.0" - }, - "devDependencies": { - "@babel/core": "7.5.5", - "@babel/preset-env": "7.5.5", - "amble": "0.0.7", - "babelify": "10.0.0", - "babili": "0.1.4", - "browserify": "16.5.0", - "chalk": "2.4.2", - "codecov": "3.5.0", - "compromise-plugin": "0.0.9", - "derequire": "2.0.6", - "dtslint": "0.9.3", - "nyc": "14.1.1", - "shelljs": "0.8.3", - "tap-dancer": "0.2.0", - "tape": "4.11.0", - "terser": "4.2.1" - }, - "license": "MIT" -} - -},{}],3:[function(_dereq_,module,exports){ -'use strict'; -const tagset = _dereq_('./tags'); - -// https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color -const c = { - reset: '\x1b[0m', - red: '\x1b[31m', - green: '\x1b[32m', - yellow: '\x1b[33m', - blue: '\x1b[34m', - magenta: '\x1b[35m', - cyan: '\x1b[36m', - black: '\x1b[30m' -}; -//dont use colors on client-side -if (typeof module === 'undefined') { - Object.keys(c).forEach(k => { - c[k] = ''; - }); -} - -//coerce any input into a string -exports.ensureString = input => { - if (typeof input === 'string') { - return input; - } else if (typeof input === 'number') { - return String(input); - } - return ''; -}; -//coerce any input into a string -exports.ensureObject = input => { - if (typeof input !== 'object') { - return {}; - } - if (input === null || input instanceof Array) { - return {}; - } - return input; -}; - -exports.titleCase = str => { - return str.charAt(0).toUpperCase() + str.substr(1); -}; - -//shallow-clone an object -exports.copy = o => { - let o2 = {}; - o = exports.ensureObject(o); - Object.keys(o).forEach(k => { - o2[k] = o[k]; - }); - return o2; -}; -exports.extend = (obj, a) => { - obj = exports.copy(obj); - const keys = Object.keys(a); - for (let i = 0; i < keys.length; i++) { - obj[keys[i]] = a[keys[i]]; - } - return obj; -}; - -//colorization -exports.green = function(str) { - return c.green + str + c.reset; -}; -exports.red = function(str) { - return c.red + str + c.reset; -}; -exports.blue = function(str) { - return c.blue + str + c.reset; -}; -exports.magenta = function(str) { - return c.magenta + str + c.reset; -}; -exports.cyan = function(str) { - return c.cyan + str + c.reset; -}; -exports.yellow = function(str) { - return c.yellow + str + c.reset; -}; -exports.black = function(str) { - return c.black + str + c.reset; -}; -exports.printTag = function(tag) { - if (tagset[tag]) { - const color = tagset[tag].color || 'blue'; - return exports[color](tag); - } - return tag; -}; -exports.printTerm = function(t) { - const tags = Object.keys(t.tags); - for (let i = 0; i < tags.length; i++) { - if (tagset[tags[i]]) { - const color = tagset[tags[i]].color || 'black'; - return exports[color](t.out('text')); - } - } - return c.reset + t.plaintext + c.reset; -}; - -exports.leftPad = function(str, width, char) { - char = char || ' '; - str = str.toString(); - while (str.length < width) { - str += char; - } - return str; -}; - -exports.isArray = function(arr) { - return Object.prototype.toString.call(arr) === '[object Array]'; -}; - -exports.isObject = function(obj) { - return obj === Object(obj); -}; - -},{"./tags":137}],4:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; -const buildText = _dereq_('./text/build'); -const pkg = _dereq_('../package.json'); -const log = _dereq_('./log'); -const unpack = _dereq_('./world/unpack'); -let world = _dereq_('./world'); -let w = world.w; - -//the main function -const nlp = function(str, lex) { - if (lex) { - w.plugin({ - words: lex - }); - } - let doc = buildText(str, w); - doc.tagger(); - return doc; -}; - -//this is used, atleast, for testing the packing -nlp.unpack = function(plugin) { - return unpack(plugin); -}; -//this is handy -nlp.version = pkg.version; -//turn-on some debugging -nlp.verbose = function(str) { - log.enable(str); -}; -//same as main method, except with no POS-tagging. -nlp.tokenize = function(str) { - return buildText(str); -}; - -//uncompress user-submitted lexicon -nlp.plugin = function(plugin) { - w.plugin(plugin); -}; -//contribute words to the lexicon -nlp.addWords = function(lex) { - w.plugin({ - words: lex - }); -}; -nlp.addTags = function(tags) { - w.plugin({ - tags: tags - }); -}; -nlp.addRegex = function(regex) { - w.plugin({ - regex: regex - }); -}; -nlp.addPatterns = function(patterns) { - w.plugin({ - patterns: patterns - }); -}; -nlp.addPlurals = function(plurals) { - w.plugin({ - plurals: plurals - }); -}; -nlp.addConjugations = function(conj) { - w.plugin({ - conjugations: conj - }); -}; - -//make a weird, half-copy of this method -nlp.clone = function() { - let w2 = world.reBuild(); - //this is weird, but it's okay - var nlp2 = function(str, lex) { - if (lex) { - w2.plugin({ - words: lex - }); - } - let doc = buildText(str, w2); - doc.tagger(); - return doc; - }; - nlp2.tokenize = nlp.tokenize; - nlp2.verbose = nlp.verbose; - nlp2.version = nlp.version; - ['Words', 'Tags', 'Regex', 'Patterns', 'Plurals', 'Conjugations'].forEach((fn) => { - nlp2['add' + fn] = function(obj) { - w2['add' + fn](obj); - }; - }); - return nlp2; -}; - -//and then all-the-exports... -if (typeof self !== 'undefined') { - self.nlp = nlp; // Web Worker -} else if (typeof window !== 'undefined') { - window.nlp = nlp; // Browser -} else if (typeof global !== 'undefined') { - global.nlp = nlp; // NodeJS -} -//don't forget amd! -if (typeof define === 'function' && define.amd) { - define(nlp); -} -//then for some reason, do this too! -if (typeof module !== 'undefined') { - module.exports = nlp; -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../package.json":2,"./log":6,"./text/build":190,"./world":215,"./world/unpack":223}],5:[function(_dereq_,module,exports){ -'use strict'; -const fns = _dereq_('../fns'); - -// const colors = { -// 'Person': '#6393b9', -// 'Pronoun': '#81acce', -// 'Noun': 'steelblue', -// 'Verb': 'palevioletred', -// 'Adverb': '#f39c73', -// 'Adjective': '#b3d3c6', -// 'Determiner': '#d3c0b3', -// 'Preposition': '#9794a8', -// 'Conjunction': '#c8c9cf', -// 'Value': 'palegoldenrod', -// 'Expression': '#b3d3c6' -// }; - -const tag = (t, pos, reason) => { - let title = t.normal || '[' + t.silent_term + ']'; - title = fns.leftPad('\'' + title + '\'', 12); - title += ' -> ' + pos; - title += fns.leftPad((reason || ''), 15); - console.log('%c' + title, ' color: #a2c99c'); -}; -const untag = (t, pos, reason) => { - let title = t.normal || '[' + t.silent_term + ']'; - title = fns.leftPad('\'' + title + '\'', 12); - title += ' ~* ' + pos; - title += ' ' + (reason || ''); - console.log('%c' + title, ' color: #b66a6a'); -}; -module.exports = { - tag: tag, - untag: untag, -}; - -},{"../fns":3}],6:[function(_dereq_,module,exports){ -'use strict'; -const client = _dereq_('./client'); -const server = _dereq_('./server'); - -let enable = false; - -module.exports = { - enable: (str) => { - if (str === undefined) { - str = true; - } - enable = str; - }, - tag: (t, pos, reason) => { - if (enable === true || enable === 'tagger') { - if (typeof window !== 'undefined') { - client.tag(t, pos, reason); - } else { - server.tag(t, pos, reason); - } - } - }, - unTag: (t, pos, reason) => { - if (enable === true || enable === 'tagger') { - if (typeof window !== 'undefined') { - client.untag(t, pos, reason); - } else { - server.untag(t, pos, reason); - } - } - } -}; - -},{"./client":5,"./server":7}],7:[function(_dereq_,module,exports){ -'use strict'; -const fns = _dereq_('../fns'); - -//use weird bash escape things for some colors -const tag = (t, pos, reason) => { - let title = t.normal || '[' + t.silent_term + ']'; - title = fns.yellow(title); - title = fns.leftPad('\'' + title + '\'', 20); - title += ' -> ' + fns.printTag(pos); - title = fns.leftPad(title, 54); - console.log(' ' + title + '(' + fns.cyan(reason || '') + ')'); -}; - -const untag = function(t, pos, reason) { - let title = '-' + t.normal + '-'; - title = fns.red(title); - title = fns.leftPad(title, 20); - title += ' ~* ' + fns.red(pos); - title = fns.leftPad(title, 54); - console.log(' ' + title + '(' + fns.red(reason || '') + ')'); -}; - -module.exports = { - tag: tag, - untag: untag, -}; - -},{"../fns":3}],8:[function(_dereq_,module,exports){ -module.exports = { - fns: _dereq_('./fns'), - Terms: _dereq_('./terms'), -}; - -},{"./fns":3,"./terms":165}],9:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -//the Acronym() subset class - -const methods = { - stripPeriods: function() { - this.list.forEach((ts) => { - ts.terms.forEach((t) => { - let chars = t._text.split('.'); - if (chars.length > 2) { - t.text = chars.join(''); - } - }); - }); - return this; - }, - addPeriods: function() { - this.list.forEach((ts) => { - ts.terms.forEach((t) => { - let chars = t._text.split('.'); - if (chars.length > 2) { - let str = t._text.replace(/\./g, ''); - t.text = str.split('').join('.') + '.'; - } - }); - }); - return this; - }, - data: function() { - return this.terms().list.map(ts => { - let t = ts.terms[0]; - let parsed = t.text - .toUpperCase() - .replace(/\./g, '') - .split(''); - return { - periods: parsed.join('.'), - normal: parsed.join(''), - text: t.text - }; - }); - } -}; - -const find = function(r, n) { - r = r.match('#Acronym'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192}],10:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const fns = _dereq_('./methods'); -//the Adjectives() subset class - -//is this an adjective we want to goof-around with? -const shouldConvert = function(str, words) { - if (!str || str.length <= 3) { - return false; - } - if (words[str] === 'Comparable') { - return true; - } - if (words[str] === 'Adjective') { - return false; - } - //has space - if (str.indexOf(' ') !== -1) { - return false; - } - return true; -}; - -const methods = { - data: function() { - return this.list.map(ts => { - const str = ts.out('normal'); - let obj = { - normal: str, - text: this.out('text'), - comparative: 'more ' + str, - superlative: 'most ' + str, - adverbForm: null, - nounForm: null - // verbForm: null - }; - if (shouldConvert(str, this.world().words) === true) { - obj.comparative = fns.toComparative(str) || obj.comparative; - obj.superlative = fns.toSuperlative(str) || obj.superlative; - obj.adverbForm = fns.toAdverb(str); - obj.nounForm = fns.toNoun(str); - // obj.verbForm = fns.toVerb(str); - } - return obj; - }); - } -}; - -const find = function(r, n) { - r = r.match('#Adjective'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./methods":11}],11:[function(_dereq_,module,exports){ -'use strict'; -module.exports = { - toNoun: _dereq_('./toNoun'), - toSuperlative: _dereq_('./toSuperlative'), - toComparative: _dereq_('./toComparative'), - toAdverb: _dereq_('./toAdverb'), - toVerb: _dereq_('./toVerb') -}; - -},{"./toAdverb":12,"./toComparative":13,"./toNoun":14,"./toSuperlative":15,"./toVerb":16}],12:[function(_dereq_,module,exports){ -//turn 'quick' into 'quickly' -'use strict'; -const not_matches = [/airs$/, /ll$/, /ee.$/, /ile$/, /y$/]; -const irregulars = _dereq_('../../../world/more-data/irregularAdjectives').toAdverb; - -const transforms = [ - { - reg: /al$/i, - repl: 'ally' - }, - { - reg: /ly$/i, - repl: 'ly' - }, - { - reg: /(.{3})y$/i, - repl: '$1ily' - }, - { - reg: /que$/i, - repl: 'quely' - }, - { - reg: /ue$/i, - repl: 'uly' - }, - { - reg: /ic$/i, - repl: 'ically' - }, - { - reg: /ble$/i, - repl: 'bly' - }, - { - reg: /l$/i, - repl: 'ly' - } -]; - -const adj_to_adv = function(str) { - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - for (let i = 0; i < not_matches.length; i++) { - if (not_matches[i].test(str) === true) { - return null; - } - } - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - return str + 'ly'; -}; -// console.log(adj_to_adv('good')); - -module.exports = adj_to_adv; - -},{"../../../world/more-data/irregularAdjectives":218}],13:[function(_dereq_,module,exports){ -//turn 'quick' into 'quickly' -'use strict'; -const do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /old$/, /oud$/, /e[ae]p$/]; -const dont_rules = [/ary$/, /ous$/]; -const irregulars = _dereq_('../../../world/more-data/irregularAdjectives').toComparative; - -const transforms = [ - { - reg: /y$/i, - repl: 'ier' - }, - { - reg: /([aeiou])t$/i, - repl: '$1tter' - }, - { - reg: /([aeou])de$/i, - repl: '$1der' - }, - { - reg: /nge$/i, - repl: 'nger' - } -]; - -const to_comparative = function(str) { - //known-irregulars - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - //known-transforms - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - //dont-patterns - for (let i = 0; i < dont_rules.length; i++) { - if (dont_rules[i].test(str) === true) { - return null; - } - } - //do-patterns - for (let i = 0; i < do_rules.length; i++) { - if (do_rules[i].test(str) === true) { - return str + 'er'; - } - } - //easy-one - if (/e$/.test(str) === true) { - return str + 'r'; - } - return str + 'er'; -// return null; -}; - -// console.log(to_comparative('big')); - -module.exports = to_comparative; - -},{"../../../world/more-data/irregularAdjectives":218}],14:[function(_dereq_,module,exports){ -'use strict'; -//convert 'cute' to 'cuteness' -const irregulars = { - clean: 'cleanliness', - naivety: 'naivety', - hurt: 'hurt' -}; - -const transforms = [ - { - reg: /y$/, - repl: 'iness' - }, - { - reg: /le$/, - repl: 'ility' - }, - { - reg: /ial$/, - repl: 'y' - }, - { - reg: /al$/, - repl: 'ality' - }, - { - reg: /ting$/, - repl: 'ting' - }, - { - reg: /ring$/, - repl: 'ring' - }, - { - reg: /bing$/, - repl: 'bingness' - }, - { - reg: /sing$/, - repl: 'se' - }, - { - reg: /ing$/, - repl: 'ment' - }, - { - reg: /ess$/, - repl: 'essness' - }, - { - reg: /ous$/, - repl: 'ousness' - } -]; - -const to_noun = function(w) { - if (irregulars.hasOwnProperty(w)) { - return irregulars[w]; - } - const lastChar = w.charAt(w.length - 1); - if (lastChar === 'w' || lastChar === 's') { - return null; - } - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(w) === true) { - return w.replace(transforms[i].reg, transforms[i].repl); - } - } - return w + 'ness'; -}; - -module.exports = to_noun; -// console.log(to_noun("great")) - -},{}],15:[function(_dereq_,module,exports){ -//turn 'quick' into 'quickest' -'use strict'; -const do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /oud$/, /...p$/]; -const dont_rules = [/ary$/]; -const irregulars = _dereq_('../../../world/more-data/irregularAdjectives').toSuperlative; - -const transforms = [ - { - reg: /y$/i, - repl: 'iest' - }, - { - reg: /([aeiou])t$/i, - repl: '$1ttest' - }, - { - reg: /([aeou])de$/i, - repl: '$1dest' - }, - { - reg: /nge$/i, - repl: 'ngest' - }, - { - reg: /([aeiou])te$/i, - repl: '$1test' - } -]; - -const to_superlative = function(str) { - //irregulars - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - //known transforms - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str)) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - //dont-rules - for (let i = 0; i < dont_rules.length; i++) { - if (dont_rules[i].test(str) === true) { - return null; - } - } - //do-rules - for (let i = 0; i < do_rules.length; i++) { - if (do_rules[i].test(str) === true) { - if (str.charAt(str.length - 1) === 'e') { - return str + 'st'; - } - return str + 'est'; - } - } - return str + 'est'; -}; - -module.exports = to_superlative; -// console.log(to_superlative("great")) - -},{"../../../world/more-data/irregularAdjectives":218}],16:[function(_dereq_,module,exports){ -'use strict'; -//turn an adjective like 'soft' into a verb like 'soften' -//(don't do words like 'green' -> 'greenen') - -const irregulars = { - red: 'redden', - sad: 'sadden', - fat: 'fatten' -}; - -const toVerb = str => { - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - if (/e$/.test(str) === true) { - return str + 'n'; - } - return str + 'en'; -}; -module.exports = toVerb; - -},{}],17:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const toAdjective = _dereq_('./toAdjective'); - -//the () subset class - -const methods = { - data: function() { - return this.terms().list.map(ts => { - let t = ts.terms[0]; - return { - adjectiveForm: toAdjective(t.normal), - normal: t.normal, - text: t.text - }; - }); - } -}; - -const find = function(r, n) { - r = r.splitAfter('#Comma'); - r = r.match('#Adverb+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./toAdjective":18}],18:[function(_dereq_,module,exports){ -//turns 'quickly' into 'quick' -'use strict'; -const irregulars = { - 'idly': 'idle', - 'sporadically': 'sporadic', - 'basically': 'basic', - 'grammatically': 'grammatical', - 'alphabetically': 'alphabetical', - 'economically': 'economical', - 'conically': 'conical', - 'politically': 'political', - 'vertically': 'vertical', - 'practically': 'practical', - 'theoretically': 'theoretical', - 'critically': 'critical', - 'fantastically': 'fantastic', - 'mystically': 'mystical', - 'pornographically': 'pornographic', - 'fully': 'full', - 'jolly': 'jolly', - 'wholly': 'whole' -}; - -const transforms = [{ - 'reg': /bly$/i, - 'repl': 'ble' -}, { - 'reg': /gically$/i, - 'repl': 'gical' -}, { - 'reg': /([rsdh])ically$/i, - 'repl': '$1ical' -}, { - 'reg': /ically$/i, - 'repl': 'ic' -}, { - 'reg': /uly$/i, - 'repl': 'ue' -}, { - 'reg': /ily$/i, - 'repl': 'y' -}, { - 'reg': /(.{3})ly$/i, - 'repl': '$1' -}]; - -const toAdjective = function(str) { - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - return str; -}; - -// console.log(toAdjective('quickly')) -module.exports = toAdjective; - -},{}],19:[function(_dereq_,module,exports){ -'use strict'; - -//the plumbing to turn two words into a contraction -const combine = (a, b) => { - b.whitespace.after = a.whitespace.after; - a.whitespace.after = ''; - b.whitespace.before = ''; - a.silent_term = a.text; - b.silent_term = b.text; - b.text = ''; - a.tag('Contraction', 'new-contraction'); - b.tag('Contraction', 'new-contraction'); -}; - -const irregulars = { - can: 'can\'t', - will: 'won\'t' -}; - -const contract = function(ts) { - if (ts.expanded === false || ts.match('#Contraction').found) { - return ts; - } - //he is -> he's - ts.match('(#Noun|#QuestionWord) is').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'s'; - ls.contracted = true; - }); - //he did -> he'd - ts.match('#PronNoun did').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); - //how do -> how'd - ts.match('#QuestionWord (did|do)').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); - //he would -> he'd - ts.match('#Noun (could|would)').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); - //they are -> they're - ts.match('(they|we|you) are').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'re'; - ls.contracted = true; - }); - //i am -> i'm - ts.match('i am').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'m'; - ls.contracted = true; - }); - //they will -> they'll - ts.match('(#Noun|#QuestionWord) will').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'ll'; - ls.contracted = true; - }); - //they have -> they've - ts.match('(they|we|you|i) have').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'ve'; - ls.contracted = true; - }); - //is not -> isn't - ts.match('(#Copula|#Modal|do|does|have|has|can|will) not').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - //can't, won't - if (irregulars.hasOwnProperty(ls.terms[0].text) === true) { - ls.terms[0].text = irregulars[ls.terms[0].text]; - } else { - ls.terms[0].text += 'n\'t'; - } - ls.contracted = true; - }); - return ts; -}; - -module.exports = contract; - -},{}],20:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../paths').Terms; -const contract = _dereq_('./contract'); -const expand = _dereq_('./expand'); - -const ContractionCl = function(arr, world, original) { - Terms.call(this, arr, world, original); -}; - -//Inherit properties -ContractionCl.prototype = Object.create(Terms.prototype); - -ContractionCl.prototype.data = function() { - let expanded = expand(this.clone()); - let contracted = contract(this.clone()); - return { - text: this.out('text'), - normal: this.out('normal'), - expanded: { - normal: expanded.out('normal'), - text: expanded.out('text') - }, - contracted: { - normal: contracted.out('normal'), - text: contracted.out('text') - }, - isContracted: Boolean(this.contracted) - }; -}; -ContractionCl.prototype.expand = function() { - return expand(this); -}; -ContractionCl.prototype.contract = function() { - return contract(this); -}; -module.exports = ContractionCl; - -},{"../../paths":8,"./contract":19,"./expand":21}],21:[function(_dereq_,module,exports){ -'use strict'; -//turn `i'd` into `i would` -const expand = function(ts) { - if (ts.contracted === false) { - return ts; - } - ts.terms.forEach((t) => { - if (t.silent_term) { - //this term also needs a space now too - if (!t.text) { - t.whitespace.before = ' '; - } - t._text = t.silent_term; - //handle (some) capitalization - if (t.tags.TitleCase) { - t.toTitleCase(); - } - t.normalize(); - t.silent_term = null; - t.unTag('Contraction', 'expanded'); - } - }); - return ts; -}; -module.exports = expand; - -},{}],22:[function(_dereq_,module,exports){ -'use strict'; -//find contractable, expanded-contractions -const find = (r) => { - let remain = r.not('#Contraction'); - let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)'); - m.concat(remain.match('(they|we|you|i) have')); - m.concat(remain.match('i am')); - m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')); - m.list.forEach((ts) => { - ts.expanded = true; - }); - return m; -}; -module.exports = find; - -},{}],23:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const ContractionCl = _dereq_('./contraction'); -const findPossible = _dereq_('./findPossible'); -//the Contractions() subset class - -const methods = { - contract: function() { - this.list.forEach(ts => ts.contract()); - return this; - }, - expand: function() { - this.list.forEach(ts => ts.expand()); - return this; - }, - contracted: function() { - this.list = this.list.filter(ts => { - return ts.contracted; - }); - return this; - }, - expanded: function() { - this.list = this.list.filter(ts => { - return !ts.contracted; - }); - return this; - } -}; - -const find = function(r, n) { - //find currently-contracted - let found = r.match('#Contraction #Contraction #Contraction?'); - found.list = found.list.map(ts => { - let c = new ContractionCl(ts.terms, ts.world, ts.refText, ts.refTerms); - c.contracted = true; - return c; - }); - //find currently-expanded - let expanded = findPossible(r); - expanded.list.forEach(ts => { - let c = new ContractionCl(ts.terms, ts.world, ts.refText, ts.refTerms); - c.contracted = false; - found.list.push(c); - }); - found.sort('chronological'); - //get nth element - if (typeof n === 'number') { - found = found.get(n); - } - return found; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./contraction":20,"./findPossible":22}],24:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../paths').Terms; -const parseDate = _dereq_('./parseDate'); - -const _Date = function(arr, world, refText) { - Terms.call(this, arr, world, refText); - this.month = this.match('#Month'); -}; - -//Inherit properties -_Date.prototype = Object.create(Terms.prototype); - -_Date.prototype.data = function() { - return { - text: this.out('text'), - normal: this.out('normal'), - date: parseDate(this) - }; -}; - -module.exports = _Date; - -},{"../../paths":8,"./parseDate":28}],25:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const Date = _dereq_('./date'); -const weekdays = _dereq_('./weekday'); -const months = _dereq_('./month'); -//the Dates() subset class -const methods = { - toShortForm: function() { - this.match('#Month') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - months.toShortForm(t); - }); - this.match('#WeekDay') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - weekdays.toShortForm(t); - }); - return this; - }, - toLongForm: function() { - this.match('#Month') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - months.toLongForm(t); - }); - this.match('#WeekDay') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - weekdays.toLongForm(t); - }); - return this; - } -}; - -const find = function(r, n) { - let dates = r.match('#Date+'); - if (typeof n === 'number') { - dates = dates.get(n); - } - dates.list = dates.list.map(ts => { - return new Date(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return dates; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./date":24,"./month":27,"./weekday":31}],26:[function(_dereq_,module,exports){ -//follow the javascript scheme -//january is 0 -exports.longMonths = { - 'january': 0, - 'february': 1, - 'march': 2, - 'april': 3, - 'may': 4, - 'june': 5, - 'july': 6, - 'august': 7, - 'september': 8, - 'october': 9, - 'november': 10, - 'december': 11, -}; -exports.shortMonths = { - 'jan': 0, - 'feb': 1, - 'mar': 2, - 'apr': 3, - 'may': 4, - 'jun': 5, - 'jul': 6, - 'aug': 7, - 'sep': 8, - 'oct': 9, - 'nov': 10, - 'dec': 11, - //extra ones - 'febr': 1, - 'sept': 8, -}; - -},{}],27:[function(_dereq_,module,exports){ -'use strict'; -const data = _dereq_('./data'); -const shortMonths = data.shortMonths; -const longMonths = data.longMonths; -const titleCase = str => { - return str.charAt(0).toUpperCase() + str.substr(1); -}; -module.exports = { - index: function (t) { - if (t.tags.Month) { - if (longMonths[t.normal] !== undefined) { - return longMonths[t.normal]; - } - if (shortMonths[t.normal] !== undefined) { - return shortMonths[t.normal]; - } - } - return null; - }, - toShortForm: function (t) { - if (t.tags.Month !== undefined) { - if (longMonths[t.normal] !== undefined) { - let shorten = Object.keys(shortMonths); - let punct = t.getPunctuation() || ''; - t.text = shorten[longMonths[t.normal]] + punct; - if (t.tags.TitleCase) { - t.text = titleCase(t.text); - } - } - } - t.dirty = true; - return t; - }, - toLongForm: function (t) { - if (t.tags.Month !== undefined) { - if (shortMonths[t.normal] !== undefined) { - let longer = Object.keys(longMonths); - let punct = t.getPunctuation() || ''; - t.text = longer[shortMonths[t.normal]] + punct; - if (t.tags.TitleCase) { - t.text = titleCase(t.text); - } - } - } - t.dirty = true; - return t; - } - -}; - -},{"./data":26}],28:[function(_dereq_,module,exports){ -'use strict'; -const parseTime = _dereq_('./parseTime'); -const weekdays = _dereq_('./weekday'); -const months = _dereq_('./month'); -//a hugely-conservative and incomplete first-pass for parsing written-dates - -//validate a day-of-month -const isDate = (num) => { - if (num && num < 31 && num > 0) { - return true; - } - return false; -}; - -//please change this in one thousand years -const isYear = (num) => { - if (num && num > 1000 && num < 3000) { - return true; - } - return false; -}; - -// -const parseDate = (r) => { - let result = { - month: null, - date: null, - weekday: null, - year: null, - named: null, - time: null, - }; - let m = r.match('(#Holiday|today|tomorrow|yesterday)'); - if (m.found) { - result.named = m.out('normal'); - } - m = r.match('#Month'); - if (m.found) { - result.month = months.index(m.list[0].terms[0]); - } - m = r.match('#WeekDay'); - if (m.found) { - result.weekday = weekdays.index(m.list[0].terms[0]); - } - m = r.match('#Time'); - if (m.found) { - result.time = parseTime(r); - r.not('#Time'); //unsure - } - //january fifth 1992 - m = r.match('#Month #Value #Year'); - if (m.found) { - let numbers = m.values().numbers(); - if (isDate(numbers[0])) { - result.date = numbers[0]; - } - let year = parseInt(r.match('#Year').out('normal'), 10); - if (isYear(year)) { - result.year = year; - } - } - if (!m.found) { - //january fifth, january 1992 - m = r.match('#Month #Value'); - if (m.found) { - let numbers = m.values().numbers(); - let num = numbers[0]; - if (isDate(num)) { - result.date = num; - } - } - //january 1992 - m = r.match('#Month #Year'); - if (m.found) { - let num = parseInt(r.match('#Year').out('normal'), 10); - if (isYear(num)) { - result.year = num; - } - } - } - - //fifth of january - m = r.match('#Value of #Month'); - if (m.found) { - let num = m.values().numbers()[0]; - if (isDate(num)) { - result.date = num; - } - } - return result; -}; -module.exports = parseDate; - -},{"./month":27,"./parseTime":29,"./weekday":31}],29:[function(_dereq_,module,exports){ -'use strict'; -const ampm = /([12]?[0-9]) ?(am|pm)/i; -const hourMin = /([12]?[0-9]):([0-9][0-9]) ?(am|pm)?/i; -// -const isHour = (num) => { - if (num && num > 0 && num < 25) { - return true; - } - return false; -}; -const isMinute = (num) => { - if (num && num > 0 && num < 60) { - return true; - } - return false; -}; - - -const parseTime = (r) => { - let result = { - logic: null, - hour: null, - minute: null, - second: null, - timezone: null - }; - - let logic = r.match('(by|before|for|during|at|until|after) #Time').firstTerm(); - if (logic.found) { - result.logic = logic.out('normal'); - } - - let time = r.match('#Time'); - time.terms().list.forEach((ts) => { - let t = ts.terms[0]; - //3pm - let m = t.text.match(ampm); - if (m !== null) { - result.hour = parseInt(m[1], 10); - if (m[2] === 'pm') { - result.hour += 12; - } - if (isHour(result.hour) === false) { - result.hour = null; - } - } - //3:15 - m = t.text.match(hourMin); - if (m !== null) { - result.hour = parseInt(m[1], 10); - result.minute = parseInt(m[2], 10); - if (!isMinute(result.minute)) { - result.minute = null; - } - if (m[3] === 'pm') { - result.hour += 12; - } - if (isHour(result.hour) === false) { - result.hour = null; - } - } - }); - return result; -}; -module.exports = parseTime; - -},{}],30:[function(_dereq_,module,exports){ -//follow the javascript scheme -//sunday is 0 -exports.longDays = { - 'sunday': 0, - 'monday': 1, - 'tuesday': 2, - 'wednesday': 3, - 'thursday': 4, - 'friday': 5, - 'saturday': 6, -}; -exports.shortDays = { - 'sun': 0, - 'mon': 1, - 'tues': 2, - 'wed': 3, - 'weds': 3, - 'thurs': 4, - 'fri': 5, - 'sat': 6, -}; - -},{}],31:[function(_dereq_,module,exports){ -'use strict'; -const data = _dereq_('./data'); -const shortDays = data.shortDays; -const longDays = data.longDays; - -module.exports = { - index: function (t) { - if (t.tags.WeekDay) { - if (longDays[t.normal] !== undefined) { - return longDays[t.normal]; - } - if (shortDays[t.normal] !== undefined) { - return shortDays[t.normal]; - } - } - return null; - }, - toShortForm: function (t) { - if (t.tags.WeekDay) { - if (longDays[t.normal] !== undefined) { - let shorten = Object.keys(shortDays); - t.text = shorten[longDays[t.normal]]; - } - } - return t; - }, - toLongForm: function (t) { - if (t.tags.WeekDay) { - if (shortDays[t.normal] !== undefined) { - let longer = Object.keys(longDays); - t.text = longer[shortDays[t.normal]]; - } - } - return t; - } -}; - -},{"./data":30}],32:[function(_dereq_,module,exports){ -'use strict'; -const Ngrams = _dereq_('./index'); -const getGrams = _dereq_('./getGrams'); - -//like an n-gram, but only the endings of matches -const EndGrams = function(arr, world, original) { - Ngrams.call(this, arr, world, original); -}; - -//Inherit properties -EndGrams.prototype = Object.create(Ngrams.prototype); - -//like an n-gram, but only the startings of matches -EndGrams.find = function(r, n, size) { - let opts = { - size: [1, 2, 3, 4], - edge: 'end' - }; - //only look for bigrams, for example - if (size) { - opts.size = [size]; - } - //fetch them - let arr = getGrams(r, opts); - r = new EndGrams(arr); - //default sort - r.sort(); - //grab top one, or something - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; -module.exports = EndGrams; - -},{"./getGrams":33,"./index":35}],33:[function(_dereq_,module,exports){ -'use strict'; -const Gram = _dereq_('./gram'); - -//strip contractions - remove '' term for "it's" -const noEmpty = function(fts) { - return fts = fts.terms.filter((t) => t._text !== ''); -}; - -//do all grams of one size, on one termList -const getGrams = function(fts, n) { - let terms = noEmpty(fts); - if (terms.length < n) { - return []; - } - let arr = []; - for(let i = 0; i < terms.length - n + 1; i++) { - let gram = new Gram(terms.slice(i, i + n)); - arr.push(gram); - } - return arr; -}; - -//left-sided grams -const startGram = function(fts, n) { - let terms = noEmpty(fts); - if (terms.length < n) { - return []; - } - let arr = [ - new Gram(terms.slice(0, n)), - ]; - return arr; -}; - -//right-sided grams -const endGram = function(fts, n) { - let terms = noEmpty(fts); - if (terms.length < n) { - return []; - } - let arr = [ - new Gram(terms.slice(terms.length - n, terms.length)) - ]; - return arr; -}; - -//ngrams are consecutive terms of a specific size -const buildGrams = function(r, options) { - options = options || {}; - options.size = options.size || [1, 2, 3]; - if (typeof options.size === 'number') { - options.size = [options.size]; - } - let obj = {}; - //collect and count all grams - options.size.forEach((size) => { - r.list.forEach((ts) => { - let newGrams = []; - if (options.edge === 'start') { - newGrams = startGram(ts, size); - } else if (options.edge === 'end') { - newGrams = endGram(ts, size); - } else { - newGrams = getGrams(ts, size); - } - newGrams.forEach((g) => { - if (obj.hasOwnProperty(g.key)) { - obj[g.key].inc(); - } else { - obj[g.key] = g; - } - }); - }); - }); - - //flatten to an array - let arr = Object.keys(obj).map((k) => obj[k]); - return arr; -}; - -module.exports = buildGrams; - -},{"./gram":34}],34:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../paths').Terms; - -//this is one-or-more terms together, sorted by frequency -const Gram = function(arr, world, original) { - Terms.call(this, arr, world, original); - //string to sort/uniq by - this.key = this.out('normal'); - //bigram/trigram/etc - this.size = arr.length; - //number of occurances - this.count = 1; -}; - -//Inherit properties -Gram.prototype = Object.create(Terms.prototype); - -Gram.prototype.inc = function() { - this.count += 1; -}; - -module.exports = Gram; - -},{"../../paths":8}],35:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const getGrams = _dereq_('./getGrams'); - -const sort = function(r) { - r.list = r.list.sort((a, b) => { - if (a.count > b.count) { - return -1; - } - //(tie-braker) - if (a.count === b.count && (a.size > b.size || a.key.length > b.key.length)) { - return -1; - } - return 1; - }); - return r; -}; - -//the Ngrams() subset class -const methods = { - data: function() { - return this.list.map(ts => { - return { - normal: ts.out('normal'), - count: ts.count, - size: ts.size - }; - }); - }, - unigrams: function() { - this.list = this.list.filter(g => g.size === 1); - return this; - }, - bigrams: function() { - this.list = this.list.filter(g => g.size === 2); - return this; - }, - trigrams: function() { - this.list = this.list.filter(g => g.size === 3); - return this; - }, - //default sort the ngrams - sort: function() { - return sort(this); - } -}; - -const find = function(r, obj) { - let sizes = []; - //support .ngrams(3), for compat - if (typeof obj === 'number') { - obj = { - n: obj - }; - } - obj = obj || {}; - let max = obj.max || 4; - for (let i = 1; i <= max; i++) { - sizes.push(i); - } - //only look for bigrams, for example - if (obj.size) { - sizes = [obj.size]; - } - let opts = { - size: sizes - }; - //fetch them - let arr = getGrams(r, opts); - r = new Text(arr); - //default sort - r = sort(r); - //grab top one, or something - if (obj.n !== undefined) { - r = r.get(obj.n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./getGrams":33}],36:[function(_dereq_,module,exports){ -'use strict'; -const Ngrams = _dereq_('./index'); -const getGrams = _dereq_('./getGrams'); - -const StartGrams = function(arr, world, original) { - Ngrams.call(this, arr, world, original); -}; - -//Inherit properties -StartGrams.prototype = Object.create(Ngrams.prototype); - -//like an n-gram, but only the startings of matches -StartGrams.find = function(r, n, size) { - let opts = { - size: [1, 2, 3, 4], - edge: 'start' - }; - //only look for bigrams, for example - if (size) { - opts.size = [size]; - } - //fetch them - let arr = getGrams(r, opts); - r = new StartGrams(arr); - //default sort - r.sort(); - //grab top one, or something - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = StartGrams; - -},{"./getGrams":33,"./index":35}],37:[function(_dereq_,module,exports){ -'use strict'; - -//certain words can't be plural, like 'peace' -const hasPlural = function(t) { - //end quick - if (!t.tags.Noun) { - return false; - } - if (t.tags.Plural) { - return true; - } - //is it potentially plural? - const noPlural = ['Pronoun', 'Place', 'Value', 'Person', 'Month', 'WeekDay', 'RelativeDay', 'Holiday']; - for (let i = 0; i < noPlural.length; i++) { - if (t.tags[noPlural[i]]) { - return false; - } - } - //terms known as un-inflectable, like 'peace' - if (t.tags.Uncountable === true) { - return false; - } - return true; -}; - -module.exports = hasPlural; - -},{}],38:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const Noun = _dereq_('./noun'); - -//the () subset class -const methods = { - isPlural: function() { - this.list = this.list.filter(ts => ts.isPlural()); - return this; - }, - hasPlural: function() { - return this.list.map(ts => ts.hasPlural()); - }, - toPlural: function() { - this.list.forEach(ts => ts.toPlural()); - return this; - }, - toSingular: function(verbose) { - this.list.forEach(ts => ts.toSingular(verbose)); - return this; - }, - toPossessive: function(verbose) { - this.list.forEach(ts => ts.toPossessive(verbose)); - return this; - }, - articles: function() { - return this.list.map(ts => { - return { - text: ts.out('text'), - normal: ts.out('normal'), - article: ts.article() - }; - }); - - } -}; - -const find = function(r, n) { - r = r.clauses(); - r = r.match('#Noun+ (of|by)? the? #Noun+?'); - //nouns that we don't want in these results, for weird reasons - r = r.not('#Pronoun'); - r = r.not('(there|these)'); - r = r.not('(#Month|#WeekDay)'); //allow Durations, Holidays - // //allow possessives like "spencer's", but not generic ones like, - r = r.not('(my|our|your|their|her|his)'); - r = r.not('(of|for|by|the)$'); - if (typeof n === 'number') { - r = r.get(n); - } - r.list = r.list.map(ts => { - return new Noun(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./noun":46}],39:[function(_dereq_,module,exports){ -'use strict'; -const rules = _dereq_('./methods/data/indicators'); -const prep = /([a-z]*) (of|in|by|for) [a-z]/; -const hasPlural = _dereq_('./hasPlural'); - -const knownPlural = { - i: false, - he: false, - she: false, - we: true, - they: true -}; - -//is it potentially plural? -const noPlural = ['Place', 'Value', 'Person', 'Month', 'WeekDay', 'RelativeDay', 'Holiday', 'Possessive']; -//first, try to guess based on existing tags -const couldEvenBePlural = function(t) { - if (hasPlural(t) === false) { - return false; - } - for (let i = 0; i < noPlural.length; i++) { - if (t.tags[noPlural[i]]) { - return false; - } - } - return true; -}; - -/** returns true, false, or null */ -const isPlural = function(t, world) { - if (t.tags.Plural) { - return true; - } - if (t.tags.Singular) { - return false; - } - let str = t.normal; - //whitelist a few easy ones - if (knownPlural.hasOwnProperty(str) === true) { - return knownPlural[str]; - } - //check given irregulars - if (world.plurals && world.plurals.hasOwnProperty(str) === true) { - return false; - } - //check opposite-ones - if (world.cache.toSingular && world.cache.toSingular.hasOwnProperty(str) === true) { - return true; - } - //inspect the existing tags to see if a plural is valid - if (couldEvenBePlural(t) === false) { - return null; - } - //handle 'mayors of chicago' - const preposition = str.match(prep); - if (preposition !== null) { - str = preposition[1]; - } - //check the suffix-type rules for indications - for (let i = 0; i < rules.plural_indicators.length; i++) { - if (rules.plural_indicators[i].test(str) === true) { - return true; - } - } - for (let i = 0; i < rules.singular_indicators.length; i++) { - if (rules.singular_indicators[i].test(str) === true) { - return false; - } - } - // a fallback 'looks check plural' rule.. - if (/s$/.test(str) === true && /ss$/.test(str) === false && str.length > 3) { - //needs some lovin' - return true; - } - return false; -}; - -module.exports = isPlural; -// console.log(is_plural('octopus')) - -},{"./hasPlural":37,"./methods/data/indicators":41}],40:[function(_dereq_,module,exports){ -'use strict'; - -//chooses an indefinite aricle 'a/an' for a word -const irregulars = { - 'hour': 'an', - 'heir': 'an', - 'heirloom': 'an', - 'honest': 'an', - 'honour': 'an', - 'honor': 'an', - 'uber': 'an' //german u -}; -//pronounced letters of acronyms that get a 'an' -const an_acronyms = { - a: true, - e: true, - f: true, - h: true, - i: true, - l: true, - m: true, - n: true, - o: true, - r: true, - s: true, - x: true -}; -//'a' regexes -const a_regexs = [ - /^onc?e/i, //'wu' sound of 'o' - /^u[bcfhjkqrstn][aeiou]/i, // 'yu' sound for hard 'u' - /^eul/i -]; - -const makeArticle = function(t) { - let str = t.normal; - //no 'the john smith', but 'a london hotel' - if (t.tags.Person) { - return ''; - } - //no a/an if it's plural - if (t.tags.Plural) { - return 'the'; - } - //explicit irregular forms - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - //spelled-out acronyms - let firstLetter = str.substr(0, 1); - if (t.isAcronym() && an_acronyms.hasOwnProperty(firstLetter)) { - return 'an'; - } - //'a' regexes - for (let i = 0; i < a_regexs.length; i++) { - if (a_regexs[i].test(str)) { - return 'a'; - } - } - //basic vowel-startings - if (/^[aeiou]/i.test(str)) { - return 'an'; - } - return 'a'; -}; - -module.exports = makeArticle; - -},{}],41:[function(_dereq_,module,exports){ -'use strict'; -//similar to plural/singularize rules, but not the same -const plural_indicators = [ - /(^v)ies$/i, - /ises$/i, - /ives$/i, - /(antenn|formul|nebul|vertebr|vit)ae$/i, - /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, - /(buffal|tomat|tornad)oes$/i, - /(analy|ba|diagno|parenthe|progno|synop|the)ses$/i, - /(vert|ind|cort)ices$/i, - /(matr|append)ices$/i, - /(x|ch|ss|sh|s|z|o)es$/i, - /men$/i, - /news$/i, - /.tia$/i, - /(^f)ves$/i, - /(lr)ves$/i, - /(^aeiouy|qu)ies$/i, - /(m|l)ice$/i, - /(cris|ax|test)es$/i, - /(alias|status)es$/i, - /ics$/i -]; - -//similar to plural/singularize rules, but not the same -const singular_indicators = [ - /(ax|test)is$/i, - /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, - /(octop|vir)i$/i, - /(rl)f$/i, - /(alias|status)$/i, - /(bu)s$/i, - /(al|ad|at|er|et|ed|ad)o$/i, - /(ti)um$/i, - /(ti)a$/i, - /sis$/i, - /(?:(^f)fe|(lr)f)$/i, - /hive$/i, - /(^aeiouy|qu)y$/i, - /(x|ch|ss|sh|z)$/i, - /(matr|vert|ind|cort)(ix|ex)$/i, - /(m|l)ouse$/i, - /(m|l)ice$/i, - /(antenn|formul|nebul|vertebr|vit)a$/i, - /.sis$/i, - /^(?!talis|.*hu)(.*)man$/i -]; -module.exports = { - singular_indicators: singular_indicators, - plural_indicators: plural_indicators -} - -},{}],42:[function(_dereq_,module,exports){ -//patterns for turning 'bus' to 'buses' -module.exports = [ - [/(ax|test)is$/i, '$1es'], - [/(octop|vir|radi|nucle|fung|cact|stimul)us$/i, '$1i'], - [/(octop|vir)i$/i, '$1i'], - [/(kn|l|w)ife$/i, '$1ives'], - [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)f$/i, '$1ves'], - [/^(dwar|handkerchie|hoo|scar|whar)f$/i, '$1ves'], - [/(alias|status)$/i, '$1es'], - [/(bu)s$/i, '$1ses'], - [/(al|ad|at|er|et|ed|ad)o$/i, '$1oes'], - [/([ti])um$/i, '$1a'], - [/([ti])a$/i, '$1a'], - [/sis$/i, 'ses'], - [/(hive)$/i, '$1s'], - [/([^aeiouy]|qu)y$/i, '$1ies'], - [/(x|ch|ss|sh|s|z)$/i, '$1es'], - [/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices'], - [/([m|l])ouse$/i, '$1ice'], - [/([m|l])ice$/i, '$1ice'], - [/^(ox)$/i, '$1en'], - [/^(oxen)$/i, '$1'], - [/(quiz)$/i, '$1zes'], - [/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae'], - [/(sis)$/i, 'ses'], - [/^(?!talis|.*hu)(.*)man$/i, '$1men'], - [/(.*)/i, '$1s'] -].map(function(a) { - return { - reg: a[0], - repl: a[1] - }; -}); - -},{}],43:[function(_dereq_,module,exports){ -//patterns for turning 'dwarves' to 'dwarf' -module.exports = [ - [/([^v])ies$/i, '$1y'], - [/ises$/i, 'isis'], - [/(kn|[^o]l|w)ives$/i, '$1ife'], - [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i, '$1f'], - [/^(dwar|handkerchie|hoo|scar|whar)ves$/i, '$1f'], - [/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a'], - [/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i, '$1us'], - [/(buffal|tomat|tornad)(oes)$/i, '$1o'], - // [/(analy|diagno|parenthe|progno|synop|the)ses$/i, '$1sis'], - [/(..[aeiou]s)es$/i, '$1'], - [/(vert|ind|cort)(ices)$/i, '$1ex'], - [/(matr|append)(ices)$/i, '$1ix'], - [/(x|ch|ss|sh|z|o)es$/i, '$1'], - [/men$/i, 'man'], - [/(n)ews$/i, '$1ews'], - [/([ti])a$/i, '$1um'], - [/([^aeiouy]|qu)ies$/i, '$1y'], - [/(s)eries$/i, '$1eries'], - [/(m)ovies$/i, '$1ovie'], - [/([m|l])ice$/i, '$1ouse'], - [/(cris|ax|test)es$/i, '$1is'], - [/(alias|status)es$/i, '$1'], - [/(ss)$/i, '$1'], - [/(ics)$/i, '$1'], - [/s$/i, ''] -].map(function(a) { - return { - reg: a[0], - repl: a[1] - }; -}); - -},{}],44:[function(_dereq_,module,exports){ -'use strict'; -// const irregulars = require('../../../lexicon/uncompressed/irregularPlurals').toPlural; -const pluralRules = _dereq_('./data/pluralRules'); - -//turn 'shoe' into 'shoes' -const pluralize = function(str, world) { - const irregulars = world.plurals || {}; - //irregular - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - //regular rule-based inflector - for (let i = 0; i < pluralRules.length; i++) { - if (pluralRules[i].reg.test(str) === true) { - return str.replace(pluralRules[i].reg, pluralRules[i].repl); - } - } - return null; -}; - -module.exports = pluralize; - -},{"./data/pluralRules":42}],45:[function(_dereq_,module,exports){ -'use strict'; -const singleRules = _dereq_('./data/singleRules'); - -//turn 'shoes' into 'shoe' -const toSingle = function(str, world) { - //reverse it //TODO: cache in world object somewhere - let irregulars = world.cache.toSingular || {}; - //check irregulars - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - if (world && world.plurals) { - //given irregulars - let keys = Object.keys(world.plurals); - for (let i = 0; i < keys.length; i++) { - if (world.plurals[keys[i]] === str) { - return keys[i]; - } - } - } - - //inflect first word of preposition-phrase - if (/([a-z]*) (of|in|by|for) [a-z]/.test(str) === true) { - const first = (str.match(/^([a-z]*) (of|in|by|for) [a-z]/) || [])[1]; - if (first) { - const better_first = toSingle(first); //recursive - return better_first + str.replace(first, ''); - } - } - - //regular rule-based inflector - for (let i = 0; i < singleRules.length; i++) { - if (singleRules[i].reg.test(str) === true) { - return str.replace(singleRules[i].reg, singleRules[i].repl); - } - } - return null; -}; - -module.exports = toSingle; -// console.log(toSingle('days')) - -},{"./data/singleRules":43}],46:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../paths').Terms; -const hasPlural = _dereq_('./hasPlural'); -const isPlural = _dereq_('./isPlural'); -const toPossessive = _dereq_('./toPossessive'); -const makeArticle = _dereq_('./makeArticle'); -const pluralize = _dereq_('./methods/pluralize'); -const singularize = _dereq_('./methods/singularize'); - -const methods = { - article: function() { - return makeArticle(this.main); - }, - isPlural: function() { - return isPlural(this.main, this.world); - }, - hasPlural: function() { - return hasPlural(this.main); - }, - toPlural: function(verbose) { - let t = this.main; - if (hasPlural(t) && !isPlural(t, this.world)) { - t.text = pluralize(t.normal, this.world, verbose) || t.text; - t.unTag('Singular', 'toPlural'); - t.tag('Plural', 'toPlural'); - } - return this; - }, - toSingular: function(verbose) { - let t = this.main; - if (isPlural(t, this.world)) { - t.text = singularize(t.normal, this.world, verbose) || t.text; - t.unTag('Plural', 'toSingular'); - t.tag('Singular', 'toSingular'); - } - return this; - }, - toPossessive: function() { - let t = this.main; - if (t.tags.Possessive) { - return this; - } - t = toPossessive(t); - return this; - }, - data: function() { - let t = this.main; - let singular = t.text; - if (isPlural(t, this.world)) { - singular = singularize(t.normal, this.world) || t.text; - } - let plural = t.text; - if (hasPlural(t) && !isPlural(t, this.world)) { - plural = pluralize(t.normal, this.world) || t.text; - } - //support 'mayors of chicago' - let qualifier = ''; - if (this.qualifier) { - qualifier = this.qualifier.out('normal'); - singular += ' ' + qualifier; - plural += ' ' + qualifier; - } - return { - text: this.out('text'), - normal: this.out('normal'), - article: this.article(), - main: t.normal, - qualifier: qualifier, - singular: singular, - plural: plural - }; - } -}; - -const Noun = function(arr, world, refText) { - Terms.call(this, arr, world, refText); - //support 'mayor of chicago' as one noun-phrase - this.main = this.match('[#Noun+] (of|by|for)'); - if (this.main.found) { - this.main = this.main.list[0].terms[0]; - } else { - this.main = this.terms[this.terms.length - 1]; - } - //'of chicago' - this.qualifier = this.match(this.main.normal + ' [.+]').list[0]; -}; -Noun.prototype = Object.create(Terms.prototype); - -Object.keys(methods).forEach(k => { - Noun.prototype[k] = methods[k]; -}); -module.exports = Noun; - -},{"../../paths":8,"./hasPlural":37,"./isPlural":39,"./makeArticle":40,"./methods/pluralize":44,"./methods/singularize":45,"./toPossessive":47}],47:[function(_dereq_,module,exports){ -const exceptions = { - he: 'his', - she: 'hers', - they: 'theirs', - we: 'ours', - i: 'mine', - you: 'yours', - - her: 'hers', - their: 'theirs', - our: 'ours', - my: 'mine', - your: 'yours', -}; - -// turn "David" to "David's" -const toPossessive = function(t) { - t.tag('Possessive', 'toPossessive'); - // exceptions - if (exceptions.hasOwnProperty(t.normal)) { - t.text = exceptions[t.normal]; - return t; - } - // flanders' - if (/s$/.test(t.normal)) { - t.text += '\''; - return t; - } - //normal form: - t.text += '\'s'; - return t; -}; -module.exports = toPossessive; - -},{}],48:[function(_dereq_,module,exports){ -'use strict'; -// make a statistical assumption about the gender of the person based on their given name -// used for pronoun resolution only. -// not intended for classification, or discrimination of people. -const gender = function (firstName) { - if (!firstName) { - return null; - } - //statistical guesses - if (/.(i|ee|[a|e]y|a)$/.test(firstName) === true) { //this is almost-always true - return 'Female'; - } - if (/[ou]$/.test(firstName) === true) { //if it ends in a 'oh or uh', male - return 'Male'; - } - if (/(nn|ll|tt)/.test(firstName) === true) { //if it has double-consonants, female - return 'Female'; - } - // name not recognized, or recognized as of indeterminate gender - return null; -}; -module.exports = gender; - -},{}],49:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const Person = _dereq_('./person'); -//this is used for pronoun and honorifics, and not intented for more-than grammatical use (see #117) - -//the () subset class -const methods = { - pronoun: function() { - return this.list.map(ts => ts.pronoun()); - }, - firstNames: function() { - return this.match('#FirstName'); - }, - lastNames: function() { - return this.match('#LastName'); - } -}; - -const find = function(r, n) { - let people = r.clauses(); - people = people.match('#Person+'); - if (typeof n === 'number') { - people = people.get(n); - } - people.list = people.list.map(ts => { - return new Person(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return people; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./person":50}],50:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../paths').Terms; -const guessGender = _dereq_('./guessGender'); - -const Person = function(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - this.firstName = this.match('#FirstName+'); - this.middleName = this.match('#Acronym+'); - this.nickName = this.match('#NickName+'); - this.honorifics = this.match('#Honorific'); - this.lastName = this.match('#LastName+'); - //assume first-last - if (!this.firstName.found && this.length > 1) { - let m = this.not('(#Acronym|#Honorific)'); - this.firstName = m.first(); - this.lastName = m.last(); - } - return this; -}; -//Inherit properties -Person.prototype = Object.create(Terms.prototype); - -const methods = { - data: function() { - return { - text: this.out('text'), - normal: this.out('normal'), - firstName: this.firstName.out('normal'), - middleName: this.middleName.out('normal'), - nickName: this.nickName.out('normal'), - lastName: this.lastName.out('normal'), - genderGuess: this.guessGender(), - pronoun: this.pronoun(), - honorifics: this.honorifics.out('array') - }; - }, - guessGender: function() { - //try known honorifics - if (this.honorifics.match('(mr|mister|sr|sir|jr)').found) { - return 'Male'; - } - if (this.honorifics.match('(mrs|miss|ms|misses|mme|mlle)').found) { - return 'Female'; - } - //try known first-names - if (this.firstName.match('#MaleName').found) { - return 'Male'; - } - if (this.firstName.match('#FemaleName').found) { - return 'Female'; - } - //look-for regex clues - let str = this.firstName.out('normal'); - return guessGender(str); - }, - pronoun: function() { - let str = this.firstName.out('normal'); - let g = this.guessGender(str); - if (g === 'Male') { - return 'he'; - } - if (g === 'Female') { - return 'she'; - } - return 'they'; - }, - root: function() { - let first = this.firstName.out('root'); - let last = this.lastName.out('root'); - if (first && last) { - return first + ' ' + last; - } - return last || first || this.out('root'); - } -}; - -Object.keys(methods).forEach(k => { - Person.prototype[k] = methods[k]; -}); -module.exports = Person; - -},{"../../paths":8,"./guessGender":48}],51:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -// const Terms = require('../../paths').Terms; - -const methods = { - //remove the 's on the end of the word - strip() { - this.list.forEach((ts) => { - let t = ts.terms[ts.terms.length - 1]; - t.text = t.text.replace(/'s$/, ''); - t.unTag('Possessive', '.strip()'); - }); - return this; - } -}; - -const find = function(r, n) { - r = r.match('#Possessive+'); - r = r.splitAfter('#Comma'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192}],52:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const Sentence = _dereq_('./sentence'); -//the Sentences() subset class -const methods = { - /** conjugate the main/first verb*/ - toPastTense: function() { - this.list = this.list.map(ts => { - ts = ts.toPastTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toPresentTense: function() { - this.list = this.list.map(ts => { - ts = ts.toPresentTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toFutureTense: function() { - this.list = this.list.map(ts => { - ts = ts.toFutureTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toContinuous: function() { - this.list = this.list.map(ts => { - ts = ts.toContinuous(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - /** negative/positive */ - toNegative: function() { - this.list = this.list.map(ts => { - ts = ts.toNegative(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toPositive: function() { - this.list = this.list.map(ts => { - ts = ts.toPositive(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - - /** look for 'was _ by' patterns */ - isPassive: function() { - this.list = this.list.filter(ts => { - return ts.isPassive(); - }); - return this; - }, - //return only questions - isQuestion: function() { - // this.list = this.list.filter(ts => { - // return ts.isQuestion(); - // }); - return this.questions() - }, - /** add a word to the start */ - prepend: function(str) { - this.list = this.list.map(ts => { - return ts.prepend(str); - }); - return this; - }, - /** add a word to the end */ - append: function(str) { - this.list = this.list.map(ts => { - return ts.append(str); - }); - return this; - }, - - /** convert between question/statement/exclamation*/ - toExclamation: function() { - this.list.forEach(ts => { - ts.setPunctuation('!'); - }); - return this; - }, - toQuestion: function() { - this.list.forEach(ts => { - ts.setPunctuation('?'); - }); - return this; - }, - toStatement: function() { - this.list.forEach(ts => { - ts.setPunctuation('.'); - }); - return this; - } -}; - -const find = function(r, n) { - r = r.all(); - if (typeof n === 'number') { - r = r.get(n); - } - r.list = r.list.map(ts => { - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./sentence":54}],53:[function(_dereq_,module,exports){ -'use strict'; - -//is this sentence asking a question? -const isQuestion = function (ts) { - let endPunct = ts.getPunctuation(); - let clauses = ts.match('*').splitAfter('#Comma'); - - if (/\?/.test(endPunct) === true) { - return true; - } - - // Has ellipsis at the end means it's probably not a question - // e.g., Is this just fantasy... - if (/\.\.$/.test(ts.out('text'))) { - return false; - } - - // Starts with question word, but has a comma, so probably not a question - // e.g., Why are we caught in a land slide, no escape from reality - if (ts.has('^#QuestionWord') && ts.has('#Comma')) { - return false; - } - - // Starts with a #QuestionWord - // e.g., What open your eyes look up to the skies and see - if (ts.has('^#QuestionWord')) { - return true; - } - - // Second word is a #QuestionWord - // e.g., I'm what a poor boy - // case ts.has('^\w+\s#QuestionWord'): - // return true; - - // is it, do you - start of sentence - // e.g., Do I need no sympathy - if (ts.has('^(do|does|did|is|was|can|could|will|would|may) #Noun')) { - return true; - } - - // these are a little more loose.. - // e.g., Must I be come easy come easy go - if (ts.has('^(have|must) you')) { - return true; - } - - // Clause starts with a question word - // e.g., Anyway the wind blows, what doesn't really matter to me - if (clauses.has('^#QuestionWord')) { - return true; - } - - //is wayne gretskzy alive - if (clauses.has('(do|does|is|was) #Noun+ #Adverb? (#Adjective|#Infinitive)$')) { - return true; - } - - // Probably not a question - return false; - -}; -module.exports = isQuestion; - -},{}],54:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../paths').Terms; -const toNegative = _dereq_('./toNegative'); -const toPositive = _dereq_('./toPositive'); -const Verb = _dereq_('../verbs/verb'); -const insert = _dereq_('./smartInsert'); - -//decide on main subject-verb-object -const parse = function(s) { - //strip conditions first - let conditions = s.match('#Condition'); - let tmp = s.not('#Condition'); - //choose the verb first - let verb = tmp.match('#VerbPhrase+').first(); //this should be much smarter - let vb = verb.out('normal'); - //get subj noun left-of the verb - let subject = tmp.match('#Determiner? #Adjective+? #Noun ' + vb).first().not('#VerbPhrase'); - //get obj noun right-of the verb - let object = tmp.match(vb + ' #Preposition? #Determiner? #Noun').first().not('#VerbPhrase'); - s.conditions = conditions; - s.subject = subject; - s.verb = verb; - s.object = object; - if (s.verb.found) { - s.verb = new Verb(s.verb.list[0].terms, s.world, s.refText, s.refTerms); - } - return s; -}; - -const fixContraction = function(contr) { - if (contr.found) { - contr.contractions().expand(); - } -}; - -const killContraction = function(s) { - s.terms = s.terms.filter(t => { - if (t.silent_term) { - if (t.silent_term === 'am' || t.silent_term === 'will' || t.silent_term === 'did') { - return false; - } - t.text = t.silent_term; - t.silent_term = null; - t.unTag('Contraction'); - if (t.tags.TitleCase === true) { - t.toTitleCase(); - } - } - return true; - }); -}; - -//if the subject of thr sentence is plural, use infinitive form of verb -// (he goes / i go) -const useInfinitive = function(s) { - if (s.subject.found && s.subject.has('(i|we)')) { - return true; - } - return false; -}; - -const methods = { - /** inflect the main/first noun*/ - toSingular: function() { - let nouns = this.match('#Noun').match('!#Pronoun').firstTerm(); - nouns.things().toSingular(); - return this; - }, - toPlural: function() { - let nouns = this.match('#Noun').match('!#Pronoun').firstTerm(); - nouns.things().toPlural(); - return this; - }, - - /** find the first important verbPhrase. returns a Term object */ - mainVerb: function() { - parse(this); //re-parse - if (this.verb.found) { - return this.verb; - } - return null; - }, - - /** sentence tense conversion**/ - toPastTense: function() { - let verb = this.mainVerb(); - if (verb) { - //this is really ugly.. - let start = verb.out('root'); - verb.toPastTense(); - //support "i'm going" - let contr = this.match('#Contraction ' + start); - fixContraction(contr); - let end = verb.out('root'); - // this.replace(start, end) - let r = this.parentTerms.replace(start, end); - return r; - } - return this; - }, - toPresentTense: function() { - let verb = this.mainVerb(); - if (verb) { - let start = verb.out('normal'); - //plural/singular stuff - if (useInfinitive(this) === true) { - if (this.has('(am|will|did) ' + start)) { - killContraction(this); - } - verb.toInfinitive(); - //irregular "i am" - // this.debug(); - // if (this.has('i #Adverb? is')) { - // this.replace(' #Adverb? [is]', 'am'); - // } - } else { - verb.toPresentTense(); - let contr = this.match('#Contraction ' + start); - fixContraction(contr); - } - //support "i'm going" - let end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - return this; - }, - toFutureTense: function() { - let verb = this.mainVerb(); - if (verb) { - let start = verb.clone(); //.out('root'); - verb.toFutureTense(); - //support "i'm going" - let contr = this.match('#Contraction ' + start.out('normal')); - fixContraction(contr); - let end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - return this; - }, - toContinuous: function() { - let verb = this.mainVerb(); - if (verb) { - let start = verb.clone(); //.out('root'); - //'is walking' or 'are walking'? - // let aux = 'is'; - // if (useInfinitive(this)) { - // aux = 'are'; - // } - verb.toGerund(); - // verb.insertBefore(aux); - //support "i'm going" - let contr = this.match('#Contraction ' + start.out('normal')); - fixContraction(contr); - let end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - return this; - }, - - /** negation **/ - isNegative: function() { - return this.match('#Negative').list.length === 1; - }, - toNegative: function() { - if (this.isNegative()) { - return this; - } - return toNegative(this); - }, - toPositive: function() { - if (!this.isNegative()) { - return this; - } - return toPositive(this); - }, - - /** smarter insert methods*/ - append: function(str) { - return insert.append(this, str); - }, - prepend: function(str) { - return insert.prepend(this, str); - }, - - /** look for 'was _ by' patterns */ - isPassive: function() { - return this.match('was #Adverb? #PastTense #Adverb? by').found; //haha - } -}; - -const Sentence = function(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - parse(this); -}; -//Terms inheritence -Sentence.prototype = Object.create(Terms.prototype); -//add-in methods -Object.keys(methods).forEach(k => { - Sentence.prototype[k] = methods[k]; -}); -module.exports = Sentence; - -},{"../../paths":8,"../verbs/verb":94,"./smartInsert":55,"./toNegative":56,"./toPositive":57}],55:[function(_dereq_,module,exports){ -'use strict'; -const hasCapital = /^[A-Z]/; - -//sticking words at the start sentence-sensitive -const prepend = (ts, str) => { - let firstTerm = ts.terms[0]; - ts.insertAt(0, str); - //handle titlecase of first-word - if (hasCapital.test(firstTerm.text)) { - //is it titlecased because it should be? - if (firstTerm.needsTitleCase() === false) { - firstTerm.toLowerCase(); - } - let newTerm = ts.terms[0]; - newTerm.toTitleCase(); - } - return ts; -}; - -//sticking words on end sentence-sensitive -const append = (ts, str) => { - let endTerm = ts.terms[ts.terms.length - 1]; - //move the sentence punctuation to the end - let punct = ts.getPunctuation(); - if (punct) { - endTerm.killPunctuation(); - } - ts.insertAt(ts.terms.length, str); - let newTerm = ts.terms[ts.terms.length - 1]; - if (punct) { - newTerm.text += punct; - } - //move over sentence-ending whitespace too - if (endTerm.whitespace.after) { - newTerm.whitespace.after = endTerm.whitespace.after; - endTerm.whitespace.after = ''; - } - return ts; -}; - -module.exports = { - append: append, - prepend: prepend -}; - -},{}],56:[function(_dereq_,module,exports){ -'use strict'; - -//these terms are nicer ways to negate a sentence -//ie. john always walks -> john always doesn't walk -const logicalNegate = { - everyone: 'no one', - everybody: 'nobody', - someone: 'no one', - somebody: 'nobody', - // everything:"nothing", - always: 'never' -}; - -//different rule for i/we/they/you + infinitive -//that is, 'i walk' -> 'i don\'t walk', not 'I not walk' -const toNegative = ts => { - let lg = ts.match('(everyone|everybody|someone|somebody|always)').first(); - if (lg.found && logicalNegate[lg.out('normal')]) { - let found = lg.out('normal'); - // ts = ts.replace(found, logicalNegate[found]); - ts = ts.match(found).replaceWith(logicalNegate[found]).list[0]; - return ts.parentTerms; - } - //negate the main verb of the sentence - let vb = ts.mainVerb(); - if (vb) { - vb.toNegative(); - } - return ts; -}; -module.exports = toNegative; - -},{}],57:[function(_dereq_,module,exports){ -'use strict'; - -//ie. john never walks -> john always walks -//nobody/noone are ambiguous logically (somebody? / everybody?) -const logical = { - 'never': 'always', - 'nothing': 'everything', -}; - -const toPositive = (ts) => { - let m = ts.match('(never|nothing)').first(); - if (m.found) { - let str = m.out('normal'); - if (logical[str]) { - ts = ts.match(str).replaceWith(logical[str], true).list[0]; - return ts.parentTerms; - } - } - //otherwise just remove 'not' - ts.delete('#Negative'); - return ts; -}; -module.exports = toPositive; - -},{}],58:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const Terms = _dereq_('../../paths').Terms; - -//the Terms() subset class -//this is just a wrapper around the actual Term class, -//which is buried in `ts.terms[0]` -const methods = { - data: function() { - return this.list.map(ts => { - let t = ts.terms[0]; - return { - spaceBefore: t.whitespace.before, - text: t.text, - spaceAfter: t.whitespace.after, - normal: t.normal, - implicit: t.silent_term, - bestTag: t.bestTag(), - tags: Object.keys(t.tags) - }; - }); - } -}; - -const find = function(r, n) { - let list = []; - //make a Terms Object for every Term - r.list.forEach(ts => { - ts.terms.forEach(t => { - list.push(new Terms([t], ts.world, r)); - }); - }); - r = new Text(list, r.world, r.parent); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../paths":8,"../../text":192}],59:[function(_dereq_,module,exports){ -const numOrdinal = _dereq_('./numOrdinal'); -const textOrdinal = _dereq_('./textOrdinal'); -const textCardinal = _dereq_('./textCardinal'); -const niceNumber = _dereq_('./niceNumber'); - -//make all the number formats -const fmt = { - nice: function(num) { - return niceNumber(num); - }, - ordinal: function(num) { - return numOrdinal(num); - }, - cardinal: function(num) { - return String(num); - }, - niceOrdinal: function(num) { - num = numOrdinal(num); - num = niceNumber(num); - return num; - }, - text: function(num) { - return textCardinal(num).join(' '); - }, - textOrdinal: function(num) { - return textOrdinal(num); - } -}; -module.exports = fmt; - -},{"./niceNumber":60,"./numOrdinal":61,"./textCardinal":62,"./textOrdinal":63}],60:[function(_dereq_,module,exports){ -'use strict'; -//put a comma or two in -const niceNumber = function (num) { - if (!num && num !== 0) { - return null; - } - num = String(num); - let x = num.split('.'); - let x1 = x[0]; - let x2 = x.length > 1 ? '.' + x[1] : ''; - let rgx = /(\d+)(\d{3})/; - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + ',' + '$2'); - } - return x1 + x2; -}; -module.exports = niceNumber; - -},{}],61:[function(_dereq_,module,exports){ -'use strict'; -const toString = _dereq_('./toString'); - -//turn a number like 5 into an ordinal like 5th -const numOrdinal = function(num) { - if (!num && num !== 0) { - return null; - } - //the teens are all 'th' - let tens = num % 100; - if (tens > 10 && tens < 20) { - return String(num) + 'th'; - } - //the rest of 'em - const mapping = { - 0: 'th', - 1: 'st', - 2: 'nd', - 3: 'rd' - }; - let str = toString(num); - let last = str.slice(str.length - 1, str.length); - if (mapping[last]) { - str += mapping[last]; - } else { - str += 'th'; - } - return str; -}; - -module.exports = numOrdinal; - -},{"./toString":64}],62:[function(_dereq_,module,exports){ -'use strict'; -const toString = _dereq_('./toString'); - -// turns an integer/float into a textual number, like 'fifty-five' -const tens_mapping = [ - ['ninety', 90], - ['eighty', 80], - ['seventy', 70], - ['sixty', 60], - ['fifty', 50], - ['forty', 40], - ['thirty', 30], - ['twenty', 20] -]; -const ones_mapping = [ - '', - 'one', - 'two', - 'three', - 'four', - 'five', - 'six', - 'seven', - 'eight', - 'nine', - 'ten', - 'eleven', - 'twelve', - 'thirteen', - 'fourteen', - 'fifteen', - 'sixteen', - 'seventeen', - 'eighteen', - 'nineteen' -]; - -const sequence = [ - [1e24, 'septillion'], - [1e21, 'sextillion'], - [1e18, 'quintillion'], - [1e15, 'quadrillion'], - [1e12, 'trillion'], - [1e9, 'billion'], - [1e8, 'hundred million'], - [1e6, 'million'], - [100000, 'hundred thousand'], - [1000, 'thousand'], - [100, 'hundred'], - [1, 'one'] -]; - -//turn number into an array of magnitudes, like [[5, million], [2, hundred]] -const breakdown_magnitudes = function(num) { - let working = num; - let have = []; - sequence.forEach((a) => { - if (num >= a[0]) { - let howmany = Math.floor(working / a[0]); - working -= howmany * a[0]; - if (howmany) { - have.push({ - unit: a[1], - count: howmany - }); - } - } - }); - return have; -}; - -//turn numbers from 100-0 into their text -const breakdown_hundred = function(num) { - let arr = []; - if (num > 100) { - return arr; //something bad happened.. - } - for (let i = 0; i < tens_mapping.length; i++) { - if (num >= tens_mapping[i][1]) { - num -= tens_mapping[i][1]; - arr.push(tens_mapping[i][0]); - } - } - //(hopefully) we should only have 20-0 now - if (ones_mapping[num]) { - arr.push(ones_mapping[num]); - } - return arr; -}; - -/** print-out 'point eight nine'*/ -const handle_decimal = (num) => { - const names = [ - 'zero', - 'one', - 'two', - 'three', - 'four', - 'five', - 'six', - 'seven', - 'eight', - 'nine' - ]; - let arr = []; - //parse it out like a string, because js math is such shit - let str = toString(num); - let decimal = str.match(/\.([0-9]+)/); - if (!decimal || !decimal[0]) { - return arr; - } - arr.push('point'); - let decimals = decimal[0].split(''); - for (let i = 0; i < decimals.length; i++) { - arr.push(names[decimals[i]]); - } - return arr; -}; - -/** turns an integer into a textual number */ -const to_text = function(num) { - //big numbers, north of sextillion, aren't gonna work well.. - //keep them small.. - if (num > 1e21) { - return [String(num)]; - } - let arr = []; - //handle negative numbers - if (num < 0) { - arr.push('negative'); - num = Math.abs(num); - } - //break-down into units, counts - let units = breakdown_magnitudes(num); - //build-up the string from its components - for (let i = 0; i < units.length; i++) { - let unit_name = units[i].unit; - if (unit_name === 'one') { - unit_name = ''; - //put an 'and' in here - if (arr.length > 1) { - arr.push('and'); - } - } - arr = arr.concat(breakdown_hundred(units[i].count)); - arr.push(unit_name); - } - //also support decimals - 'point eight' - arr = arr.concat(handle_decimal(num)); - //remove empties - arr = arr.filter((s) => s); - if (arr.length === 0) { - arr[0] = ''; - } - return arr; -}; - -module.exports = to_text; - -// console.log(to_text(-1000.8)); - -},{"./toString":64}],63:[function(_dereq_,module,exports){ -'use strict'; -const textValue = _dereq_('./textCardinal'); -const ordinalWord = _dereq_('../../../world/more-data/numbers').toOrdinal; -// -const textOrdinal = num => { - let words = textValue(num); - //convert the last number to an ordinal - let last = words[words.length - 1]; - words[words.length - 1] = ordinalWord[last] || last; - return words.join(' '); -}; - -module.exports = textOrdinal; - -},{"../../../world/more-data/numbers":220,"./textCardinal":62}],64:[function(_dereq_,module,exports){ -//turn big numbers, like 2.3e+22, into a tonne of 0's -const numToString = function(n) { - if (n < 1000000) { - return String(n); - } - var str = n.toFixed(0); - if (str.indexOf('e+') === -1) { - return str; - } - return str.replace('.', '').split('e+').reduce(function(p, b) { - return p + Array(b - p.length + 2).join(0); - }); -}; -module.exports = numToString; -// console.log(numToString(2.5e+22)); - -},{}],65:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const Value = _dereq_('./value'); -const parse = _dereq_('./parse'); - -//the Values() subset class -const methods = { - noDates: function() { - return this.not('#Date'); - }, - noUnits: function() { - return this.not('#Unit'); - }, - units: function() { - return this.match('#Unit+'); - }, - /** five -> 5 */ - numbers: function() { - return this.list.map(ts => { - return ts.number(); - }); - }, - /** five -> '5' */ - toNumber: function() { - this.list = this.list.map(ts => { - return ts.toNumber(); - }); - return this; - }, - /**5 -> 'five' */ - toText: function() { - this.list = this.list.map(ts => { - return ts.toText(); - }); - return this; - }, - /**5th -> 5 */ - toCardinal: function() { - this.list = this.list.map(ts => { - return ts.toCardinal(); - }); - return this; - }, - /**5 -> 5th */ - toOrdinal: function() { - this.list = this.list.map(ts => { - return ts.toOrdinal(); - }); - return this; - }, - /**5900 -> 5,900 */ - toNice: function() { - this.list = this.list.map(ts => { - return ts.toNice(); - }); - return this; - }, - /**seven === 7th */ - isEqual: function(num) { - num = parse(num); - this.list = this.list.filter(ts => { - return num !== null && ts.number() === num; - }); - return this; - }, - /**eight > 7th */ - greaterThan: function(num) { - num = parse(num); - this.list = this.list.filter(ts => { - return num !== null && ts.number() > num; - }); - return this; - }, - /**five < 7th */ - lessThan: function(num) { - num = parse(num); - this.list = this.list.filter(ts => { - return num !== null && ts.number() < num; - }); - return this; - }, - between: function(min, max) { - if (min === undefined || max === undefined) { - return this; - } - min = parse(min); - max = parse(max); - this.list = this.list.filter(ts => { - let n = ts.number(); - return n > min && n < max; - }); - return this; - }, - /**seven + 2 = 'nine' */ - add: function(n) { - this.list = this.list.map(ts => { - return ts.add(n); - }); - return this; - }, - /**seven - 2 = 'five' */ - subtract: function(n) { - this.list = this.list.map(ts => { - return ts.subtract(n); - }); - return this; - }, - /**seven -> 'eight' */ - increment: function() { - this.list = this.list.map(ts => { - return ts.add(1); - }); - return this; - }, - /**seven -> 'eight' */ - decrement: function() { - this.list = this.list.map(ts => { - return ts.subtract(1); - }); - return this; - } -}; - -const find = function(r, n) { - const tens = 'twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty'; - const teens = 'eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen'; - r = r.match('#Value+ #Unit?'); - // r = r.match('#Value+ #Unit?'); - - //"50 83" - if (r.has('#NumericValue #NumericValue')) { - //a comma may mean two numbers - if (r.has('#Value #Comma #Value')) { - r.splitAfter('#Comma'); - } else { - r.splitAfter('#NumericValue'); - } - } - //three-length - if (r.has('#Value #Value #Value') && !r.has('#Multiple')) { - //twenty-five-twenty - if (r.has('(' + tens + ') #Cardinal #Cardinal')) { - r.splitAfter('(' + tens + ') #Cardinal'); - } - } - - //two-length ones - if (r.has('#Value #Value')) { - //june 21st 1992 is two seperate values - if (r.has('#NumericValue #NumericValue')) { - r.splitOn('#Year'); - } - //sixty fifteen - if (r.has('(' + tens + ') (' + teens + ')')) { - r.splitAfter('(' + tens + ')'); - } - //"72 82" - let double = r.match('#Cardinal #Cardinal'); - if (double.found && !r.has('(point|decimal)')) { - //not 'two hundred' - if (!double.has('#Cardinal (#Multiple|point|decimal)')) { - //one proper way, 'twenty one', or 'hundred one' - if (!double.has('(' + tens + ') #Cardinal') && !double.has('#Multiple #Value')) { - r.splitAfter(double.terms(0).out('normal')); - } - } - } - //seventh fifth - if (r.match('#Ordinal #Ordinal').match('#TextValue').found && !r.has('#Multiple')) { - //the one proper way, 'twenty first' - if (!r.has('(' + tens + ') #Ordinal')) { - r.splitAfter('#Ordinal'); - } - } - //fifth five - if (r.has('#Ordinal #Cardinal')) { - r.splitBefore('#Cardinal+'); - } - //five 2017 (support '5 hundred', and 'twenty 5' - if ( - r.has('#TextValue #NumericValue') && - !r.has('(' + tens + '|#Multiple)') - ) { - r.splitBefore('#NumericValue+'); - } - } - //5-8 - if (r.has('#NumberRange')) { - r.splitAfter('#NumberRange'); - } - if (typeof n === 'number') { - r = r.get(n); - } - let world = r.world(); - r.list = r.list.map(ts => { - return new Value(ts.terms, world, ts.refText, ts.refTerms); - }); - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./parse":66,"./value":74}],66:[function(_dereq_,module,exports){ -'use strict'; -const parseText = _dereq_('./parseText'); -// 2.5, $5.50, 3,432, etc - -const numeric = /^-?(\$|€|¥|£)?\.?[0-9]+[0-9,\.]*(st|nd|rd|th|rth|%)?$/; - -const parseString = function(str) { - if (numeric.test(str) === true) { - //clean up a number, like '$4,342.00' - str = str.replace(/,/g, ''); - str = str.replace(/^[\$|€|¥|£]/g, ''); - str = str.replace(/%$/, ''); - str = str.replace(/(st|nd|rd|th|rth)$/g, ''); - let num = parseFloat(str); - if (num || num === 0) { - return num; - } - } - return parseText(str); -}; - -//turn it all into a number -const parse = function(val) { - if (val === null || val === undefined || typeof val === 'number') { - return val; - } - if (typeof val === 'string') { - return parseString(val); - } - //numerical values can only be one term - if (val.terms.length === 1 && val.terms[0].tags.TextValue !== true) { - let str = val.terms[0].normal; - return parseString(str); - } - return parseText(val.out('normal')); -}; -module.exports = parse; - -},{"./parseText":69}],67:[function(_dereq_,module,exports){ -const numbers = _dereq_('../../../world/more-data/numbers'); -const fns = _dereq_('../paths').fns; - -//setup number-word data -const ones = fns.extend(numbers.ordinal.ones, numbers.cardinal.ones); -const teens = fns.extend(numbers.ordinal.teens, numbers.cardinal.teens); -const tens = fns.extend(numbers.ordinal.tens, numbers.cardinal.tens); -const multiples = fns.extend(numbers.ordinal.multiples, numbers.cardinal.multiples); - -//add this one -multiples.grand = 1000; - -module.exports = { - ones: ones, - teens: teens, - tens: tens, - multiples: multiples -}; - -},{"../../../world/more-data/numbers":220,"../paths":73}],68:[function(_dereq_,module,exports){ -'use strict'; - -//support global multipliers, like 'half-million' by doing 'million' then multiplying by 0.5 -const findModifiers = str => { - const mults = [ - { - reg: /^(minus|negative)[\s\-]/i, - mult: -1 - }, - { - reg: /^(a\s)?half[\s\-](of\s)?/i, - mult: 0.5 - } - // { - // reg: /^(a\s)?quarter[\s\-]/i, - // mult: 0.25 - // } - ]; - for (let i = 0; i < mults.length; i++) { - if (mults[i].reg.test(str) === true) { - return { - amount: mults[i].mult, - str: str.replace(mults[i].reg, '') - }; - } - } - return { - amount: 1, - str: str - }; -}; - -module.exports = findModifiers; - -},{}],69:[function(_dereq_,module,exports){ -'use strict'; -const findModifiers = _dereq_('./findModifiers'); -const words = _dereq_('./data'); -const isValid = _dereq_('./validate'); -const parseDecimals = _dereq_('./parseDecimals'); -const parseNumeric = _dereq_('./parseNumeric'); -const improperFraction = /^([0-9,\. ]+)\/([0-9,\. ]+)$/; - -//some numbers we know -const casualForms = { - // 'a few': 3, - 'a couple': 2, - 'a dozen': 12, - 'two dozen': 24, - zero: 0 -}; - -// a 'section' is something like 'fifty-nine thousand' -// turn a section into something we can add to - like 59000 -const section_sum = obj => { - return Object.keys(obj).reduce((sum, k) => { - sum += obj[k]; - return sum; - }, 0); -}; - -//turn a string into a number -const parse = function(str) { - //convert some known-numbers - if (casualForms.hasOwnProperty(str) === true) { - return casualForms[str]; - } - //'a/an' is 1 - if (str === 'a' || str === 'an') { - return 1; - } - const modifier = findModifiers(str); - str = modifier.str; - let last_mult = null; - let has = {}; - let sum = 0; - let isNegative = false; - const terms = str.split(/[ -]/); - for (let i = 0; i < terms.length; i++) { - let w = terms[i]; - w = parseNumeric(w); - if (!w || w === 'and') { - continue; - } - if (w === '-' || w === 'negative') { - isNegative = true; - continue; - } - if (w.charAt(0) === '-') { - isNegative = true; - w = w.substr(1); - } - //decimal mode - if (w === 'point') { - sum += section_sum(has); - sum += parseDecimals(terms.slice(i + 1, terms.length)); - sum *= modifier.amount; - return sum; - } - //improper fraction - const fm = w.match(improperFraction); - if (fm) { - const num = parseFloat(fm[1].replace(/[, ]/g, '')); - const denom = parseFloat(fm[2].replace(/[, ]/g, '')); - if (denom) { - sum += num / denom || 0; - } - continue; - } - //prevent mismatched units, like 'seven eleven' - if (isValid(w, has) === false) { - return null; - } - //buildOut section, collect 'has' values - if (/^[0-9\.]+$/.test(w)) { - has['ones'] = parseFloat(w); //not technically right - } else if (words.ones.hasOwnProperty(w) === true) { - has['ones'] = words.ones[w]; - } else if (words.teens.hasOwnProperty(w) === true) { - has['teens'] = words.teens[w]; - } else if (words.tens.hasOwnProperty(w) === true) { - has['tens'] = words.tens[w]; - } else if (words.multiples.hasOwnProperty(w) === true) { - let mult = words.multiples[w]; - - //something has gone wrong : 'two hundred five hundred' - if (mult === last_mult) { - return null; - } - //support 'hundred thousand' - //this one is tricky.. - if (mult === 100 && terms[i + 1] !== undefined) { - // has['hundreds']= - const w2 = terms[i + 1]; - if (words.multiples[w2]) { - mult *= words.multiples[w2]; //hundredThousand/hundredMillion - i += 1; - } - } - //natural order of things - //five thousand, one hundred.. - if (last_mult === null || mult < last_mult) { - sum += (section_sum(has) || 1) * mult; - last_mult = mult; - has = {}; - } else { - //maybe hundred .. thousand - sum += section_sum(has); - last_mult = mult; - sum = (sum || 1) * mult; - has = {}; - } - } - } - //dump the remaining has values - sum += section_sum(has); - //post-process add modifier - sum *= modifier.amount; - sum *= isNegative ? -1 : 1; - //dont return 0, if it went straight-through - if (sum === 0 && Object.keys(has).length === 0) { - return null; - } - return sum; -}; - -module.exports = parse; - -},{"./data":67,"./findModifiers":68,"./parseDecimals":70,"./parseNumeric":71,"./validate":72}],70:[function(_dereq_,module,exports){ -'use strict'; -const words = _dereq_('./data'); - -//concatenate into a string with leading '0.' -const parseDecimals = function(arr) { - let str = '0.'; - for (let i = 0; i < arr.length; i++) { - let w = arr[i]; - if (words.ones.hasOwnProperty(w) === true) { - str += words.ones[w]; - } else if (words.teens.hasOwnProperty(w) === true) { - str += words.teens[w]; - } else if (words.tens.hasOwnProperty(w) === true) { - str += words.tens[w]; - } else if (/^[0-9]$/.test(w) === true) { - str += w; - } else { - return 0; - } - } - return parseFloat(str); -}; - -module.exports = parseDecimals; - -},{"./data":67}],71:[function(_dereq_,module,exports){ -'use strict'; -//parse a string like "4,200.1" into Number 4200.1 -const parseNumeric = str => { - //remove ordinal - 'th/rd' - str = str.replace(/1st$/, '1'); - str = str.replace(/2nd$/, '2'); - str = str.replace(/3rd$/, '3'); - str = str.replace(/([4567890])r?th$/, '$1'); - //remove prefixes - str = str.replace(/^[$€¥£¢]/, ''); - //remove suffixes - str = str.replace(/[%$€¥£¢]$/, ''); - //remove commas - str = str.replace(/,/g, ''); - //split '5kg' from '5' - str = str.replace(/([0-9])([a-z]{1,2})$/, '$1'); - return str; -}; - -module.exports = parseNumeric; - -},{}],72:[function(_dereq_,module,exports){ -'use strict'; -const words = _dereq_('./data'); - -//prevent things like 'fifteen ten', and 'five sixty' -const isValid = (w, has) => { - if (words.ones.hasOwnProperty(w)) { - if (has.ones || has.teens) { - return false; - } - } else if (words.teens.hasOwnProperty(w)) { - if (has.ones || has.teens || has.tens) { - return false; - } - } else if (words.tens.hasOwnProperty(w)) { - if (has.ones || has.teens || has.tens) { - return false; - } - } - return true; -}; -module.exports = isValid; - -},{"./data":67}],73:[function(_dereq_,module,exports){ -module.exports = _dereq_('../../paths'); - -},{"../../paths":8}],74:[function(_dereq_,module,exports){ -'use strict'; -const paths = _dereq_('../../paths'); -const Terms = paths.Terms; -const parse = _dereq_('./parse'); -const fmt = _dereq_('./format'); - -// const unpackRange = function(ts) { -// if (ts.has('#NumberRange')) { -// ts.terms.forEach(t => { -// if (t.silent_term && !t._text) { -// t.text = t.silent_term; -// } -// }); -// } -// return ts; -// }; - -const parseValue = function(ts) { - ts.val = ts.match('#Value+'); - // ts.val = unpackRange(ts.val); - ts.val = ts.val.list[0]; - ts.unit = ts.match('#Unit+'); - if (ts.unit.found) { - ts.unit = ts.unit.list[0]; - } - return ts; -}; - -const isPercent = function(val, unit) { - //pre-tagged - if (val.has('#Percent') || unit.has('#Percent')) { - return true; - } - // 'five percent' - if (unit.out('normal') === 'percent') { - return true; - } - //'5%' - if (val.out('normal').match(/%$/) !== null) { - return true; - } - return false; -}; - -//set the text as the same num format -const setNumber = function(ts, num) { - let str = ts.val.out(); - if (ts.has('#Ordinal')) { - if (ts.has('#TextValue')) { - str = fmt.textOrdinal(num); //ordinal text - } else { - str = fmt.ordinal(num); //ordinal number - } - } else if (ts.has('#TextValue')) { - str = fmt.text(num); //cardinal text - } else if (ts.has('#NiceNumber')) { - str = fmt.nice(num); //8,929 number - } else { - str = fmt.cardinal(num); //cardinal number - } - //add the unit at the end - if (ts.unit.found) { - str += ts.unit.out('text'); - } - ts = ts.replaceWith(str, true); - return parseValue(ts); -}; - -const Value = function(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - parseValue(this); -}; - -//Terms inheritence -Value.prototype = Object.create(Terms.prototype); - -const methods = { - data: function() { - let num = parse(this.val); - return { - number: num, - nice: fmt.nice(num), - ordinal: fmt.ordinal(num), - niceOrdinal: fmt.niceOrdinal(num), - text: fmt.text(num), - textOrdinal: fmt.textOrdinal(num), - unit: this.unit.out('normal') - }; - }, - number: function() { - return parse(this.val); - }, - // /** five -> '5' */ - toNumber: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#Ordinal')) { - str = fmt.ordinal(num); - } else { - str = String(num); - //convert 'five percent' -> '5%' - if (isPercent(this.val, this.unit)) { - str = str + '%'; - this.unit.delete(); - } - } - // let before = this.terms[0].whitespace.before; - // let after = this.terms[this.terms.length - 1].whitespace.after; - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('NumericValue'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - // this.whitespace.before(before); - // this.whitespace.after(after); - } - return this; - }, - // /**5 -> 'five' */ - toText: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#Ordinal')) { - str = fmt.textOrdinal(num); - } else { - str = fmt.text(num); - //add percent - if (isPercent(this.val, this.unit)) { - str = str + ' percent'; - } - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('TextValue'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5th -> 5 */ - toCardinal: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#TextValue')) { - str = fmt.text(num); - } else { - str = num; - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('Cardinal'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5 -> 5th */ - toOrdinal: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#TextValue')) { - str = fmt.textOrdinal(num); - } else { - str = fmt.ordinal(num); - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('Ordinal'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5900 -> 5,900 */ - toNice: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#Ordinal')) { - str = fmt.niceOrdinal(num); - } else { - str = fmt.nice(num); - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('NumericValue'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - /** seven + 2 = nine */ - add: function(n) { - if (!n) { - return this; - } - let num = parse(this.val) || 0; - num += n; //add it - return setNumber(this, num); - }, - /** seven - 2 = five */ - subtract: function(n) { - if (!n) { - return this; - } - let num = parse(this.val) || 0; - num -= n; //subtract it - return setNumber(this, num); - }, - /**seven -> 'eight' */ - increment: function() { - return this.add(1); - }, - /**seven -> 'six' */ - decrement: function() { - return this.subtract(1); - } -}; - -Object.keys(methods).forEach(k => { - Value.prototype[k] = methods[k]; -}); -module.exports = Value; - -},{"../../paths":8,"./format":59,"./parse":66}],75:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('../../text'); -const Verb = _dereq_('./verb'); - -//the () subset class -const methods = { - conjugation: function(verbose) { - return this.list.map(ts => { - return ts.conjugation(verbose); - }); - }, - conjugate: function(num, verbose) { - //suppport only conjugating one verb in our result.. - if (num !== null && typeof num === 'number' && this.list[num]) { - return this.list[num].conjugate(verbose); - } - //otherwise, return an array of conjugations - return this.list.map(ts => { - return ts.conjugate(verbose); - }); - }, - - /** plural/singular **/ - isPlural: function() { - this.list = this.list.filter(ts => { - return ts.isPlural(); - }); - return this; - }, - isSingular: function() { - this.list = this.list.filter(ts => { - return !ts.isPlural(); - }); - return this; - }, - - /** negation **/ - isNegative: function() { - this.list = this.list.filter(ts => { - return ts.isNegative(); - }); - return this; - }, - isPositive: function() { - this.list = this.list.filter(ts => { - return !ts.isNegative(); - }); - return this; - }, - toNegative: function() { - this.list = this.list.map(ts => { - return ts.toNegative(); - }); - return this; - }, - toPositive: function() { - this.list.forEach(ts => { - ts.toPositive(); - }); - return this; - }, - - /** tense **/ - toPastTense: function() { - this.list.forEach(ts => { - ts.toPastTense(); - }); - return this; - }, - toPresentTense: function() { - this.list.forEach(ts => { - ts.toPresentTense(); - }); - return this; - }, - toFutureTense: function() { - this.list.forEach(ts => { - ts.toFutureTense(); - }); - return this; - }, - toInfinitive: function() { - this.list.forEach(ts => { - ts.toInfinitive(); - }); - return this; - }, - toGerund: function() { - this.list.forEach(ts => { - ts.toGerund(); - }); - return this; - }, - asAdjective: function() { - return this.list.map(ts => ts.asAdjective()); - } -}; -//aliases -methods.toContinuous = methods.toGerund; - -const find = function(r, n) { - r = r.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); - r = r.splitAfter('#Comma'); - r.list.forEach(ts => { - ts.terms.forEach( t => { - if(t.whitespace.before.match('/')){ - r.splitOn(t.normal) - } - }) - }) - r = r.if('#Verb'); //this should be (much) smarter - if (typeof n === 'number') { - r = r.get(n); - } - r.list = r.list.map(ts => { - return new Verb(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return new Text(r.list, this.world, this.parent); -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./verb":94}],76:[function(_dereq_,module,exports){ -'use strict'; -const predict = _dereq_('./methods/predict'); -const isPlural = _dereq_('./methods/isPlural'); - -//'walking' - aka progressive -const isContinuous = function(ts) { - return ts.match('#Gerund').found; -}; - -//will not walk -const isNegative = function(ts) { - let negs = ts.match('#Negative').list; - if (negs.length === 2) { - return false; - } - if (negs.length === 1) { - return true; - } - return false; -}; - -//been walked by.. -const isPassive = function(ts) { - if (ts.match('is being #PastTense').found) { - return true; - } - if (ts.match('(had|has) been #PastTense').found) { - return true; - } - if (ts.match('will have been #PastTense').found) { - return true; - } - return false; -}; - -//had walked -const isPerfect = function(ts) { - if (ts.match('^(had|have) #PastTense')) { - return true; - } - return false; -}; - -//should walk, could walk -const getModal = function(ts) { - let modal = ts.match('#Modal'); - if (!modal.found) { - return null; - } - return modal.out('normal'); -}; - -//past/present/future -const getTense = function(ts) { - //look at the preceding words - if (ts.auxiliary.found) { - //'will' - if (ts.match('will have #PastTense').found) { - return 'Past'; - } - if (ts.auxiliary.match('will').found) { - return 'Future'; - } - //'was' - if (ts.auxiliary.match('was').found) { - return 'Past'; - } - } - //look at the main verb tense - if (ts.verb) { - const tenses = { - PastTense: 'Past', - FutureTense: 'Future', - FuturePerfect: 'Future', - }; - let tense = predict(ts.verb); //yikes - return tenses[tense] || 'Present'; - } - return 'Present'; -}; - -// const isImperative = function(ts) {}; -// const isConditional = function(ts) {}; - -// detect signals in Auxiliary verbs -// 'will' -> future, 'have'->perfect, modals, negatives, adverbs -const interpret = (ts) => { - let isNeg = isNegative(ts); - // let aux = ts.Auxiliary.clone(); - // aux = aux.not('(#Negative|#Adverb)'); - let obj = { - negative: isNeg, - continuous: isContinuous(ts), - passive: isPassive(ts), - perfect: isPerfect(ts), - plural: isPlural(ts), - modal: getModal(ts), - tense: getTense(ts), - }; - return obj; -}; -module.exports = interpret; - -},{"./methods/isPlural":86,"./methods/predict":87}],77:[function(_dereq_,module,exports){ -'use strict'; -const checkIrregulars = _dereq_('./irregulars'); -const suffixPass = _dereq_('./suffixes'); -const toActor = _dereq_('./toActor'); -const generic = _dereq_('./generic'); -const predict = _dereq_('../predict'); -const toInfinitive = _dereq_('../toInfinitive'); -const toBe = _dereq_('./toBe'); - -//turn a verb into all it's forms -const conjugate = function(t, world) { - //handle is/was/will-be specially - if (t.normal === 'is' || t.normal === 'was' || t.normal === 'will') { - return toBe(); - } - - //dont conjugate didn't - if (t.tags.Contraction) { - t.text = t.silent_term; - } - let all = { - PastTense: null, - PresentTense: null, - Infinitive: null, - Gerund: null, - Actor: null - }; - //first, get its current form - let form = predict(t); - if (form) { - all[form] = t.normal; - } - if (form !== 'Infinitive') { - all['Infinitive'] = toInfinitive(t, world) || ''; - } - //check irregular forms - const irregObj = checkIrregulars(all['Infinitive'], world) || {}; - Object.keys(irregObj).forEach(k => { - if (irregObj[k] && !all[k]) { - all[k] = irregObj[k]; - } - }); - //ok, send this infinitive to all conjugators - let inf = all['Infinitive'] || t.normal; - - //check suffix rules - const suffObj = suffixPass(inf); - Object.keys(suffObj).forEach(k => { - if (suffObj[k] && !all[k]) { - all[k] = suffObj[k]; - } - }); - //ad-hoc each missing form - //to Actor - if (!all.Actor) { - all.Actor = toActor(inf); - } - - //use fallback, generic transformations - Object.keys(all).forEach(k => { - if (!all[k] && generic[k]) { - all[k] = generic[k](all); - } - }); - - return all; -}; - -module.exports = conjugate; - -},{"../predict":87,"../toInfinitive":90,"./generic":80,"./irregulars":82,"./suffixes":83,"./toActor":84,"./toBe":85}],78:[function(_dereq_,module,exports){ -module.exports = [ - { - reg: /(eave)$/i, - repl: { - pr: '$1s', - pa: '$1d', - gr: 'eaving', - ar: '$1r' - } - }, - { - reg: /(ink)$/i, - repl: { - pr: '$1s', - pa: 'unk', - gr: '$1ing', - ar: '$1er' - } - }, - { - reg: /([aeiou]k)in$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing', - ar: '$1er' - } - }, - { - reg: /(end)$/i, - repl: { - pr: '$1s', - pa: 'ent', - gr: '$1ing', - ar: '$1er' - } - }, - { - reg: /(ide)$/i, - repl: { - pr: '$1s', - pa: 'ode', - gr: 'iding', - ar: 'ider' - } - }, - { - reg: /(ake)$/i, - repl: { - pr: '$1s', - pa: 'ook', - gr: 'aking', - ar: '$1r' - } - }, - { - reg: /(eed)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing', - ar: '$1er' - } - }, - - { - reg: /(e)(ep)$/i, - repl: { - pr: '$1$2s', - pa: '$1pt', - gr: '$1$2ing', - ar: '$1$2er' - } - }, { - reg: /(a[tg]|i[zn]|ur|nc|gl|is)e$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing', - prt: '$1en' - } - }, { - reg: /([i|f|rr])y$/i, - repl: { - pr: '$1ies', - pa: '$1ied', - gr: '$1ying' - } - }, { - reg: /([td]er)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /([bd]l)e$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(ish|tch|ess)$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(ion|end|e[nc]t)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(om)e$/i, - repl: { - pr: '$1es', - pa: 'ame', - gr: '$1ing' - } - }, { - reg: /(.eat)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /([aeiu])([pt])$/i, - repl: { - pr: '$1$2s', - pa: '$1$2', - gr: '$1$2$2ing' - } - }, { - reg: /(er)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(en)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - }, - }, { - reg: /(ed)$/i, - repl: { - pr: '$1s', - pa: '$1ded', - ar: '$1der', - gr: '$1ding' - }, - }, - { - reg: /(..)(ow)$/i, - repl: { - pr: '$1$2s', - pa: '$1ew', - gr: '$1$2ing', - prt: '$1$2n' - } - }, - { - reg: /(..)([cs]h)$/i, - repl: { - pr: '$1$2es', - pa: '$1$2ed', - gr: '$1$2ing' - }, - }, - { - reg: /([^aeiou][ou])(g|d)$/i, - repl: { - pr: '$1$2s', - pa: '$1$2$2ed', - gr: '$1$2$2ing' - }, - }, - { - reg: /([^aeiou][aeiou])(b|t|p|m)$/i, - repl: { - pr: '$1$2s', - pa: '$1$2$2ed', - gr: '$1$2$2ing' - }, - }, - { - reg: /([aeiou]zz)$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } - } -]; - -},{}],79:[function(_dereq_,module,exports){ -'use strict'; -const checkIrregulars = _dereq_('./irregulars'); -const suffixPass = _dereq_('./suffixes'); -const generic = _dereq_('./generic'); -//this method is the same as regular conjugate, but optimised for use in the lexicon during warm-up. -//it's way faster because it knows input is already infinitive - -const want = ['Gerund', 'PastTense', 'PresentTense']; - -const fasterConjugate = function(inf, world) { - let all = { - Infinitive: inf - }; - //check irregulars list - if (world && world.conjugations) { - const irregObj = checkIrregulars(all['Infinitive'], world); - if (irregObj !== null) { - Object.keys(irregObj).forEach(k => { - if (irregObj[k] && !all[k]) { - all[k] = irregObj[k]; - } - }); - } - } - //check suffix rules - const suffObj = suffixPass(inf); - Object.keys(suffObj).forEach(k => { - if (suffObj[k] && !all[k]) { - all[k] = suffObj[k]; - } - }); - for (let i = 0; i < want.length; i++) { - if (all[want[i]] === undefined) { - all[want[i]] = generic[want[i]](all); - } - } - return all; -}; -module.exports = fasterConjugate; -// console.log(fasterConjugate('repeat')); - -},{"./generic":80,"./irregulars":82,"./suffixes":83}],80:[function(_dereq_,module,exports){ -'use strict'; -//non-specifc, 'hail-mary' transforms from infinitive, into other forms -const hasY = /[bcdfghjklmnpqrstvwxz]y$/; -const generic = { - - Gerund: (o) => { - const inf = o.Infinitive; - if (inf.charAt(inf.length - 1) === 'e') { - return inf.replace(/e$/, 'ing'); - } - return inf + 'ing'; - }, - - PresentTense: (o) => { - const inf = o.Infinitive; - if (inf.charAt(inf.length - 1) === 's') { - return inf + 'es'; - } - if (hasY.test(inf) === true) { - return inf.slice(0, -1) + 'ies'; - } - return inf + 's'; - }, - - PastTense: (o) => { - const inf = o.Infinitive; - if (inf.charAt(inf.length - 1) === 'e') { - return inf + 'd'; - } - if (inf.substr(-2) === 'ed') { - return inf; - } - if (hasY.test(inf) === true) { - return inf.slice(0, -1) + 'ied'; - } - return inf + 'ed'; - }, - - // FutureTense: (o) => { - // return 'will ' + o.Infinitive; - // }, - // - // PerfectTense: (o) => { - // return 'have ' + (o.Participle || o.PastTense); - // }, - // - // Pluperfect: (o) => { - // if (o.PastTense) { - // return 'had ' + o.PastTense; - // } - // return null; - // }, - // FuturePerfect: (o) => { - // if (o.PastTense) { - // return 'will have ' + o.PastTense; - // } - // return null; - // } - -}; - -module.exports = generic; - -},{}],81:[function(_dereq_,module,exports){ -'use strict'; -const conjugate = _dereq_('./conjugate'); -const toBe = _dereq_('./toBe'); - -const addAdverbs = function(obj, vb) { - if (vb.adverbs.found) { - //does the adverb go at the start or end? - let isFirst = vb.first().match('#Adverb').found; - Object.keys(obj).forEach(k => { - if (isFirst) { - obj[k] = vb.adverbs.out() + ' ' + obj[k]; - } else { - obj[k] = obj[k] + vb.adverbs.out(); - } - }); - } - return obj; -}; - -//conjugation using auxillaries+adverbs and stuff -const multiWordConjugate = (vb, verbose) => { - let isNegative = vb.negative.found; - let isPlural = vb.isPlural(); - //handle 'to be' verb seperately - if (vb.verb.tags.Copula || (vb.verb.normal === 'be' && vb.auxiliary.match('will').found)) { - let isI = false; - //account for 'i is' -> 'i am' irregular - if (vb.parent && vb.parent.has('i #Adverb? #Copula')) { - isI = true; - } - let copulas = toBe(isPlural, isNegative, isI); - return addAdverbs(copulas, vb); - } - let obj = conjugate(vb.verb, vb.world, verbose); - //apply particles - if (vb.particle.found) { - Object.keys(obj).forEach(k => { - obj[k] = obj[k] + vb.particle.out(); - }); - } - //apply negative - if (isNegative) { - obj.PastTense = 'did not ' + obj.Infinitive; - obj.PresentTense = 'does not ' + obj.Infinitive; - obj.Gerund = 'not ' + obj.Gerund; - } - //future Tense is pretty straightforward - if (!obj.FutureTense) { - if (isNegative) { - obj.FutureTense = 'will not ' + obj.Infinitive; - } else { - obj.FutureTense = 'will ' + obj.Infinitive; - } - } - //apply adverbs - obj = addAdverbs(obj, vb); - return obj; -}; -module.exports = multiWordConjugate; - -},{"./conjugate":77,"./toBe":85}],82:[function(_dereq_,module,exports){ -'use strict'; -// let irregulars = require('../../../../lexicon/uncompressed/irregularVerbs').irregulars; //weeee! -const fns = _dereq_('../../../../fns'); //weeee! -const forms = ['Participle', 'Gerund', 'PastTense', 'PresentTense', 'FuturePerfect', 'PerfectTense', 'Actor']; - -const checkIrregulars = function(str, world) { - const irregulars = world.conjugations; - const infArr = Object.keys(irregulars); - //check irregulars in world - if (world && world.conjugations && world.conjugations.hasOwnProperty(str) === true) { - return world.conjugations[str]; - } - //fast infinitive lookup - if (irregulars.hasOwnProperty(str) === true) { - let obj = fns.copy(irregulars[str]); - obj.Infinitive = str; - return obj; - } - //longer check of known-verb forms - for (let i = 0; i < infArr.length; i++) { - for (let o = 0; o < forms.length; o++) { - let irObj = irregulars[infArr[i]]; - if (irObj[forms[o]] === str) { - let obj = fns.copy(irObj); - obj.Infinitive = infArr[i]; - return obj; - } - } - } - return {}; -}; - -module.exports = checkIrregulars; -// console.log(checkIrregulars('bit')); - -},{"../../../../fns":3}],83:[function(_dereq_,module,exports){ -'use strict'; -const rules = _dereq_('./data/rules'); -const mapping = { - pr: 'PresentTense', - pa: 'PastTense', - gr: 'Gerund', - prt: 'Participle', - ar: 'Actor', -}; -const keys = Object.keys(mapping); - -//check suffix rules -const suffixPass = function(inf) { - let found = {}; - for(let i = 0; i < rules.length; i++) { - if (rules[i].reg.test(inf) === true) { - let obj = rules[i].repl; - for(let o = 0; o < keys.length; o++) { - if (obj.hasOwnProperty(keys[o]) === true) { - let key = mapping[keys[o]]; - // console.log(rules[i]); - found[key] = inf.replace(rules[i].reg, obj[keys[o]]); - } - } - return found; - } - } - return found; -}; - -module.exports = suffixPass; - -},{"./data/rules":78}],84:[function(_dereq_,module,exports){ -'use strict'; -//turn 'walk' into 'walker' -const irregulars = { - 'tie': 'tier', - 'dream': 'dreamer', - 'sail': 'sailer', - 'run': 'runner', - 'rub': 'rubber', - 'begin': 'beginner', - 'win': 'winner', - 'claim': 'claimant', - 'deal': 'dealer', - 'spin': 'spinner' -}; -const dont = { - 'aid': 1, - 'fail': 1, - 'appear': 1, - 'happen': 1, - 'seem': 1, - 'try': 1, - 'say': 1, - 'marry': 1, - 'be': 1, - 'forbid': 1, - 'understand': 1, - 'bet': 1 -}; -const rules = [{ - 'reg': /e$/i, - 'repl': 'er' -}, { - 'reg': /([aeiou])([mlgp])$/i, - 'repl': '$1$2$2er' -}, { - 'reg': /([rlf])y$/i, - 'repl': '$1ier' -}, { - 'reg': /^(.?.[aeiou])t$/i, - 'repl': '$1tter' -}]; - -const toActor = function(inf) { - //check blacklist - if (dont[inf]) { - return null; - } - //check irregulars - if (irregulars.hasOwnProperty(inf)) { - return irregulars[inf]; - } - //try rules - for (let i = 0; i < rules.length; i++) { - if (rules[i].reg.test(inf) === true) { - return inf.replace(rules[i].reg, rules[i].repl); - } - } - //yup, - return inf + 'er'; -}; - -module.exports = toActor; - -},{}],85:[function(_dereq_,module,exports){ -'use strict'; -//too many special cases for is/was/will be -const toBe = (isPlural, isNegative, isI) => { - let obj = { - PastTense: 'was', - PresentTense: 'is', - FutureTense: 'will be', - Infinitive: 'is', - Gerund: 'being', - Actor: '', - PerfectTense: 'been', - Pluperfect: 'been', - }; - //"i is" -> "i am" - if (isI === true) { - obj.PresentTense = 'am'; - obj.Infinitive = 'am'; - } - if (isPlural) { - obj.PastTense = 'were'; - obj.PresentTense = 'are'; - obj.Infinitive = 'are'; - } - if (isNegative) { - obj.PastTense += ' not'; - obj.PresentTense += ' not'; - obj.FutureTense = 'will not be'; - obj.Infinitive += ' not'; - obj.PerfectTense = 'not ' + obj.PerfectTense; - obj.Pluperfect = 'not ' + obj.Pluperfect; - obj.Gerund = 'not ' + obj.Gerund; - } - return obj; -}; -module.exports = toBe; - -},{}],86:[function(_dereq_,module,exports){ -'use strict'; -//sometimes you can tell if a verb is plural/singular, just by the verb -// i am / we were -//othertimes you need its noun 'we walk' vs 'i walk' -const isPlural = (vb) => { - if (vb.match('(are|were|does)').found) { - return true; - } - if (vb.match('(is|am|do|was)').found) { - return false; - } - //consider its prior noun - let noun = vb.getNoun(); - if (noun && noun.found) { - if (noun.match('#Plural').found) { - return true; - } - if (noun.match('#Singular').found) { - return false; - } - } - return null; -}; -module.exports = isPlural; - -},{}],87:[function(_dereq_,module,exports){ -'use strict'; -const suffix_rules = _dereq_('./suffix_rules'); - -const goodTypes = { - Infinitive: true, - Gerund: true, - PastTense: true, - PresentTense: true, - FutureTense: true, - PerfectTense: true, - Pluperfect: true, - FuturePerfect: true, - Participle: true -}; - -const predictForm = function(term) { - //do we already know the form? - const keys = Object.keys(goodTypes); - for (let i = 0; i < keys.length; i++) { - if (term.tags[keys[i]]) { - return keys[i]; - } - } - //consult our handy suffix rules - const arr = Object.keys(suffix_rules); - for (let i = 0; i < arr.length; i++) { - const substr = term.normal.substr(-arr[i].length); - if (substr === arr[i] && term.normal.length > arr[i].length) { - return suffix_rules[arr[i]]; - } - } - return null; -}; - -module.exports = predictForm; - -},{"./suffix_rules":88}],88:[function(_dereq_,module,exports){ -'use strict'; -//suffix signals for verb tense, generated from test data -const compact = { - 'Gerund': [ - 'ing' - ], - 'Actor': [ - 'erer' - ], - 'Infinitive': [ - 'ate', - 'ize', - 'tion', - 'rify', - 'then', - 'ress', - 'ify', - 'age', - 'nce', - 'ect', - 'ise', - 'ine', - 'ish', - 'ace', - 'ash', - 'ure', - 'tch', - 'end', - 'ack', - 'and', - 'ute', - 'ade', - 'ock', - 'ite', - 'ase', - 'ose', - 'use', - 'ive', - 'int', - 'nge', - 'lay', - 'est', - 'ain', - 'ant', - 'ent', - 'eed', - 'er', - 'le', - 'own', - 'unk', - 'ung', - 'en' - ], - 'PastTense': [ - 'ed', - 'lt', - 'nt', - 'pt', - 'ew', - 'ld' - ], - 'PresentTense': [ - 'rks', - 'cks', - 'nks', - 'ngs', - 'mps', - 'tes', - 'zes', - 'ers', - 'les', - 'acks', - 'ends', - 'ands', - 'ocks', - 'lays', - 'eads', - 'lls', - 'els', - 'ils', - 'ows', - 'nds', - 'ays', - 'ams', - 'ars', - 'ops', - 'ffs', - 'als', - 'urs', - 'lds', - 'ews', - 'ips', - 'es', - 'ts', - 'ns', - 's' - ] -}; -const suffix_rules = {}; -const keys = Object.keys(compact); -const l = keys.length; - -for (let i = 0; i < l; i++) { - let l2 = compact[keys[i]].length; - for (let o = 0; o < l2; o++) { - suffix_rules[compact[keys[i]][o]] = keys[i]; - } -} -module.exports = suffix_rules; - -},{}],89:[function(_dereq_,module,exports){ -'use strict'; -//turn a infinitiveVerb, like "walk" into an adjective like "walkable" - -const rules = [ - [/y$/, 'i'], //relay - reliable - [/([aeiou][n])$/, '$1n'], //win - winnable -]; - -//convert - 'convertible' -//http://grammarist.com/usage/able-ible/ -//http://blog.oxforddictionaries.com/2012/10/ibles-and-ables/ -const ible_suffixes = { - collect: true, - exhaust: true, - convert: true, - digest: true, - discern: true, - dismiss: true, - reverse: true, - access: true, - collapse: true, - express: true -}; - -const irregulars = { - eat: 'edible', - hear: 'audible', - see: 'visible', - defend: 'defensible', - write: 'legible', - move: 'movable', - divide: 'divisible', - perceive: 'perceptible' -}; - -//takes an infitive verb, and returns an adjective form -const toAdjective = function(str) { - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - for(let i = 0; i < rules.length; i++) { - if (rules[i][0].test(str) === true) { - str = str.replace(rules[i][0], rules[i][1]); - } - } - //ible/able - let adj = str + 'able'; - if (ible_suffixes[str]) { - adj = str + 'ible'; - } - return adj; -}; - -module.exports = toAdjective; - -},{}],90:[function(_dereq_,module,exports){ -'use strict'; -//turn any verb into its infinitive form -const rules = _dereq_('./rules'); -const predict = _dereq_('../predict'); - -const toInfinitive = function(t, world) { - const irregulars = world.cache.toInfinitive || {}; //verb_mapping(world.conjugations); //TODO: do this at world cache - if (t.tags.Infinitive) { - return t.normal; - } - //check the irregular verb conjugations - if (irregulars.hasOwnProperty(t.normal) === true) { - return irregulars[t.normal]; - } - //check the suffix rules - let form = predict(t); - if (rules[form]) { - for (let i = 0; i < rules[form].length; i++) { - let rule = rules[form][i]; - if (t.normal.match(rule.reg)) { - return t.normal.replace(rule.reg, rule.to); - } - } - } - return t.normal; -}; - -module.exports = toInfinitive; - -},{"../predict":87,"./rules":91}],91:[function(_dereq_,module,exports){ -'use strict'; -//rules for turning a verb into infinitive form -let rules = { - Participle: [ - { - reg: /own$/i, - to: 'ow' - }, - { - reg: /(.)un([g|k])$/i, - to: '$1in$2' - } - ], - Actor: [ - { - reg: /(er)er$/i, - to: '$1' - } - ], - PresentTense: [ - { - reg: /(..)(ies)$/i, - to: '$1y' - }, { - reg: /(tch|sh)es$/i, - to: '$1' - }, { - reg: /(ss|zz)es$/i, - to: '$1' - }, { - reg: /([tzlshicgrvdnkmu])es$/i, - to: '$1e' - }, { - reg: /(n[dtk]|c[kt]|[eo]n|i[nl]|er|a[ytrl])s$/i, - to: '$1' - }, { - reg: /(ow)s$/i, - to: '$1' - }, { - reg: /(op)s$/i, - to: '$1' - }, { - reg: /([eirs])ts$/i, - to: '$1t' - }, { - reg: /(ll)s$/i, - to: '$1' - }, { - reg: /(el)s$/i, - to: '$1' - }, { - reg: /(ip)es$/i, - to: '$1e' - }, { - reg: /ss$/i, - to: 'ss' - }, { - reg: /s$/i, - to: '' - }], - Gerund: [ - { - reg: /pping$/i, - to: 'p' - }, { - reg: /lling$/i, - to: 'll' - }, { - reg: /tting$/i, - to: 't' - }, { - reg: /dding$/i, - to: 'd' - }, { - reg: /ssing$/i, - to: 'ss' - }, { - reg: /(..)gging$/i, - to: '$1g' - }, { - reg: /([^aeiou])ying$/i, - to: '$1y' - }, { - reg: /([^ae]i.)ing$/i, - to: '$1e' - }, { - reg: /(ea.)ing$/i, - to: '$1' - }, { - reg: /(u[rtcb]|[bdtpkg]l|n[cg]|a[gdkvtc]|[ua]s|[dr]g|yz|o[rlsp]|cre)ing$/i, - to: '$1e' - }, { - reg: /(ch|sh)ing$/i, - to: '$1' - }, { - reg: /(..)ing$/i, - to: '$1' - }], - PastTense: [ - { - reg: /(ued)$/i, - to: 'ue' - }, { - reg: /a([^aeiouy])ed$/i, - to: 'a$1e' - }, { - reg: /([aeiou]zz)ed$/i, - to: '$1' - }, { - reg: /(e|i)lled$/i, - to: '$1ll' - }, { - reg: /(.)(sh|ch)ed$/i, - to: '$1$2' - }, { - reg: /(tl|gl)ed$/i, - to: '$1e' - }, { - reg: /(um?pt?)ed$/i, - to: '$1' - }, { - reg: /(ss)ed$/i, - to: '$1' - }, { - reg: /pped$/i, - to: 'p' - }, { - reg: /tted$/i, - to: 't' - }, { - reg: /(..)gged$/i, - to: '$1g' - }, { - reg: /(..)lked$/i, - to: '$1lk' - }, { - reg: /([^aeiouy][aeiou])ked$/i, - to: '$1ke' - }, { - reg: /(.[aeiou])led$/i, - to: '$1l' - }, { - reg: /(..)(h|ion|n[dt]|ai.|[cs]t|pp|all|ss|tt|int|ail|ld|en|oo.|er|k|pp|w|ou.|rt|ght|rm)ed$/i, - to: '$1$2' - }, { - reg: /(.ut)ed$/i, - to: '$1e' - }, { - reg: /(.pt)ed$/i, - to: '$1' - }, { - reg: /(us)ed$/i, - to: '$1e' - }, { - reg: /(..[^aeiouy])ed$/i, - to: '$1e' - }, { - reg: /(..)ied$/i, - to: '$1y' - }, { - reg: /(.o)ed$/i, - to: '$1o' - }, { - reg: /(..i)ed$/i, - to: '$1' - }, { - reg: /(.a[^aeiou])ed$/i, - to: '$1' - }, { - reg: /([rl])ew$/i, - to: '$1ow' - }, { - reg: /([pl])t$/i, - to: '$1t' - }] -}; -module.exports = rules; - -},{}],92:[function(_dereq_,module,exports){ -//these are contractions with a implicit verb. -const expand = function(vb) { - vb.match('#Contraction+').list.forEach((ts) => { - if (ts.has('#Verb')) { - ts.terms.forEach((t) => { - if (t.silent_term) { - //this term also needs a space now too - if (!t.text) { - t.whitespace.before = ' '; - } - t._text = t.silent_term; - //handle (some) capitalization - if (t.tags.TitleCase) { - t.toTitleCase(); - } - t.normalize(); - t.silent_term = null; - t.unTag('Contraction', 'expanded'); - } - }); - } - }); - return vb; -}; -module.exports = expand; - -},{}],93:[function(_dereq_,module,exports){ -'use strict'; -//turns a verb negative - may not have enough information to do it properly -// (eg 'did not eat' vs 'does not eat') - needs the noun -const toInfinitive = _dereq_('./methods/toInfinitive'); - -//this methods operate on parentTerms, so return subset -const getVerb = function(ts) { - ts = ts.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); - ts = ts.splitAfter('#Comma'); - return ts.list[0]; -}; - -const toNegative = ts => { - //would not walk - let modal = ts.match('#Auxiliary').first(); //.notIf('(is|are|was|will|has|had)').first(); //.first(); - if (modal.found) { - let index = modal.list[0].index(); - let vb = ts.parentTerms.insertAt(index + 1, 'not', 'Verb'); - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //words that pair easily with a 'not' - 'is not' - let copula = ts.match('(#Copula|will|has|had|do)').first(); - if (copula.found) { - let index = copula.list[0].index(); - let vb = ts.parentTerms.insertAt(index + 1, 'not', 'Verb'); - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - let isPlural = ts.isPlural(); - - //walked -> did not walk - let past = ts.match('#PastTense').last(); - if (past.found) { - // past.debug(); - let first = past.list[0]; - let index = first.index(); - first.terms[0].text = toInfinitive(first.terms[0], ts.world); - let vb = ts.parentTerms.insertAt(index, 'did not', 'Verb'); - //add 'do not'? - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //walks -> does not walk - let pres = ts.match('#PresentTense').first(); - if (pres.found) { - let first = pres.list[0]; - let index = first.index(); - first.terms[0].text = toInfinitive(first.terms[0], ts.world); - //some things use 'do not', everything else is 'does not' - let noun = ts.getNoun(); - let vb = null; - if (noun.match('(i|we|they|you)').found) { - vb = ts.parentTerms.insertAt(index, 'do not', 'Verb'); - } else { - vb = ts.parentTerms.insertAt(index, 'does not', 'Verb'); - } - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //not walking - let gerund = ts.match('#Gerund').last(); - if (gerund.found) { - let index = gerund.list[0].index(); - let vb = ts.parentTerms.insertAt(index, 'not', 'Verb'); - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //walk -> do not walk - let verb = ts.match('#Verb').last(); - if (verb.found) { - let first = verb.list[0]; - let index = first.index(); - first.terms[0].text = toInfinitive(first.terms[0], ts.world); - let vb = ts; - if (isPlural) { - vb = ts.parentTerms.insertAt(index - 1, 'do not', 'Verb'); - } else { - vb = ts.parentTerms.insertAt(index - 1, 'does not', 'Verb'); - } - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - return ts; -}; -module.exports = toNegative; - -},{"./methods/toInfinitive":90}],94:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../paths').Terms; -const conjugate = _dereq_('./methods/conjugate'); -const toAdjective = _dereq_('./methods/toAdjective'); -const interpret = _dereq_('./interpret'); -const toNegative = _dereq_('./toNegative'); -const isPlural = _dereq_('./methods/isPlural'); -const expand = _dereq_('./methods/verbContraction'); - -const parse = function(r) { - let original = r; - r.negative = r.match('#Negative'); - r.adverbs = r.match('#Adverb'); - let aux = r.clone().not('(#Adverb|#Negative)'); - r.verb = aux - .match('#Verb') - .not('#Particle') - .last(); - r.particle = aux.match('#Particle').last(); - if (r.verb.found) { - let str = r.verb.out('normal'); - r.auxiliary = original.not(str).not('(#Adverb|#Negative)'); - r.verb = r.verb.list[0].terms[0]; - // r.auxiliary = aux.match('#Auxiliary+'); - } else { - r.verb = original.terms[0]; - r.auxiliary = aux.not('.'); - } - return r; -}; - -const methods = { - parse: function() { - return parse(this); - }, - data: function(verbose) { - return { - text: this.out('text'), - normal: this.out('normal'), - parts: { - negative: this.negative.out('normal'), - auxiliary: this.auxiliary.out('normal'), - verb: this.verb.out('normal'), - particle: this.particle.out('normal'), - adverbs: this.adverbs.out('normal') - }, - interpret: interpret(this, verbose), - conjugations: this.conjugate() - }; - }, - getNoun: function() { - if (!this.refTerms) { - return null; - } - let str = '#Adjective? #Noun+ ' + this.out('normal'); - return this.refTerms.match(str).match('#Noun+'); - }, - //which conjugation is this right now? - conjugation: function() { - return interpret(this, false).tense; - }, - //blast-out all forms - conjugate: function(verbose) { - return conjugate(this, verbose); - }, - - isPlural: function() { - return isPlural(this); - }, - /** negation **/ - isNegative: function() { - return this.match('#Negative').list.length === 1; - }, - isPerfect: function() { - return this.auxiliary.match('(have|had)').found; - }, - toNegative: function() { - if (this.isNegative()) { - return this; - } - return toNegative(this); - }, - toPositive: function() { - return this.match('#Negative').delete(); - }, - - /** conjugation **/ - toPastTense: function() { - if (this.has('#Contraction')) { - this.list = expand(this.parentTerms).list; - } - let obj = this.conjugate(); - let end = obj.PastTense; - let r = this.replaceWith(end, false); - r.verb.tag('#PastTense'); - return r; - }, - toPresentTense: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let r = this.replaceWith(obj.PresentTense, false); - r.verb.tag('#PresentTense'); - return r; - }, - toFutureTense: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let r = this.replaceWith(obj.FutureTense, false); - r.verb.tag('#FutureTense'); - return r; - }, - toInfinitive: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let r = this.replaceWith(obj.Infinitive, false); - r.verb.tag('#Infinitive'); - return r; - }, - toGerund: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let aux = 'is'; - //support 'i am', 'we are', 'he is' - let noun = this.getNoun().out('normal'); - if (noun) { - let auxList = { - i: 'am', - we: 'are', - they: 'are', - }; - if (auxList.hasOwnProperty(noun)) { - aux = auxList[noun]; - } - } - let end = aux + ' ' + obj.Gerund; - //i would go -> i would have be going - // if (this.auxiliary && this.auxiliary.has('#Modal') && !this.auxiliary.has('will')) { - // end = this.auxiliary.match('#Modal').out() + ' have ' + end; - // } - let r = this.replaceWith(end, false); - r.verb.tag('#Gerund'); - return r; - }, - asAdjective: function() { - return toAdjective(this.verb.out('normal')); - } -}; - -const Verb = function(arr, world, refText, parentTerms) { - Terms.call(this, arr, world, refText, parentTerms); - //basic verb-phrase parsing: - return parse(this); -}; -//Terms inheritence -Verb.prototype = Object.create(Terms.prototype); -//apply methods -Object.keys(methods).forEach(k => { - Verb.prototype[k] = methods[k]; -}); -module.exports = Verb; - -},{"../../paths":8,"./interpret":76,"./methods/conjugate":81,"./methods/isPlural":86,"./methods/toAdjective":89,"./methods/verbContraction":92,"./toNegative":93}],95:[function(_dereq_,module,exports){ -'use strict'; -//the steps and processes of pos-tagging -const step = { - punctuation_step: _dereq_('./steps/01-punctuation_step'), - emoji_step: _dereq_('./steps/02-emoji_step'), - lexicon_step: _dereq_('./steps/03-lexicon_step'), - lexicon_multi: _dereq_('./steps/04-lexicon_multi'), - web_step: _dereq_('./steps/05-web_step'), - suffix_step: _dereq_('./steps/06-suffix_step'), - neighbour_step: _dereq_('./steps/07-neighbour_step'), - capital_step: _dereq_('./steps/08-capital_step'), - noun_fallback: _dereq_('./steps/09-noun_fallback'), - contraction: _dereq_('./steps/10-contraction_step'), - date_step: _dereq_('./steps/11-date_step'), - auxiliary_step: _dereq_('./steps/12-auxiliary_step'), - negation_step: _dereq_('./steps/13-negation_step'), - comma_step: _dereq_('./steps/14-comma_step'), - quotation_step: _dereq_('./steps/15-quotation_step'), - possessive_step: _dereq_('./steps/16-possessive_step'), - acronym_step: _dereq_('./steps/17-acronym_step'), - person_step: _dereq_('./steps/18-person_step'), - organization_step: _dereq_('./steps/19-organization_step'), - parentheses_step: _dereq_('./steps/20-parentheses_step'), - plural_step: _dereq_('./steps/21-plural_step'), - value_step: _dereq_('./steps/22-value_step'), - corrections: _dereq_('./steps/23-corrections'), - properNoun: _dereq_('./steps/24-proper_noun'), - custom: _dereq_('./steps/25-custom'), -}; -const tagPhrase = _dereq_('./phrase'); - -const tagger = function(ts) { - ts = step.punctuation_step(ts); - ts = step.emoji_step(ts); - ts = step.lexicon_step(ts); - ts = step.lexicon_multi(ts); - ts = step.web_step(ts); - ts = step.suffix_step(ts); - ts = step.comma_step(ts); //formerly #14 - ts = step.neighbour_step(ts); - ts = step.capital_step(ts); - ts = step.noun_fallback(ts); - ts = step.contraction(ts); - ts = step.date_step(ts); //3ms - ts = step.auxiliary_step(ts); - ts = step.negation_step(ts); - ts = step.quotation_step(ts); - ts = step.possessive_step(ts); - ts = step.acronym_step(ts); - ts = step.person_step(ts); //1ms - ts = step.organization_step(ts); - ts = step.parentheses_step(ts); - ts = step.plural_step(ts); - ts = step.value_step(ts); - ts = step.corrections(ts); //2ms - ts = step.properNoun(ts); - ts = tagPhrase(ts); - ts = step.custom(ts); - return ts; -}; - -module.exports = tagger; - -},{"./phrase":98,"./steps/01-punctuation_step":99,"./steps/02-emoji_step":100,"./steps/03-lexicon_step":101,"./steps/04-lexicon_multi":102,"./steps/05-web_step":103,"./steps/06-suffix_step":104,"./steps/07-neighbour_step":105,"./steps/08-capital_step":106,"./steps/09-noun_fallback":107,"./steps/10-contraction_step":108,"./steps/11-date_step":109,"./steps/12-auxiliary_step":110,"./steps/13-negation_step":111,"./steps/14-comma_step":112,"./steps/15-quotation_step":113,"./steps/16-possessive_step":114,"./steps/17-acronym_step":115,"./steps/18-person_step":116,"./steps/19-organization_step":117,"./steps/20-parentheses_step":118,"./steps/21-plural_step":119,"./steps/22-value_step":120,"./steps/23-corrections":121,"./steps/24-proper_noun":122,"./steps/25-custom":123}],96:[function(_dereq_,module,exports){ -'use strict'; - -// -const conditionPass = function(ts) { - //'if it really goes, I will..' - let m = ts.match('#Condition .{1,7} #ClauseEnd'); - //make sure it ends on a comma - if (m.found && m.match('#Comma$')) { - m.tag('Condition'); - } - //'go a bit further, if it then has a pronoun - m = ts.match('#Condition .{1,13} #ClauseEnd #Pronoun'); - if (m.found && m.match('#Comma$')) { - m.not('#Pronoun$').tag('Condition', 'end-pronoun'); - } - //if it goes then .. - m = ts.match('#Condition .{1,7} then'); - if (m.found) { - m.not('then$').tag('Condition', 'cond-then'); - } - //as long as .. - m = ts.match('as long as .{1,7} (then|#ClauseEnd)'); - if (m.found) { - m.not('then$').tag('Condition', 'as-long-then'); - } - //at the end of a sentence: - //'..., if it really goes.' - m = ts.match('#Comma #Condition .{1,7} .$'); - if (m.found) { - m.not('^#Comma').tag('Condition', 'comma-7-end'); - } - // '... if so.' - m = ts.match('#Condition .{1,4}$'); - if (m.found) { - m.tag('Condition', 'cond-4-end'); - } - return ts; -}; - -module.exports = conditionPass; - -},{}],97:[function(_dereq_,module,exports){ -'use strict'; -//a verbPhrase is a sequence of axiliaries, adverbs and verbs -const verbPhrase = function (ts) { - if (ts.has('(#Verb|#Auxiliary)')) { - ts.match('#Verb').tag('VerbPhrase', 'verbphrase-verb'); - //quickly was - ts.match('#Adverb #Verb').tag('VerbPhrase', 'adverb-verb'); - //was quickly - ts.match('#Verb #Adverb').tag('VerbPhrase', 'verb-adverb'); - //is not - ts.match('#Verb #Negative').tag('VerbPhrase', 'verb-not'); - //never is - ts.match('never #Verb').tag('VerbPhrase', 'not-verb'); - //'will have had'.. - ts.match('#Auxiliary+').tag('VerbPhrase', '2'); - // 'is' - ts.match('#Copula').tag('VerbPhrase', '#3'); - //'really will'.. - ts.match('#Adverb #Auxiliary').tag('VerbPhrase', '#4'); - //to go - // ts.match('to #Infinitive').tag('VerbPhrase', '#5'); - //work with - // ts.match('#Verb #Preposition').tag('VerbPhrase', '#6'); - } - return ts; -}; - -module.exports = verbPhrase; - -},{}],98:[function(_dereq_,module,exports){ -'use strict'; -const conditionPass = _dereq_('./00-conditionPass'); -const verbPhrase = _dereq_('./01-verbPhrase'); -// const nounPhrase = require('./02-nounPhrase'); -// const AdjectivePhrase = require('./03-adjectivePhrase'); -// -const phraseTag = function (ts) { - ts = conditionPass(ts); - ts = verbPhrase(ts); - // ts = nounPhrase(ts); - // ts = AdjectivePhrase(ts); - return ts; -}; - -module.exports = phraseTag; - -},{"./00-conditionPass":96,"./01-verbPhrase":97}],99:[function(_dereq_,module,exports){ -'use strict'; -//regs- -const titleCase = /^[A-Z][a-z']/; -const romanNum = /^[IVXCM]+$/; - -//not so smart (right now) -const isRomanNumeral = function(t) { - if (t.text.length > 1 && romanNum.test(t.text) === true) { - return t.canBe('RomanNumeral'); - } - return false; -}; - -const oneLetters = { - a: true, - i: true, - //internet-slang - u: true, - r: true, - c: true, - k: true -}; - -const punctuation_step = function(ts) { - let rules = ts.world.regex || []; - ts.terms.forEach((t, o) => { - let str = t.text; - //anything can be titlecase - if (titleCase.test(str) === true) { - t.tag('TitleCase', 'punct-rule'); - } - //add hyphenation - if (t.whitespace.after === '-' && ts.terms[o + 1] && ts.terms[o + 1].whitespace.before === '') { - t.tag('Hyphenated', 'has-hyphen'); - ts.terms[o + 1].tag('Hyphenated', 'has-hyphen'); - } - //look at () parentheses - if (t.text[0] === '(') { - t.tag('StartBracket'); - } - //look at end-brackets (allow some punctuation after)! - if (/\)[,.?!;:]?$/.test(t.text) === true) { - t.tag('EndBracket'); - } - //ok, normalise it a little, - str = str.replace(/[,\.\?]$/, ''); - //do punctuation rules (on t.text) - for (let i = 0; i < rules.length; i++) { - let r = rules[i]; - if (r.reg.test(str) === true) { - //don't over-write any other known tags - if (t.canBe(r.tag)) { - t.tag(r.tag, 'punctuation-rule- "' + r.reg.toString() + '"'); - } - return; - } - } - //terms like 'e' - if (str.length === 1 && ts.terms[o + 1] && /[A-Z]/.test(str) && !oneLetters[str.toLowerCase()]) { - t.tag('Acronym', 'one-letter-acronym'); - } - //roman numerals (weak rn) - if (isRomanNumeral(t)) { - t.tag('RomanNumeral', 'is-roman-numeral'); - } - //'100+' - if (/[0-9]\+$/.test(t.text) === true) { - t.tag('NumericValue', 'number-plus'); - } - }); - return ts; -}; - -module.exports = punctuation_step; - -},{}],100:[function(_dereq_,module,exports){ -'use strict'; -const emojiReg = _dereq_('./rules/emoji_regex'); -const emoticon = _dereq_('./rules/emoticon_list'); -//for us, there's three types - -// * ;) - emoticons -// * 🌵 - unicode emoji -// * :smiling_face: - asci-represented emoji - -//test for forms like ':woman_tone2:‍:ear_of_rice:' -//https://github.com/Kikobeats/emojis-keywords/blob/master/index.js -const isColonEmoji = (t) => { - if (t.text.charAt(0) === ':') { - //end comma can be last or second-last ':haircut_tone3:‍♀️' - if (t.text.match(/:.?$/) === null) { - return false; - } - //ensure no spaces - if (t.text.match(' ')) { - return false; - } - //reasonably sized - if (t.text.length > 35) { - return false; - } - return true; - } - return false; -}; - -//check against emoticon whitelist -const isEmoticon = (t) => { - //normalize the 'eyes' - let str = t.text.replace(/^[:;]/, ':'); - return emoticon.hasOwnProperty(str) === true; -}; - -// -const emojiStep = (ts) => { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //test for :keyword: emojis - if (isColonEmoji(t)) { - t.tag('Emoji', 'colon-emoji'); - } - //test for unicode emojis - if (t.text.match(emojiReg)) { - t.tag('Emoji', 'unicode-emoji'); - } - //test for emoticon ':)' emojis - if (isEmoticon(t)) { - t.tag('Emoji', 'emoticon-emoji'); - } - } - return ts; -}; -module.exports = emojiStep; - -},{"./rules/emoji_regex":130,"./rules/emoticon_list":131}],101:[function(_dereq_,module,exports){ -'use strict'; -const split = _dereq_('./contraction/split'); -// const l = require('../../lexicon/init'); -// const lexicon = l.lexicon; - -const lexicon_pass = function(ts) { - const lexicon = ts.world.words || {}; - //loop through each term - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //basic term lookup - if (lexicon.hasOwnProperty(t.normal) === true) { - t.tag(lexicon[t.normal], 'lexicon'); - continue; - } - //support silent_term matches - if (t.silent_term && lexicon.hasOwnProperty(t.silent_term) === true) { - t.tag(lexicon[t.silent_term], 'silent_term-lexicon'); - continue; - } - //check root version too - if (t.root && t.normal !== t.root) { - if (lexicon.hasOwnProperty(t.root) === true) { - t.tag(lexicon[t.root], 'lexicon'); - continue; - } - } - //support contractions (manually) - let parts = split(t); - if (parts && parts.start) { - let start = parts.start.toLowerCase(); - if (lexicon.hasOwnProperty(start) === true) { - t.tag(lexicon[start], 'contraction-lexicon'); - continue; - } - } - } - return ts; -}; - -module.exports = lexicon_pass; - -},{"./contraction/split":129}],102:[function(_dereq_,module,exports){ -'use strict'; -const MAX = 4; - -//find terms in the lexicon longer than one word (like 'hong kong') -const findMultiWords = function(ts, i, world) { - let lex = world.words; - let start = ts.terms[i].root; - let nextTerms = ts.terms.slice(i + 1, i + MAX).map((t) => t.root); - //look for matches, try biggest first - let max = MAX; - if (nextTerms.length < max) { - max = nextTerms.length; - } - for(let k = max; k > 0; k -= 1) { - let howAbout = start + ' ' + nextTerms.slice(0, k).join(' '); - if (lex.hasOwnProperty(howAbout) === true) { - ts.slice(i, i + k + 1).tag(lex[howAbout], 'multi-lexicon-' + howAbout); - return k; - } - } - return 0; -}; - - -//try multiple-word matches in the lexicon (users and default) -const lexiconMulti = ts => { - ts.world.cache = ts.world.cache || {}; - let firstWords = ts.world.cache.firstWords || {}; - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //try multi words from user-lexicon - if (firstWords.hasOwnProperty(t.root) === true) { - let jump = findMultiWords(ts, i, ts.world); - i += jump; - continue; - } - } - return ts; -}; -module.exports = lexiconMulti; - -},{}],103:[function(_dereq_,module,exports){ -'use strict'; -//identify urls, hashtags, @mentions, emails -//regs -const email = /^\w+@\w+\.[a-z]{2,3}$/; //not fancy -const hashTag = /^#[a-z0-9_]{2,}$/; -const atMention = /^@\w{2,}$/; -const urlA = /^(https?:\/\/|www\.)\w+\.[a-z]{2,3}/; //with http/www -const urlB = /^[\w\.\/]+\.(com|net|gov|org|ly|edu|info|biz|ru|jp|de|in|uk|br)/; //http://mostpopularwebsites.net/top-level-domain - -const web_pass = function(terms) { - for (let i = 0; i < terms.length; i++) { - let t = terms.get(i); - let str = t.text.trim().toLowerCase(); - if (email.test(str) === true) { - t.tag('Email', 'web_pass'); - } - if (hashTag.test(str) === true) { - t.tag('HashTag', 'web_pass'); - } - if (atMention.test(str) === true) { - t.tag('AtMention', 'web_pass'); - } - if (urlA.test(str) === true || urlB.test(str) === true) { - t.tag('Url', 'web_pass'); - } - } - return terms; -}; - -module.exports = web_pass; - -},{}],104:[function(_dereq_,module,exports){ -'use strict'; -const regs = _dereq_('./rules/regex_list'); -const suffixes = _dereq_('./rules/suffix_lookup'); - -const misc = [ - //slang things - [/^(lol)+[sz]$/, 'Expression'], //lol - [/^ma?cd[aeiou]/, 'LastName'], //macdonell - Last patterns https://en.wikipedia.org/wiki/List_of_family_name_affixes - //starting-ones - [/^[\-\+]?[0-9][0-9,]*(\.[0-9])*$/, 'Cardinal'], //like 5 - [/^(un|de|re)\\-[a-z]../, 'Verb'], - [/^[\-\+]?[0-9]+(\.[0-9])*$/, 'NumericValue'], - [/^https?\:?\/\/[a-z0-9]/, 'Url'], //the colon is removed in normalisation - [/^www\.[a-z0-9]/, 'Url'], - [/^(over|under)[a-z]{2,}/, 'Adjective'], - [/^[0-9]{1,4}\.[0-9]{1,2}\.[0-9]{1,4}$/, 'Date'], // 03-02-89 - //ending-ones - [/^[0-9]+([a-z]{1,2})$/, 'Value'], //like 5kg - [/^[0-9][0-9,\.]*(st|nd|rd|r?th)$/, ['NumericValue', 'Ordinal']], //like 5th - //middle (anywhere) - [/[a-z]*\\-[a-z]*\\-/, 'Adjective'] -]; - -//straight-up lookup of known-suffixes -const lookup = function(t) { - const len = t.normal.length; - let max = 7; - if (len <= max) { - max = len - 1; - } - for (let i = max; i > 1; i -= 1) { - let str = t.normal.substr(len - i, len); - if (suffixes[i][str] !== undefined) { - // console.log('suffix-match: ' + str); - return suffixes[i][str]; - } - } - return null; -}; - -//word-regexes indexed by last-character -const regexFn = function(t) { - let char = t.normal.charAt(t.normal.length - 1); - if (regs[char] === undefined) { - return null; - } - let arr = regs[char]; - for (let o = 0; o < arr.length; o++) { - if (arr[o][0].test(t.normal) === true) { - return arr[o]; - } - } - return null; -}; - -const suffix_step = function(ts) { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //try known suffixes - let tag = lookup(t); - if (tag !== null && t.canBe(tag) === true) { - t.tag(tag, 'suffix-lookup'); - continue; - } - //apply regexes by final-char - tag = regexFn(t); - if (tag !== null && t.canBe(tag[1]) === true) { - t.tag(tag[1], 'regex-list: ' + String(tag[0])); - continue; - } - //apply misc regexes - for (let o = 0; o < misc.length; o++) { - if (misc[o][0].test(t.normal) === true) { - tag = misc[o][1]; - if (t.canBe(tag) === true) { - t.tag(tag, 'misc-regex-' + misc[o][0]); - } - } - } - } - return ts; -}; - -module.exports = suffix_step; - -},{"./rules/regex_list":133,"./rules/suffix_lookup":134}],105:[function(_dereq_,module,exports){ -'use strict'; -const markov = _dereq_('./rules/neighbours'); -const afterThisWord = markov.afterThisWord; -const beforeThisWord = markov.beforeThisWord; -const beforeThisPos = markov.beforeThisPos; -const afterThisPos = markov.afterThisPos; - -const nothing = { - TitleCase: true, - UpperCase: true, - CamelCase: true, - Hyphenated: true, - StartBracket: true, - EndBracket: true, - Comma: true, - ClauseEnd: true, -}; - -//basically a last-ditch effort before everything falls back to a noun -//for unknown terms, look left + right first, and hit-up the markov-chain for clues -const neighbour_step = function (ts) { - ts.terms.forEach((t, n) => { - //is it still unknown? - let termTags = Object.keys(t.tags); - termTags = termTags.filter((tag) => nothing.hasOwnProperty(tag) === false); - if (termTags.length === 0) { - let lastTerm = ts.terms[n - 1]; - let nextTerm = ts.terms[n + 1]; - //look at previous word for clues - if (lastTerm && afterThisWord.hasOwnProperty(lastTerm.normal) && !lastTerm.tags.ClauseEnd) { - t.tag(afterThisWord[lastTerm.normal], 'neighbour-after-"' + lastTerm.normal + '"'); - return; - } - //look at next word for clues.. - //(not if there's a comma, though) - if (!t.tags.ClauseEnd && nextTerm && beforeThisWord.hasOwnProperty(nextTerm.normal)) { - t.tag(beforeThisWord[nextTerm.normal], 'neighbour-before-"' + nextTerm.normal + '"'); - return; - } - //look at the last POS for clues - let tags = []; - if (lastTerm) { - tags = Object.keys(lastTerm.tags); - for (let i = 0; i < tags.length; i++) { - if (afterThisPos[tags[i]]) { - t.tag(afterThisPos[tags[i]], 'neighbour-after-[' + tags[i] + ']'); - return; - } - } - } - //look at the next POS for clues - if (nextTerm) { - tags = Object.keys(nextTerm.tags); - for (let i = 0; i < tags.length; i++) { - if (beforeThisPos[tags[i]]) { - t.tag(beforeThisPos[tags[i]], 'neighbour-before-[' + tags[i] + ']'); - return; - } - } - } - } - }); - - return ts; -}; - -module.exports = neighbour_step; - -},{"./rules/neighbours":132}],106:[function(_dereq_,module,exports){ -'use strict'; -//titlecase is a signal for a noun - -const capital_logic = function (s) { - //(ignore first word) - for (let i = 1; i < s.terms.length; i++) { - let t = s.terms[i]; - //has a capital, but isn't too weird. - if (t.tags.TitleCase && t.isWord()) { - t.tag('Noun', 'capital-step'); - t.tag('TitleCase', 'capital-step'); - } - } - //support first-word of sentence as proper titlecase - let t = s.terms[0]; - if (t && t.tags.TitleCase) { - if (t.tags.Person || t.tags.Organization || t.tags.Place) { - t.tag('TitleCase', 'first-term-capital'); - } - } - return s; -}; - -module.exports = capital_logic; - -},{}],107:[function(_dereq_,module,exports){ -'use strict'; -//tag word as noun if we know nothing about it, still. - -//tags that dont really count -const nothing = { - TitleCase: true, - UpperCase: true, - CamelCase: true, - Hyphenated: true, - StartBracket: true, - EndBracket: true, - Comma: true, - ClauseEnd: true, -}; -//are the tags basically empty -const gotNothing = function(t) { - //fail-fast - if (t.tags.Noun || t.tags.Verb || t.tags.Adjective) { - return false; - } - let tags = Object.keys(t.tags); - if (tags.length === 0) { - return true; - } - if (tags.filter(tag => !nothing[tag]).length === 0) { - return true; - } - return false; -}; - -//in last-ditch, try to match 'rewatch' -> 'watch' in the lexicon -const tryRoot = function(t) { - if (/^(re|un)-?[^aeiou]./.test(t.normal) === true) { - let str = t.normal.replace(/^(re|un)-?/, ''); - if (t.world.words.hasOwnProperty(str) === true) { - let tag = t.world.words[str]; - if (tag === 'Infinitive' || tag === 'PresentTense' || tag === 'PastTense' || tag === 'Gerund') { - return tag; - } - } - } - return null; -}; - -const noun_fallback = function(s) { - for (let i = 0; i < s.terms.length; i++) { - let t = s.terms[i]; - //fail-fast - if (t.tags.Noun || t.tags.Verb) { - continue; - } - //ensure it only has the tag 'Term' - if (gotNothing(t)) { - //ensure it's atleast word-looking - if (t.isWord() === false) { - continue; - } - let rootTag = tryRoot(t); - if (rootTag !== null) { - t.tag(rootTag, 'root-tag-match'); - continue; - } - t.tag('Noun', 'noun-fallback'); - } - } - return s; -}; - -module.exports = noun_fallback; - -},{}],108:[function(_dereq_,module,exports){ -'use strict'; -const irregulars = _dereq_('./contraction/01-irregulars'); -const isWasHas = _dereq_('./contraction/02-isWasHas'); -const easyOnes = _dereq_('./contraction/03-easyOnes'); -const numberRange = _dereq_('./contraction/04-numberRange'); - -//find and pull-apart contractions -const interpret = function(ts) { - //check irregulars - ts = irregulars(ts); - //guess-at ambiguous "'s" one - ts = isWasHas(ts); - //check easy ones - ts = easyOnes(ts); - //5-7 - ts = numberRange(ts); - return ts; -}; - -module.exports = interpret; - -},{"./contraction/01-irregulars":124,"./contraction/02-isWasHas":125,"./contraction/03-easyOnes":126,"./contraction/04-numberRange":127}],109:[function(_dereq_,module,exports){ -'use strict'; -//ambiguous 'may' and 'march' -const preps = '(in|by|before|during|on|until|after|of|within|all)'; -const thisNext = '(last|next|this|previous|current|upcoming|coming)'; -const sections = '(start|end|middle|starting|ending|midpoint|beginning)'; -const seasons = '(spring|summer|winter|fall|autumn)'; - -//ensure a year is approximately typical for common years -//please change in one thousand years -const tagYear = (v, reason) => { - if (v.found !== true) { - return; - } - v.list.forEach((ts) => { - let num = parseInt(ts.terms[0].normal, 10); - if (num && num > 1000 && num < 3000) { - ts.terms[0].tag('Year', reason); - } - }); -}; -//same, but for less-confident values -const tagYearSafer = (v, reason) => { - if (v.found !== true) { - return; - } - v.list.forEach((ts) => { - let num = parseInt(ts.terms[0].normal, 10); - if (num && num > 1900 && num < 2030) { - ts.terms[0].tag('Year', reason); - } - }); -}; - -//non-destructively tag values & prepositions as dates -const datePass = function (ts) { - //ambiguous month - person forms - let people = '(january|april|may|june|summer|autumn|jan|sep)'; - if (ts.has(people)) { - //give to april - ts.match(`#Infinitive #Determiner? #Adjective? #Noun? (to|for) ${people}`).lastTerm().tag('Person', 'ambig-person'); - //remind june - ts.match(`#Infinitive ${people}`).lastTerm().tag('Person', 'infinitive-person'); - //may waits for - ts.match(`${people} #PresentTense (to|for)`).firstTerm().tag('Person', 'ambig-active'); - //april will - ts.match(`${people} #Modal`).firstTerm().tag('Person', 'ambig-modal'); - //would april - ts.match(`#Modal ${people}`).lastTerm().tag('Person', 'modal-ambig'); - //with april - ts.match(`(that|with|for) ${people}`).term(1).tag('Person', 'that-month'); - //it is may - ts.match(`#Copula ${people}`).term(1).tag('Person', 'is-may'); - //may is - ts.match(`${people} #Copula`).term(0).tag('Person', 'may-is'); - //april the 5th - ts.match(`${people} the? #Value`).term(0).tag('Month', 'person-value'); - //wednesday april - ts.match(`#Date ${people}`).term(1).tag('Month', 'correction-may'); - //may 5th - ts.match(`${people} the? #Value`).firstTerm().tag('Month', 'may-5th'); - //5th of may - ts.match(`#Value of ${people}`).lastTerm().tag('Month', '5th-of-may'); - //by april - ts.match(`${preps} ${people}`).ifNo('#Holiday').term(1).tag('Month', 'preps-month'); - //this april - ts.match(`(next|this|last) ${people}`).term(1).tag('Month', 'correction-may'); //maybe not 'this' - } - //ambiguous month - verb-forms - let verbs = '(may|march)'; - if (ts.has(verbs)) { - //quickly march - ts.match(`#Adverb ${verbs}`).lastTerm().tag('Infinitive', 'ambig-verb'); - ts.match(`${verbs} #Adverb`).lastTerm().tag('Infinitive', 'ambig-verb'); - //all march - ts.match(`${preps} ${verbs}`).lastTerm().tag('Month', 'in-month'); - //this march - ts.match(`(next|this|last) ${verbs}`).lastTerm().tag('Month', 'this-month'); - //with date - ts.match(`${verbs} the? #Value`).firstTerm().tag('Month', 'march-5th'); - ts.match(`#Value of? ${verbs}`).lastTerm().tag('Month', '5th-of-march'); - //nearby - ts.match(`[${verbs}] .? #Date`).lastTerm().tag('Month', 'march-and-feb'); - ts.match(`#Date .? [${verbs}]`).lastTerm().tag('Month', 'feb-and-march'); - - if (ts.has('march')) { - //march to - ts.match('march (up|down|back|to|toward)').term(0).tag('Infinitive', 'march-to'); - //must march - ts.match('#Modal march').term(1).tag('Infinitive', 'must-march'); - } - - } - //sun 5th - if (ts.has('sun')) { - //sun feb 2 - ts.match('sun #Date').firstTerm().tag('WeekDay', 'sun-feb'); - //sun the 5th - ts.match('sun the #Ordinal').tag('Date').firstTerm().tag('WeekDay', 'sun-the-5th'); - //the sun - ts.match('#Determiner sun').lastTerm().tag('Singular', 'the-sun'); - } - //sat, nov 5th - if (ts.has('sat')) { - //sat november - ts.match('sat #Date').firstTerm().tag('WeekDay', 'sat-feb'); - //this sat - ts.match(`${preps} sat`).lastTerm().tag('WeekDay', 'sat'); - } - - //months: - if (ts.has('#Month')) { - //June 5-7th - ts.match(`#Month #DateRange+`).tag('Date', 'correction-numberRange'); - //5th of March - ts.match('#Value of #Month').tag('Date', 'value-of-month'); - //5 March - ts.match('#Cardinal #Month').tag('Date', 'cardinal-month'); - //march 5 to 7 - ts.match('#Month #Value to #Value').tag('Date', 'value-to-value'); - //march the 12th - ts.match('#Month the #Value').tag('Date', 'month-the-value'); - } - - ts.match('in the (night|evening|morning|afternoon|day|daytime)').tag('Time', 'in-the-night'); - ts.match('(#Value|#Time) (am|pm)').tag('Time', 'value-ampm'); - - //months: - if (ts.has('#Value')) { - //for 4 months - ts.match('for #Value #Duration').tag('Date', 'for-x-duration'); - //values - ts.match('#Value #Abbreviation').tag('Value', 'value-abbr'); - ts.match('a #Value').if('(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)').tag('Value', 'a-value'); - ts.match('(minus|negative) #Value').tag('Value', 'minus-value'); - ts.match('#Value grand').tag('Value', 'value-grand'); - // ts.match('#Ordinal (half|quarter)').tag('Value', 'ordinal-half');//not ready - ts.match('(half|quarter) #Ordinal').tag('Value', 'half-ordinal'); - ts.match('(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion) and #Value').tag('Value', 'magnitude-and-value'); - ts.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value'); - //for four days - ts.match(`${preps}? #Value #Duration`).tag('Date', 'value-duration'); - ts.match('(#WeekDay|#Month) #Value').ifNo('#Money').tag('Date', 'date-value'); - ts.match('#Value (#WeekDay|#Month)').ifNo('#Money').tag('Date', 'value-date'); - //may twenty five - let vs = ts.match('#TextValue #TextValue'); - if (vs.found && vs.has('#Date')) { - vs.tag('#Date', 'textvalue-date'); - } - //two days before - ts.match('#Value #Duration #Conjunction').tag('Date', 'val-duration-conjunction'); - //two years old - ts.match('#Value #Duration old').unTag('Date', 'val-years-old'); - } - - - //seasons - if (ts.has(seasons)) { - ts.match(`${preps}? ${thisNext} ${seasons}`).tag('Date', 'thisNext-season'); - ts.match(`the? ${sections} of ${seasons}`).tag('Date', 'section-season'); - } - - //rest-dates - if (ts.has('#Date')) { - //june the 5th - ts.match('#Date the? #Ordinal').tag('Date', 'correction-date'); - //last month - ts.match(`${thisNext} #Date`).tag('Date', 'thisNext-date'); - //by 5 March - ts.match('due? (by|before|after|until) #Date').tag('Date', 'by-date'); - //tomorrow before 3 - ts.match('#Date (by|before|after|at|@|about) #Cardinal').not('^#Date').tag('Time', 'date-before-Cardinal'); - //saturday am - ts.match('#Date (am|pm)').term(1).unTag('Verb').unTag('Copula').tag('Time', 'date-am'); - ts.match('(last|next|this|previous|current|upcoming|coming|the) #Date').tag('Date', 'next-feb'); - ts.match('#Date (#Preposition|to) #Date').tag('Date', 'date-prep-date'); - //start of june - ts.match(`the? ${sections} of #Date`).tag('Date', 'section-of-date'); - //fifth week in 1998 - ts.match('#Ordinal #Duration in #Date').tag('Date', 'duration-in-date'); - //early in june - ts.match('(early|late) (at|in)? the? #Date').tag('Time', 'early-evening'); - } - - - //year/cardinal tagging - if (ts.has('#Cardinal')) { - let v = ts.match(`#Date #Value #Cardinal`).lastTerm(); - tagYear(v, 'date-value-year'); - //scoops up a bunch - v = ts.match(`#Date+ #Cardinal`).lastTerm(); - tagYear(v, 'date-year'); - //feb 8 2018 - v = ts.match(`#Month #Value #Cardinal`).lastTerm(); - tagYear(v, 'month-value-year'); - //feb 8 to 10th 2018 - v = ts.match(`#Month #Value to #Value #Cardinal`).lastTerm(); - tagYear(v, 'month-range-year'); - //in 1998 - v = ts.match(`(in|of|by|during|before|starting|ending|for|year) #Cardinal`).lastTerm(); - tagYear(v, 'in-year'); - //q2 2009 - v = ts.match('(q1|q2|q3|q4) [#Cardinal]'); - tagYear(v, 'in-year'); - //2nd quarter 2009 - v = ts.match('#Ordinal quarter [#Cardinal]'); - tagYear(v, 'in-year'); - //in the year 1998 - v = ts.match('the year [#Cardinal]'); - tagYear(v, 'in-year'); - - //it was 1998 - v = ts.match('it (is|was) [#Cardinal]'); - tagYearSafer(v, 'in-year'); - //was 1998 and... - v = ts.match(`#Cardinal !#Plural`).firstTerm(); - tagYearSafer(v, 'year-unsafe'); - } - - //another pass at dates.. - if (ts.has('#Date')) { - //time: - if (ts.has('#Time')) { - ts.match('#Cardinal #Time').not('#Year').tag('Time', 'value-time'); - ts.match('(by|before|after|at|@|about) #Time').tag('Time', 'preposition-time'); - //2pm est - ts.match('#Time (eastern|pacific|central|mountain)').term(1).tag('Time', 'timezone'); - ts.match('#Time (est|pst|gmt)').term(1).tag('Time', 'timezone abbr'); - } - - //fix over-greedy - let date = ts.match('#Date+').splitOn('Clause'); - - if (date.has('(#Year|#Time)') === false) { - //12 february 12 - date.match('#Value (#Month|#Weekday) #Value').lastTerm().unTag('Date'); - } - } - - return ts; -}; - -module.exports = datePass; - -},{}],110:[function(_dereq_,module,exports){ -'use strict'; -//auxiliary verbs are extra verbs beside the main ones -// "[will be] going" - etc. - -const Auxiliary = { - 'do': true, - 'don\'t': true, - 'does': true, - 'doesn\'t': true, - 'will': true, - 'wont': true, - 'won\'t': true, - 'have': true, - 'haven\'t': true, - 'had': true, - 'hadn\'t': true, - 'not': true, -}; - -const corrections = function(ts) { - //set verbs as auxillaries - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (Auxiliary[t.normal] || Auxiliary[t.silent_term]) { - let next = ts.terms[i + 1]; - //if next word is a verb - if (next && (next.tags.Verb || next.tags.Adverb || next.tags.Negative)) { - t.tag('Auxiliary', 'corrections-Auxiliary'); - continue; - } - } - } - return ts; -}; - -module.exports = corrections; - -},{}],111:[function(_dereq_,module,exports){ -'use strict'; - -// 'not' is sometimes a verb, sometimes an adjective -const negation_step = function(ts) { - for(let i = 0; i < ts.length; i++) { - let t = ts.get(i); - if (t.normal === 'not' || t.silent_term === 'not') { - //find the next verb/adjective - for(let o = i + 1; o < ts.length; o++) { - if (ts.get(o).tags.Verb) { - t.tag('VerbPhrase', 'negate-verb'); - break; - } - if (ts.get(o).tags.Adjective) { - t.tag('AdjectivePhrase', 'negate-adj'); - break; - } - } - } - } - return ts; -}; - -module.exports = negation_step; - -},{}],112:[function(_dereq_,module,exports){ -'use strict'; -//-types of comma-use- -// PlaceComma - Hollywood, California -// List - cool, fun, and great. -// ClauseEnd - if so, we do. - -//like Toronto, Canada -const isPlaceComma = (ts, i) => { - let t = ts.terms[i]; - let nextTerm = ts.terms[i + 1]; - //'australia, canada' is a list - if (nextTerm && t.tags.Place && !t.tags.Country && nextTerm.tags.Country) { - return true; - } - return false; -}; - -//adj, noun, or verb -const mainTag = (t) => { - if (t.tags.Adjective) { - return 'Adjective'; - } - if (t.tags.Noun) { - return 'Noun'; - } - if (t.tags.Verb) { - return 'Verb'; - } - if (t.tags.Value) { - return 'Value'; - } - return null; -}; - - -//take the first term with a comma, and test to the right. -//the words with a comma must be the same pos. -const isList = (ts, i) => { - let start = i; - let tag = mainTag(ts.terms[i]); - //ensure there's a following comma, and its the same pos - //then a Conjunction - let sinceComma = 0; - let count = 0; - let hasConjunction = false; - for(i = i + 1; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //are we approaching the end - if (count > 0 && t.tags.Conjunction) { - hasConjunction = true; - continue; - } - //found one, - if (t.tags[tag]) { - //looks good. keep it going - if (t.tags.Comma) { - count += 1; - sinceComma = 0; - continue; - } - if (count > 0 && hasConjunction) { //is this the end of the list? - ts.slice(start, i).tag('List'); - return true; - } - } - sinceComma += 1; - //have we gone too far without a comma? - if (sinceComma > 5) { - return false; - } - //this one, not a clause.. - if (tag === 'Value') { - return true; - } - } - return false; -}; - -const commaStep = function(ts) { - //tag the correct punctuation forms - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - let punct = t.getPunctuation(); - if (punct === ',') { - t.tag('Comma', 'comma-step'); - continue; - } - if (punct === ';' || punct === ':') { - t.tag('ClauseEnd', 'clause-punt'); - continue; - } - //support elipses - if (t.whitespace.after.match(/^\.\./)) { - t.tag('ClauseEnd', 'clause-elipses'); - continue; - } - - //support ' - ' clause - if (ts.terms[i + 1] && ts.terms[i + 1].whitespace.before.match(/ - /)) { - t.tag('ClauseEnd', 'hypen-clause'); - continue; - } - } - - //disambiguate the commas now - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (t.tags.Comma) { - //if we already got it - if (t.tags.List) { - continue; - } - //like 'Hollywood, California' - if (isPlaceComma(ts, i)) { - continue; - } - //like 'cold, wet hands' - let found = isList(ts, i); - //otherwise, it's a phrasal comma, like 'you must, if you think so' - if (!found) { - t.tag('ClauseEnd', 'phrasal-comma'); - } - } - } - return ts; -}; - -module.exports = commaStep; - -},{}],113:[function(_dereq_,module,exports){ -'use strict'; - -const quotemarks = { - '\u0022': { - close: '\u0022', - tag: 'StraightDoubleQuotes' - }, - '\uFF02': { - close: '\uFF02', - tag: 'StraightDoubleQuotesWide' - }, - '\u0027': { - close: '\u0027', - tag: 'StraightSingleQuotes' - }, - - '\u201C': { - close: '\u201D', - tag: 'CommaDoubleQuotes' - }, - '\u2018': { - close: '\u2019', - tag: 'CommaSingleQuotes' - }, - - '\u201F': { - close: '\u201D', - tag: 'CurlyDoubleQuotesReversed' - }, - '\u201B': { - close: '\u2019', - tag: 'CurlySingleQuotesReversed' - }, - - '\u201E': { - close: '\u201D', - tag: 'LowCurlyDoubleQuotes' - }, - '\u2E42': { - close: '\u201D', - tag: 'LowCurlyDoubleQuotesReversed' - }, - - '\u201A': { - close: '\u2019', - tag: 'LowCurlySingleQuotes' - }, - - '\u00AB': { - close: '\u00BB', - tag: 'AngleDoubleQuotes' - }, - '\u2039': { - close: '\u203A', - tag: 'AngleSingleQuotes' - }, - - // Prime 'non quotation' - '\u2035': { - close: '\u2032', - tag: 'PrimeSingleQuotes' - }, - '\u2036': { - close: '\u2033', - tag: 'PrimeDoubleQuotes' - }, - '\u2037': { - close: '\u2034', - tag: 'PrimeTripleQuotes' - }, - - // Prime 'quotation' variation - '\u301D': { - close: '\u301E', - tag: 'PrimeDoubleQuotes' - }, - '\u0060': { - close: '\u00B4', - tag: 'PrimeSingleQuotes' - }, - - '\u301F': { - close: '\u301E', - tag: 'LowPrimeDoubleQuotesReversed' - } -}; - -// Convert the close quote to a regex. -Object.keys(quotemarks).forEach((open) => { - quotemarks[open].regex = new RegExp(quotemarks[open].close + '[;:,.]*'); - quotemarks[open].open = open; -}); - -// Improve open match detection. -const startQuote = new RegExp('[' + Object.keys(quotemarks).join('') + ']'); - -//tag a inline quotation as such -const quotation_step = ts => { - // Isolate the text so it doesn't change. - const terms = ts.terms.slice(0); //.map(e => e.text); - for (let i = 0; i < terms.length; i++) { - - let t = ts.terms[i]; - if (startQuote.test(t.whitespace.before)) { - // Get the match and split it into groups - let quotes = t.whitespace.before.match(startQuote).shift().split(''); - // Get close and tag info. - quotes = quotes.map(mark => quotemarks[mark]); - // Look for the ending - for (let o = 0; o < ts.terms.length; o++) { - // max-length don't go-on forever - if (!terms[i + o] || o > 28) { - break; - } - // Find the close. - let index = -1; - for(let qi = 0; qi < quotes.length; qi += 1) { - if (quotes[qi].regex.test(terms[i + o].whitespace.after) === true) { - index = qi; - break; - } - } - if (index !== -1) { - // Remove the found - const quote = quotes.splice(index, 1).pop(); - - if (quote.regex.test(ts.terms[i + o].normal)) { - ts.terms[i + o].whitespace.after.replace(quote.regex, ''); - } - // Tag the things. - t.tag('StartQuotation', 'quotation_open'); - ts.terms[i + o].tag('EndQuotation', 'quotation_close'); - ts.slice(i, i + o + 1).tag('Quotation', 'quotation_step'); - // Compensate for multiple close quotes ('"Really"') - o -= 1; - if (!quotes.length) { - break; - } - } - } - } - } - return ts; -}; -module.exports = quotation_step; - -},{}],114:[function(_dereq_,module,exports){ -'use strict'; -//decide if an apostrophe s is a contraction or not -// 'spencer's nice' -> 'spencer is nice' -// 'spencer's house' -> 'spencer's house' - -const singleQuotes = [ - ['\u0027', '\u0027'], // Straight Single Quotes - ['\u2018', '\u2019'], // Comma Single Quotes - ['\u201B', '\u2019'], // Curly Single Quotes Reversed - ['\u201A', '\u2019'], // Low Curly Single Quotes - ['\u2035', '\u2032'], // Prime Single Quotes Alt - ['\u0060', '\u00B4'] // Prime Single Quotes -]; -//these are always contractions -const blacklist = [ - 'it\'s', - 'that\'s' -]; - -// Get all types of single quote. -const apostrophes = '\'‘’‛‚‵′`´'; -const afterWord = new RegExp('([a-z]s[' + apostrophes + '])\\W*$'); // [^\w]* match 0 or more of any char that is NOT alphanumeric -const hasApostrophe = new RegExp('[' + apostrophes + ']'); -const trailers = new RegExp('[^' + apostrophes + '\\w]+$'); - -const quoteRegex = {}; -singleQuotes.forEach(quote => { - quoteRegex[quote[0]] = new RegExp(quote[1] + '[^' + quote[1] + '\\w]*$'); -}); - -// Compensate for different `'`s in the blacklist -blacklist.map(item => new RegExp( - item.replace('\'', '[' + apostrophes + ']') -)); - -// A possessive means `'s` describes ownership -// Not a contraction, like it's -> `it is` -const is_possessive = function(terms, text, index) { - const thisWord = terms.get(index); - const nextWord = terms.get(index + 1); - const stepWord = terms.get(index + 2); - - //our booleans: - // `blacklist` are always contractions, not possessive - const inBlacklist = blacklist.map(r => text.match(r)).find(m => m); - // If no apostrophe s or s apostrophe - const endTick = hasApostrophe.test(thisWord.whitespace.after); - // "spencers'" - this is always possessive - eg "flanders'" - const hasPronoun = thisWord.tags.Pronoun; - - if (inBlacklist || hasPronoun || !endTick) { - return false; - } - if (afterWord.test(text) || nextWord === undefined) { - return true; - } - // Next word is 'house' - if (nextWord.tags.Noun === true || thisWord.tags.ClauseEnd === true) { - return true; - } - //rocket's red glare - if (stepWord !== undefined && nextWord.tags.Adjective && stepWord.tags.Noun) { - return true; - } - return false; -}; - -// Tag each term as possessive, if it should -const possessiveStep = function(ts) { - let expectingClosers = []; - for(let i = 0; i < ts.length; i++) { - const term = ts.get(i); - let text = term.text; - - // First detect open quotes before detecting apostrophes - if (typeof quoteRegex[text[0]] !== 'undefined') { - // Add the expected closing quotes to our inspection array. - expectingClosers[expectingClosers.length] = quoteRegex[text[0]]; - text = text.slice(1); - } - - // Pre checking for quotes. e.g: Carlos'.’. -> Carlos'.’ - text = text.replace(trailers, ''); - // If the string ends with an expected closer. - let closer = -1; - for(let qi = 0; qi < expectingClosers.length; qi += 1) { - if (expectingClosers[qi].test(text) === true) { - closer = qi; - break; - } - } - if (closer !== -1) { - text = text.replace(expectingClosers[closer], ''); - delete expectingClosers[closer]; - } - - // Post checking for quotes. e.g: Carlos'. -> Carlos' - text = text.replace(trailers, ''); - if (is_possessive(ts, text, i)) { - // If it's not already a noun, co-erce it to one - if (!term.tags['Noun']) { - term.tag('Noun', 'possessive_pass'); - } - term.tag('Possessive', 'possessive_pass'); - - // If it's been detected as a `Contraction` - if (term.tags.Contraction === true) { - // Remove the `Contraction` tag and silent_terms - term.unTag('Contraction'); - ts.terms.splice(i + 1, 1); - term.silent_term = ''; - } - } - } - return ts; -}; -module.exports = possessiveStep; - -},{}],115:[function(_dereq_,module,exports){ -'use strict'; - -//tag 'FBI' as letters-representing-words. -//we guess if letters are an acronym in the Term class. -const acronym_step = function(ts) { - ts.terms.forEach((t) => { - if (t.isAcronym()) { - t.tag('Acronym', 'acronym-step'); - } - }); - return ts; -}; - -module.exports = acronym_step; - -},{}],116:[function(_dereq_,module,exports){ -'use strict'; - -//sort-out things like 'theresa may', or 'will jones'. -const person_step = function(ts) { - //mr Putin - ts.match('(mr|mrs|ms|dr) (#TitleCase|#Possessive)+').tag('#Person', 'mr-putin'); - - //a bunch of ambiguous first names - let maybeNoun = '(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)'; - if (ts.has(maybeNoun)) { - ts.match('(#Determiner|#Adverb|#Pronoun|#Possessive) [' + maybeNoun + ']').tag('Noun', 'the-ray'); - ts.match(maybeNoun + ' (#Person|#Acronym|#TitleCase)').canBe('#Person').tag('Person', 'ray-smith'); - } - //verbs or people-names - let maybeVerb = '(pat|wade|ollie|will|rob|buck|bob|mark|jack)'; - if (ts.has(maybeVerb)) { - ts.match('(#Modal|#Adverb) [' + maybeVerb + ']').tag('Verb', 'would-mark'); - ts.match(maybeVerb + ' (#Person|#TitleCase)').tag('Person', 'rob-smith'); - } - //adjectives or people-names - let maybeAdj = '(misty|rusty|dusty|rich|randy)'; - if (ts.has(maybeAdj)) { - ts.match('#Adverb [' + maybeAdj + ']').tag('Adjective', 'really-rich'); - ts.match(maybeAdj + ' (#Person|#TitleCase)').tag('Person', 'randy-smith'); - } - //dates as people names - let maybeDate = '(april|june|may|jan|august|eve)'; - if (ts.has(maybeDate)) { - ts.match(String(maybeDate) + ' (#Person|#TitleCase)').canBe('#Person').tag('Person', 'june-smith'); - ts.match('(in|during|on|by|before|#Date) [' + maybeDate + ']').canBe('#Date').tag('Date', 'in-june'); - ts.match(maybeDate + ' (#Date|#Value)').canBe('#Date').tag('Date', 'june-5th'); - } - //place-names as people-names - let maybePlace = '(paris|alexandria|houston|kobe|salvador|sydney)'; - if (ts.has(maybePlace)) { - ts.match('(in|near|at|from|to|#Place) [' + maybePlace + ']').canBe('#Place').tag('Place', 'in-paris'); - ts.match('[' + maybePlace + '] #Place').canBe('#Place').tag('Place', 'paris-france'); - ts.match('[' + maybePlace + '] #Person').canBe('#Person').tag('Person', 'paris-hilton'); - } - //this one is tricky - if (ts.match('al')) { - ts.match('al (#Person|#TitleCase)').canBe('#Person').tag('#Person', 'al-borlen'); - ts.match('#TitleCase al #TitleCase').canBe('#Person').tag('#Person', 'arabic-al-arabic'); - } - //ambiguous honorifics - ts.match('(private|general|major|corporal|lord|lady|secretary|premier) #Honorific? #Person').terms(0).tag('Honorific', 'ambg-honorifics'); - //first general.. - ts.match('(1st|2nd|first|second) #Honorific').terms(0).tag('Honorific', 'ordinal-honorific'); - - // let firstNames = '()'; - // let names = ts.match(firstNames); - // if (names.found) { - // //prolly not a name: - // if (ts.has('(#Determiner|#Adverb|#Pronoun|#Possessive) ' + firstNames)) { - // names.unTag('Person', 'the-bill'); - // } else { - // //probably a name here: - // let name = ts.match('(#Honorific|#Person) ' + firstNames); - // if (!name.found) { - // name = ts.match(firstNames + ' (#Person|#Honorific|#TitleCase)'); - // } - // if (name.found && name.has('(#Place|#Date|#Organization)') === false) { - // name.tag('Person', 'dr-bill'); - // names.tag('FirstName', 'ambiguous-name'); - // } - // } - // } - //tighter-matches for other ambiguous names: - // ts.match('(al|) #Acronym? #LastName').firstTerm().tag('#FirstName', 'ambig-lastname'); - - //methods requiring a firstname match - if (ts.has('#FirstName')) { - // Firstname x (dangerous) - let tmp = ts.match('#FirstName #Noun').ifNo('^#Possessive').ifNo('#ClauseEnd .'); - tmp.lastTerm().canBe('#LastName').tag('#LastName', 'firstname-noun'); - //ferdinand de almar - ts.match('#FirstName de #Noun').canBe('#Person').tag('#Person', 'firstname-de-noun'); - //Osama bin Laden - ts.match('#FirstName (bin|al) #Noun').canBe('#Person').tag('#Person', 'firstname-al-noun'); - //John L. Foo - ts.match('#FirstName #Acronym #TitleCase').tag('Person', 'firstname-acronym-titlecase'); - //Andrew Lloyd Webber - ts.match('#FirstName #FirstName #TitleCase').tag('Person', 'firstname-firstname-titlecase'); - //Mr Foo - ts.match('#Honorific #FirstName? #TitleCase').tag('Person', 'Honorific-TitleCase'); - //John Foo - ts.match('#FirstName #TitleCase #TitleCase?').match('#Noun+').tag('Person', 'firstname-titlecase'); - //peter the great - ts.match('#FirstName the #Adjective').tag('Person', 'correction-determiner5'); - //very common-but-ambiguous lastnames - ts.match('#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)').tag('#Person', 'firstname-maybe'); - //Joe K. Sombrero - ts.match('#FirstName #Acronym #Noun') - .ifNo('#Date') - .tag('#Person', 'n-acro-noun') - .lastTerm() - .tag('#LastName', 'n-acro-noun'); - // Dwayne 'the rock' Johnson - ts.match('#FirstName [#Determiner? #Noun] #LastName') - .tag('#NickName', 'first-noun-last') - .tag('#Person', 'first-noun-last'); - - //john bodego's - ts.match('#FirstName (#Singular|#Possessive)') - .ifNo('#Date') - .ifNo('#NickName') - .tag('#Person', 'first-possessive') - .lastTerm() - .tag('#LastName', 'first-possessive'); - } - - //methods requiring a lastname match - if (ts.has('#LastName')) { - // x Lastname - ts.match('#Noun #LastName') - .firstTerm() - .canBe('#FirstName') - .tag('#FirstName', 'noun-lastname'); - //ambiguous-but-common firstnames - ts.match('(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill) #LastName') - .firstTerm() - .tag('#FirstName', 'maybe-lastname'); - //Jani K. Smith - ts.match('#TitleCase #Acronym? #LastName') - .ifNo('#Date') - .tag('#Person', 'title-acro-noun') - .lastTerm() - .tag('#LastName', 'title-acro-noun'); - //is foo Smith - ts.match('#Copula (#Noun|#PresentTense) #LastName') - .term(1) - .tag('#FirstName', 'copula-noun-lastname'); - } - - //methods requiring a titlecase - if (ts.has('#TitleCase')) { - ts.match('#Acronym #TitleCase') - .canBe('#Person') - .tag('#Person', 'acronym-titlecase'); - //ludwig van beethovan - ts.match('#TitleCase (van|al|bin) #TitleCase') - .canBe('#Person') - .tag('Person', 'correction-titlecase-van-titlecase'); - ts.match('#TitleCase (de|du) la? #TitleCase') - .canBe('#Person') - .tag('Person', 'correction-titlecase-van-titlecase'); - //Morgan Shlkjsfne - ts.match('#Person #TitleCase') - .match('#TitleCase #Noun') - .canBe('#Person') - .tag('Person', 'correction-person-titlecase'); - //pope francis - ts.match('(lady|queen|sister) #TitleCase') - .ifNo('#Date') - .ifNo('#Honorific') - .tag('#FemaleName', 'lady-titlecase'); - ts.match('(king|pope|father) #TitleCase') - .ifNo('#Date') - .tag('#MaleName', 'correction-poe'); - } - - //j.k Rowling - ts.match('#Noun van der? #Noun') - .canBe('#Person') - .tag('#Person', 'von der noun'); - //king of spain - ts.match('(king|queen|prince|saint|lady) of? #Noun') - .canBe('#Person') - .tag('#Person', 'king-of-noun'); - //mr X - ts.match('#Honorific #Acronym').tag('Person', 'Honorific-TitleCase'); - //peter II - ts.match('#Person #Person the? #RomanNumeral').tag('Person', 'correction-roman-numeral'); - - //'Professor Fink', 'General McCarthy' - ts.match('#Honorific #Person').tag('Person', 'Honorific-Person'); - - //remove single 'mr' - ts.match('^#Honorific$').unTag('Person', 'single-honorific'); - - return ts; -}; - -module.exports = person_step; - -},{}],117:[function(_dereq_,module,exports){ -'use strict'; -//orgwords like 'bank' in 'Foo Bank' -let orgWords = _dereq_('../../world/more-data/orgWords'); - -//could this word be an organization -const maybeOrg = function(t) { - //must be a noun - if (!t.tags.Noun) { - return false; - } - //can't be these things - if (t.tags.Pronoun || t.tags.Comma || t.tags.Possessive || t.tags.Place) { - return false; - } - //must be one of these - if (t.tags.TitleCase || t.tags.Organization || t.tags.Acronym) { - return true; - } - return false; -}; - -const organization_step = ts => { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (orgWords.hasOwnProperty(t.root) === true) { - //eg. Toronto University - let lastTerm = ts.terms[i - 1]; - if (lastTerm && maybeOrg(lastTerm)) { - lastTerm.tag('Organization', 'org-word-1'); - t.tag('Organization', 'org-word-2'); - continue; - } - //eg. University of Toronto - let nextTerm = ts.terms[i + 1]; - if (nextTerm && nextTerm.normal === 'of') { - if (ts.terms[i + 2] && maybeOrg(ts.terms[i + 2])) { - t.tag('Organization', 'org-of-word-1'); - nextTerm.tag('Organization', 'org-of-word-2'); - ts.terms[i + 2].tag('Organization', 'org-of-word-3'); - continue; - } - } - } - } - if (ts.has('#Acronym')) { - ts.match('the #Acronym').not('(iou|fomo|yolo|diy|dui|nimby)').lastTerm().tag('Organization', 'the-acronym'); - ts.match('#Acronym').match('#Possessive').tag('Organization', 'possessive-acronym'); - } - return ts; -}; -module.exports = organization_step; - -},{"../../world/more-data/orgWords":221}],118:[function(_dereq_,module,exports){ -'use strict'; -//tag the words between '(' and ')' as #Parentheses -const parenthesesStep = function(ts) { - ts.terms.forEach((t, i) => { - if (t.tags.StartBracket) { - for(let o = i; o < ts.terms.length; o += 1) { - if (ts.terms[o].tags.EndBracket === true) { - ts.slice(i, o + 1).tag('Parentheses'); - break; - } - } - } - }); - return ts; -}; -module.exports = parenthesesStep; - -},{}],119:[function(_dereq_,module,exports){ -'use strict'; -const isPlural = _dereq_('../../subset/nouns/isPlural'); - -const pluralStep = function(ts) { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (t.tags.Noun) { - //skip existing fast - if (t.tags.Singular || t.tags.Plural) { - continue; - } - //check if it's plural - let plural = isPlural(t, t.world); //can be null if unknown - if (plural === true) { - t.tag('Plural', 'pluralStep'); - } else if (plural === false) { - t.tag('Singular', 'pluralStep'); - } - } - } - return ts; -}; - -module.exports = pluralStep; - -},{"../../subset/nouns/isPlural":39}],120:[function(_dereq_,module,exports){ -'use strict'; -//regs- -const numericCardinal = /^\$?[0-9,](\.[0-9])?/; -const isOrdinal = /[0-9](st|nd|rd|th)$/; -// const hasText = /^[a-z]/; - -const value_step = function(ts) { - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (t.tags.Value === true) { - //ordinal/cardinal - if (t.tags.Ordinal === undefined && t.tags.Cardinal === undefined) { - if (numericCardinal.test(t.normal) === true) { - t.tag('Cardinal', 'cardinal-val-regex'); - t.tag('NumericValue', 'NumericValue-regex'); - } else if (isOrdinal.test(t.normal) === true) { - t.tag('Ordinal', 'ordinal-value-regex'); - t.tag('NumericValue', 'NumericValue-regex'); - } - } - } - } - //5 books - ts.match('#Cardinal [#Plural]').tag('Unit', 'cardinal-plural'); - //5th book - ts.match('#Ordinal [#Singular]').tag('Unit', 'ordinal-singular'); - //1 book - ts.match('(one|first|1|1st) [#Singular]').tag('Unit', 'one-singular'); - return ts; -}; - -module.exports = value_step; - -},{}],121:[function(_dereq_,module,exports){ -'use strict'; - -//mostly pos-corections here -const corrections = function(ts) { - //ambig prepositions/conjunctions - if (ts.has('so')) { - //so funny - ts.match('so #Adjective').match('so').tag('Adverb', 'so-adv'); - //so the - ts.match('so #Noun').match('so').tag('Conjunction', 'so-conj'); - //do so - ts.match('do so').match('so').tag('Noun', 'so-noun'); - } - if (ts.has('all')) { - //all students - ts.match('[all] #Determiner? #Noun').tag('Adjective', 'all-noun'); - //it all fell apart - ts.match('[all] #Verb').tag('Adverb', 'all-verb'); - } - //the ambiguous word 'that' and 'which' - if (ts.has('(that|which)')) { - //remind john that - ts.match('#Verb #Adverb? #Noun (that|which)').lastTerm().tag('Preposition', 'that-prep'); - //that car goes - ts.match('that #Noun #Verb').firstTerm().tag('Determiner', 'that-determiner'); - //work, which has been done. - ts.match('#Comma [which] (#Pronoun|#Verb)').tag('Preposition', 'which-copula'); - //things that provide - // ts.match('#Plural (that|which) #Adverb? #Verb').term(1).tag('Preposition', 'noun-that'); - } - //Determiner-signals - if (ts.has('#Determiner')) { - //the wait to vote - ts.match('(the|this) [#Verb] #Preposition .').tag('Noun', 'correction-determiner1'); - //the swim - ts.match('(the|those|these) (#Infinitive|#PresentTense|#PastTense)').term(1).tag('Noun', 'correction-determiner2'); - //a staggering cost - ts.match('(a|an) [#Gerund]').tag('Adjective', 'correction-a|an'); - ts.match('(a|an) #Adjective (#Infinitive|#PresentTense)').term(2).tag('Noun', 'correction-a|an2'); - //some pressing issues - ts.match('some [#Verb] #Plural').tag('Noun', 'correction-determiner6'); - //the test string - ts.match('#Determiner [#Infinitive] #Noun').tag('Noun', 'correction-determiner7'); - //the orange. - ts.match('#Determiner #Adjective$').not('(#Comparative|#Superlative)').term(1).tag('Noun', 'the-adj-1'); - //the orange is - ts.match('#Determiner [#Adjective] (#Copula|#PastTense|#Auxiliary)').tag('Noun', 'the-adj-2'); - //the nice swim - ts.match('(the|this|those|these) #Adjective [#Verb]').tag('Noun', 'the-adj-verb'); - //the truly nice swim - ts.match('(the|this|those|these) #Adverb #Adjective [#Verb]').tag('Noun', 'correction-determiner4'); - //a stream runs - ts.match('(the|this|a|an) [#Infinitive] #Adverb? #Verb').tag('Noun', 'correction-determiner5'); - //a sense of - ts.match('#Determiner [#Verb] of').tag('Noun', 'the-verb-of'); - //the threat of force - ts.match('#Determiner #Noun of [#Verb]').tag('Noun', 'noun-of-noun'); - //a close - ts.match('#Determiner #Adverb? [close]').tag('Adjective', 'a-close'); - //did a 900, paid a 20 - ts.match('#Verb (a|an) [#Value]').tag('Singular', 'a-value'); - //a tv show - ts.match('(a|an) #Noun [#Infinitive]').tag('Noun', 'a-noun-inf'); - } - - //like - if (ts.has('like')) { - ts.match('just [like]').tag('Preposition', 'like-preposition'); - //folks like her - ts.match('#Noun [like] #Noun').tag('Preposition', 'noun-like'); - //look like - ts.match('#Verb [like]').tag('Adverb', 'verb-like'); - //exactly like - ts.match('#Adverb like').not('(really|generally|typically|usually|sometimes|often) like').lastTerm().tag('Adverb', 'adverb-like'); - } - - if (ts.has('#Value')) { - //half a million - ts.match('half a? #Value').tag('Value', 'half-a-value'); //quarter not ready - ts.match('#Value and a (half|quarter)').tag('Value', 'value-and-a-half'); - //all values are either ordinal or cardinal - // ts.match('#Value').match('!#Ordinal').tag('#Cardinal', 'not-ordinal'); - //money - ts.match('#Value+ #Currency').tag('Money', 'value-currency').lastTerm().tag('Unit', 'money-unit'); - ts.match('#Money and #Money #Currency?').tag('Money', 'money-and-money'); - //1 800 PhoneNumber - ts.match('1 #Value #PhoneNumber').tag('PhoneNumber', '1-800-Value'); - //(454) 232-9873 - ts.match('#NumericValue #PhoneNumber').tag('PhoneNumber', '(800) PhoneNumber'); - //two hundredth - ts.match('#TextValue+').match('#Cardinal+ #Ordinal').tag('Ordinal', 'two-hundredth'); - } - - if (ts.has('#Noun')) { - //'more' is not always an adverb - ts.match('more #Noun').tag('Noun', 'more-noun'); - //the word 'second' - ts.match('[second] #Noun').not('#Honorific').unTag('Unit').tag('Ordinal', 'second-noun'); - //he quickly foo - ts.match('#Noun #Adverb [#Noun]').tag('Verb', 'correction'); - //fix for busted-up phrasalVerbs - ts.match('#Noun [#Particle]').tag('Preposition', 'repair-noPhrasal'); - //John & Joe's - ts.match('#Noun (&|n) #Noun').tag('Organization', 'Noun-&-Noun'); - //Aircraft designer - ts.match('#Noun #Actor').tag('Actor', 'thing-doer'); - //this rocks - ts.match('(this|that) [#Plural]').tag('PresentTense', 'this-verbs'); - //by a bear. - ts.match('#Determiner #Infinitive$').lastTerm().tag('Noun', 'a-inf'); - //the western line - ts.match('#Determiner [(western|eastern|northern|southern|central)] #Noun').tag('Noun', 'western-line'); - ts.match('(#Determiner|#Value) [(linear|binary|mobile|lexical|technical|computer|scientific|formal)] #Noun').tag('Noun', 'technical-noun'); - //organization - if (ts.has('#Organization')) { - ts.match('#Organization of the? #TitleCase').tag('Organization', 'org-of-place'); - ts.match('#Organization #Country').tag('Organization', 'org-country'); - ts.match('(world|global|international|national|#Demonym) #Organization').tag('Organization', 'global-org'); - } - if (ts.has('#Possessive')) { - //my buddy - ts.match('#Possessive [#FirstName]').unTag('Person', 'possessive-name'); - //spencer kelly's - ts.match('#FirstName #Acronym? #Possessive').notIf('#Comma').match('#FirstName #Acronym? #LastName').tag('Possessive'); - //Super Corp's fundraiser - ts.match('#Organization+ #Possessive').notIf('#Comma').tag('Possessive'); - //Los Angeles's fundraiser - ts.match('#Place+ #Possessive').notIf('#Comma').tag('Possessive'); - } - } - - if (ts.has('#Verb')) { - //still make - ts.match('[still] #Verb').tag('Adverb', 'still-verb'); - //'u' as pronoun - ts.match('[u] #Verb').tag('Pronoun', 'u-pronoun-1'); - //is no walk - ts.match('is no [#Verb]').tag('Noun', 'is-no-verb'); - //different views than - ts.match('[#Verb] than').tag('Noun', 'correction'); - //her polling - ts.match('#Possessive [#Verb]').tag('Noun', 'correction-possessive'); - //there are reasons - ts.match('there (are|were) #Adjective? [#PresentTense]').tag('Plural', 'there-are'); - //jack seems guarded - ts.match('#Singular (seems|appears) #Adverb? [#PastTense$]').tag('Adjective', 'seems-filled'); - - if (ts.has('(who|what|where|why|how|when)')) { - //the word 'how' - ts.match('^how').tag('QuestionWord', 'how-question').tag('QuestionWord', 'how-question'); - ts.match('how (#Determiner|#Copula|#Modal|#PastTense)').term(0).tag('QuestionWord', 'how-is'); - // //the word 'which' - ts.match('^which').tag('QuestionWord', 'which-question').tag('QuestionWord', 'which-question'); - ts.match('which . (#Noun)+ #Pronoun').term(0).tag('QuestionWord', 'which-question2'); - ts.match('which').tag('QuestionWord', 'which-question3'); - //where - - //how he is driving - let word = ts.match('#QuestionWord #Noun #Copula #Adverb? (#Verb|#Adjective)').firstTerm(); - word.unTag('QuestionWord').tag('Conjunction', 'how-he-is-x'); - //when i go fishing - word = ts.match('#QuestionWord #Noun #Adverb? #Infinitive not? #Gerund').firstTerm(); - word.unTag('QuestionWord').tag('Conjunction', 'when i go fishing'); - } - - if (ts.has('#Copula')) { - //is eager to go - ts.match('#Copula #Adjective to #Verb').match('#Adjective to').tag('Verb', 'correction'); - //is mark hughes - ts.match('#Copula [#Infinitive] #Noun').tag('Noun', 'is-pres-noun'); - - ts.match('[#Infinitive] #Copula').tag('Noun', 'infinitive-copula'); - //sometimes adverbs - 'pretty good','well above' - ts.match('#Copula (pretty|dead|full|well) (#Adjective|#Noun)').notIf('#Comma').tag('#Copula #Adverb #Adjective', 'sometimes-adverb'); - //sometimes not-adverbs - ts.match('#Copula [(just|alone)$]').tag('Adjective', 'not-adverb'); - //jack is guarded - ts.match('#Singular is #Adverb? [#PastTense$]').tag('Adjective', 'is-filled'); - } - //went to sleep - // ts.match('#Verb to #Verb').lastTerm().tag('Noun', 'verb-to-verb'); - //support a splattering of auxillaries before a verb - let advb = '(#Adverb|not)+?'; - if (ts.has(advb)) { - //had walked - ts.match(`(has|had) ${advb} #PastTense`).not('#Verb$').tag('Auxiliary', 'had-walked'); - //was walking - ts.match(`#Copula ${advb} #Gerund`).not('#Verb$').tag('Auxiliary', 'copula-walking'); - //been walking - ts.match(`(be|been) ${advb} #Gerund`).not('#Verb$').tag('Auxiliary', 'be-walking'); - //would walk - ts.match(`(#Modal|did) ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'modal-verb'); - //would have had - ts.match(`#Modal ${advb} have ${advb} had ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'would-have'); - //would be walking - ts.match(`(#Modal) ${advb} be ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'would-be'); - //would been walking - ts.match(`(#Modal|had|has) ${advb} been ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'would-be'); - //infinitive verbs suggest plural nouns - 'XYZ walk to the store' - // r.match(`#Singular+ #Infinitive`).match('#Singular+').tag('Plural', 'infinitive-make-plural'); - } - //fall over - ts.match('#PhrasalVerb #PhrasalVerb').lastTerm().tag('Particle', 'phrasal-particle'); - if (ts.has('#Gerund')) { - //walking is cool - ts.match('#Gerund #Adverb? not? #Copula').firstTerm().tag('Activity', 'gerund-copula'); - //walking should be fun - ts.match('#Gerund #Modal').firstTerm().tag('Activity', 'gerund-modal'); - //running-a-show - ts.match('#Gerund #Determiner [#Infinitive]').tag('Noun', 'running-a-show'); - //setting records - // ts.match('#Gerund [#PresentTense]').tag('Plural', 'setting-records'); - } - //will be cool -> Copula - if (ts.has('will #Adverb? not? #Adverb? be')) { - //will be running (not copula - if (ts.has('will #Adverb? not? #Adverb? be #Gerund') === false) { - //tag it all - ts.match('will not? be').tag('Copula', 'will-be-copula'); - //for more complex forms, just tag 'be' - ts.match('will #Adverb? not? #Adverb? be #Adjective').match('be').tag('Copula', 'be-copula'); - } - } - } - - if (ts.has('#Adjective')) { - //still good - ts.match('still #Adjective').match('still').tag('Adverb', 'still-advb'); - //big dreams, critical thinking - ts.match('#Adjective [#PresentTense]').tag('Noun', 'adj-presentTense'); - //will secure our - ts.match('will [#Adjective]').tag('Verb', 'will-adj'); - //cheering hard - dropped -ly's - ts.match('#PresentTense (hard|quick|long|bright|slow)').lastTerm().tag('Adverb', 'lazy-ly'); - //his fine - ts.match('(his|her|its) [#Adjective]').tag('Noun', 'his-fine'); - // - ts.match('#Noun #Adverb? [left]').tag('PastTense', 'left-verb'); - } - - if (ts.has('#TitleCase')) { - //FitBit Inc - ts.match('#TitleCase (ltd|co|inc|dept|assn|bros)').tag('Organization', 'org-abbrv'); - //Foo District - ts - .match('#TitleCase+ (district|region|province|county|prefecture|municipality|territory|burough|reservation)') - .tag('Region', 'foo-district'); - //District of Foo - ts - .match('(district|region|province|municipality|territory|burough|state) of #TitleCase') - .tag('Region', 'district-of-Foo'); - } - - if (ts.has('#Hyphenated')) { - //air-flow - ts.match('#Hyphenated #Hyphenated').match('#Noun #Verb').tag('Noun', 'hyphen-verb'); - let hyphen = ts.match('#Hyphenated+'); - if (hyphen.has('#Expression')) { - //ooh-wee - hyphen.tag('Expression', 'ooh-wee'); - } - } - - if (ts.has('#Place')) { - //West Norforlk - ts.match('(west|north|south|east|western|northern|southern|eastern)+ #Place').tag('Region', 'west-norfolk'); - //some us-state acronyms (exlude: al, in, la, mo, hi, me, md, ok..) - ts.match('#City [#Acronym]').match('(al|ak|az|ar|ca|ct|dc|fl|ga|id|il|nv|nh|nj|ny|oh|or|pa|sc|tn|tx|ut|vt|pr)').tag('Region', 'us-state'); - } - //misc: - //foot/feet - ts.match('(foot|feet)').tag('Noun', 'foot-noun'); - ts.match('#Value (foot|feet)').term(1).tag('Unit', 'foot-unit'); - //'u' as pronoun - ts.match('#Conjunction [u]').tag('Pronoun', 'u-pronoun-2'); - //'a/an' can mean 1 - "a hour" - ts.match('(a|an) (#Duration|hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)').ifNo('#Plural').term(0).tag('Value', 'a-is-one'); - //swear-words as non-expression POS - //nsfw - ts.match('holy (shit|fuck|hell)').tag('Expression', 'swears-expression'); - ts.match('#Determiner (shit|damn|hell)').term(1).tag('Noun', 'swears-noun'); - ts.match('(shit|damn|fuck) (#Determiner|#Possessive|them)').term(0).tag('Verb', 'swears-verb'); - ts.match('#Copula fucked up?').not('#Copula').tag('Adjective', 'swears-adjective'); - //6 am - ts.match('#Holiday (day|eve)').tag('Holiday', 'holiday-day'); - //timezones - ts.match('(standard|daylight|summer|eastern|pacific|central|mountain) standard? time').tag('Time', 'timezone'); - //canadian dollar, Brazilian pesos - ts.match('#Demonym #Currency').tag('Currency', 'demonym-currency'); - //about to go - ts.match('about to #Adverb? #Verb').match('about to').tag(['Auxiliary', 'Verb'], 'about-to'); - //Doctor john smith jr - ts.match('#Honorific #Person').tag('Person', 'honorific-person'); - ts.match('#Person (jr|sr|md)').tag('Person', 'person-honorific'); - //right of way - ts.match('(right|rights) of .').tag('Noun', 'right-of'); - return ts; -}; - -module.exports = corrections; - -},{}],122:[function(_dereq_,module,exports){ - -//a specificly-named thing, that should be capitalized -const properNoun = function(ts) { - if (ts.has('#Person') === true) { - ts.match('#FirstName #Person+').tag('ProperNoun'); - ts.match('#Person+ #LastName').tag('ProperNoun'); - } - if (ts.has('#Place') === true) { - ts.match('(#City|#Region|#Country)').tag('ProperNoun'); - } - ts.match('#Organization').tag('ProperNoun'); - ts.match('#Month').tag('ProperNoun'); - return ts; -}; -module.exports = properNoun; - -},{}],123:[function(_dereq_,module,exports){ - -//patterns are .match() statements to be run after the tagger -const posthoc = function(ts) { - const patterns = ts.world.patterns; - Object.keys(patterns).forEach((k) => { - ts.match(k).tag(patterns[k], 'post-hoc: ' + k); - }); - return ts; -}; -module.exports = posthoc; - -},{}],124:[function(_dereq_,module,exports){ -'use strict'; -const fixContraction = _dereq_('./fix'); - -const irregulars = { - wanna: ['want', 'to'], - gonna: ['going', 'to'], - im: ['i', 'am'], - alot: ['a', 'lot'], - - dont: ['do', 'not'], - dun: ['do', 'not'], - - ive: ['i', 'have'], - - "won't": ['will', 'not'], - wont: ['will', 'not'], - - "can't": ['can', 'not'], - cant: ['can', 'not'], - cannot: ['can', 'not'], - - // aint: ['is', 'not'], //or 'are' - // "ain't": ['is', 'not'], - "shan't": ['should', 'not'], - imma: ['I', 'will'], - - "where'd": ['where', 'did'], - whered: ['where', 'did'], - "when'd": ['when', 'did'], - whend: ['when', 'did'], - "how'd": ['how', 'did'], - howd: ['how', 'did'], - "what'd": ['what', 'did'], - whatd: ['what', 'did'], - "let's": ['let', 'us'], - - //multiple word contractions - dunno: ['do', 'not', 'know'], - brb: ['be', 'right', 'back'], - gtg: ['got', 'to', 'go'], - irl: ['in', 'real', 'life'], - tbh: ['to', 'be', 'honest'], - imo: ['in', 'my', 'opinion'], - til: ['today', 'i', 'learned'], - rn: ['right', 'now'], - twas: ['it', 'was'], - '@': ['at'] -}; - -//check irregulars -const checkIrregulars = ts => { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (irregulars[t.normal]) { - let fix = irregulars[t.normal]; - ts = fixContraction(ts, fix, i); - i += fix.length - 1; - } - } - return ts; -}; -module.exports = checkIrregulars; - -},{"./fix":128}],125:[function(_dereq_,module,exports){ -'use strict'; -const fixContraction = _dereq_('./fix'); -const splitContraction = _dereq_('./split'); - -//these are always contractions -const blacklist = { - 'that\'s': true, - 'there\'s': true -}; -const are = { - we: true, - they: true, - you: true -}; - -// "'s" may be a contraction or a possessive -// 'spencer's house' vs 'spencer's good' -const isPossessive = (ts, i) => { - let t = ts.terms[i]; - let next_t = ts.terms[i + 1]; - //a pronoun can't be possessive - "he's house" - if (t.tags.Pronoun || t.tags.QuestionWord) { - return false; - } - if (blacklist[t.normal]) { - return false; - } - //if end of sentence, it is possessive - "was spencer's" - if (!next_t) { - return true; - } - //an infinitive is probably mis-tagged - 'jamie's bite' - if (next_t.tags.Infinitive) { - return true; - } - //a gerund suggests 'is walking' - if (next_t.tags.VerbPhrase) { - return false; - } - //spencer's house - if (next_t.tags.Noun) { - return true; - } - //rocket's red glare - if (next_t.tags.Adjective && ts.terms[i + 2] && ts.terms[i + 2].tags.Noun) { - return true; - } - //an adjective suggests 'is good' - if (next_t.tags.Adjective || next_t.tags.Adverb || next_t.tags.Verb) { - return false; - } - return false; -}; - -// you ain't / i ain't. -const isAre = function(ts, i) { - let arr = ['is', 'not']; //default - //get what's it 'about' - if (ts.terms[i - 1]) { - let about = ts.terms[i - 1]; - //go back one more.. - if (about.tags.Adverb && ts.terms[i - 2]) { - about = ts.terms[i - 2]; - } - if (about.tags.Plural || are[about.normal] === true) { - arr[0] = 'are'; - } - } - return arr; -}; - -//handle ambigous contraction "'s" -const hardOne = ts => { - for (let i = 0; i < ts.terms.length; i++) { - //skip existing - if (ts.terms[i].silent_term) { - continue; - } - if (ts.terms[i].normal === 'ain\'t' || ts.terms[i].normal === 'aint') { - let arr = isAre(ts, i); - ts = fixContraction(ts, arr, i); - i += 1; - continue; - } - let parts = splitContraction(ts.terms[i]); - if (parts) { - //have we found a hard one - if (parts.end === 's') { - //spencer's house - if (isPossessive(ts, i)) { - ts.terms[i].tag('#Possessive', 'hard-contraction'); - continue; - } - let arr = [parts.start, 'is']; - if (ts.terms[i + 1]) { - let str = ts.terms[i].normal; - //he's walking -> is/was - if (ts.match(str + ' (#Negative|#Adverb|#Auxiliary)+? #Gerund').found) { - arr = [parts.start, 'is']; - } else if (ts.match(str + ' (#Negative|#Adverb|#Auxiliary)+? #Verb').found) { - //is vs has ('he's got milk') - arr = [parts.start, 'has']; - } - } - ts = fixContraction(ts, arr, i); - i += 1; - } - } - } - return ts; -}; - -module.exports = hardOne; - -},{"./fix":128,"./split":129}],126:[function(_dereq_,module,exports){ -'use strict'; -const fixContraction = _dereq_('./fix'); -const split = _dereq_('./split'); - -//the formulaic contraction types: -const easy_ends = { - ll: 'will', - // 'd': 'would', - ve: 'have', - re: 'are', - m: 'am', - 'n\'t': 'not' -//these ones are a bit tricksier: -// 't': 'not', -// 's': 'is' //or was -}; - -//unambiguous contractions, like "'ll" -const easyOnes = ts => { - for (let i = 0; i < ts.terms.length; i++) { - //skip existing - if (ts.terms[i].silent_term) { - continue; - } - let parts = split(ts.terms[i]); - if (parts) { - parts.start = parts.start.toLowerCase(); - - //make sure its an easy one - if (easy_ends[parts.end]) { - let arr = [parts.start, easy_ends[parts.end]]; - ts = fixContraction(ts, arr, i); - i += 1; - } - - //handle i'd -> 'i would' vs 'i had' - if (parts.end === 'd') { - //assume 'would' - let arr = [parts.start, 'would']; - //if next verb is past-tense, choose 'had' - if (ts.terms[i + 1] && ts.terms[i + 1].tags.PastTense) { - arr[1] = 'had'; - } - //also support '#Adverb #PastTense' - if (ts.terms[i + 2] && ts.terms[i + 2].tags.PastTense && ts.terms[i + 1].tags.Adverb) { - arr[1] = 'had'; - } - ts = fixContraction(ts, arr, i); - i += 1; - } - } - } - return ts; -}; -module.exports = easyOnes; - -},{"./fix":128,"./split":129}],127:[function(_dereq_,module,exports){ -'use strict'; -const fixContraction = _dereq_('./fix'); -const Term = _dereq_('../../../term'); - -const hasDash = function(t) { - let dashes = /(-|–|—)/; - return dashes.test(t.whitespace.before) || dashes.test(t.whitespace.after); -}; - -const numberRange = ts => { - //try to support number range, like 5-9, this way: - ts.match('#Hyphenated #Hyphenated').match('#NumericValue #NumericValue').tag('NumberRange'); - //otherwise, loop through and find them - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //skip existing - if (t.silent_term) { - continue; - } - if (t.tags.TextValue) { - continue; - } - //hyphens found in whitespace - '5 - 7' - if (t.tags.Value && ts.terms[i + 1] && i > 0 && (hasDash(t) || hasDash(ts.terms[i - 1])) && ts.terms[i - 1].tags.Value) { - let to = new Term('', ts.world); - to.silent_term = 'to'; - ts.insertAt(i, to); - ts.terms[i - 1].tag('NumberRange', 'number-number1'); - ts.terms[i].tag('NumberRange', 'number-number2'); - ts.terms[i].whitespace.before = ''; - ts.terms[i].whitespace.after = ''; - ts.terms[i + 1].tag('NumberRange', 'number-number3'); - return ts; - } - //add a silent term - if (t.tags.NumberRange) { - let arr = t.text.split(/(-|–|—)/); - arr[1] = 'to'; - ts = fixContraction(ts, arr, i); - ts.terms[i].tag(['NumberRange', 'NumericValue'], 'numRange-1'); - ts.terms[i + 1].tag(['NumberRange', 'Preposition'], 'numRange-silent'); - ts.terms[i + 2].tag(['NumberRange', 'NumericValue'], 'numRange-3'); - i += 2; - } - } - return ts; -}; -module.exports = numberRange; - -},{"../../../term":143,"./fix":128}],128:[function(_dereq_,module,exports){ -'use strict'; -const Term = _dereq_('../../../term'); - -const tags = { - not: 'Negative', - will: 'Verb', - would: 'Modal', - have: 'Verb', - are: 'Copula', - is: 'Copula', - am: 'Verb' -}; -//make sure the newly created term gets the easy tags -const easyTag = t => { - if (tags[t.silent_term]) { - t.tag(tags[t.silent_term]); - } -}; - -//add a silent term -const fixContraction = (ts, parts, i) => { - //add the interpretation to the contracted term - let one = ts.terms[i]; - one.silent_term = parts[0]; - //tag it as a contraction - one.tag('Contraction', 'tagger-contraction'); - - //add a new empty term - if (parts[1]) { - let two = new Term('', ts.world); - two.silent_term = parts[1]; - two.tag('Contraction', 'tagger-contraction'); - ts.insertAt(i + 1, two); - //ensure new term has no auto-whitspace - two.whitespace.before = ''; - two.whitespace.after = ''; - easyTag(two); - } - - //potentially it's three-contracted-terms, like 'dunno' - if (parts[2]) { - let three = new Term('', ts.world); - three.silent_term = parts[2]; - // ts.terms.push(three); - ts.insertAt(i + 2, three); - three.tag('Contraction', 'tagger-contraction'); - easyTag(three); - } - - return ts; -}; - -module.exports = fixContraction; - -},{"../../../term":143}],129:[function(_dereq_,module,exports){ -'use strict'; -const contraction = /^([a-z]+)'([a-z][a-z]?)$/i; -const possessive = /[a-z]s'$/i; - -const allowed = { - re: 1, - ve: 1, - ll: 1, - t: 1, - s: 1, - d: 1, - m: 1 -}; - -/** interpret a terms' contraction */ -const splitContraction = t => { - //handle this irregular one (shared trailing n) - if (t.normal === 'can\'t') { - return { - start: 'can', - end: 'n\'t' - }; - } - let parts = t.normal.match(contraction); - if (parts && parts[1] && allowed[parts[2]] === 1) { - //handle n't - if (parts[2] === 't' && parts[1].match(/[a-z]n$/)) { - parts[1] = parts[1].replace(/n$/, ''); - parts[2] = 'n\'t'; //dunno.. - } - //fix titlecase - if (t.tags.TitleCase === true) { - parts[1] = parts[1].replace(/^[a-z]/, x => x.toUpperCase()); - } - return { - start: parts[1], - end: parts[2] - }; - } - // "flanders' house" - if (possessive.test(t.text) === true) { - return { - start: t.normal.replace(/s'?$/, ''), - end: '' - }; - } - return null; -}; -module.exports = splitContraction; - -},{}],130:[function(_dereq_,module,exports){ -//yep, -//https://github.com/mathiasbynens/emoji-regex/blob/master/index.js -module.exports = /(?:0\u20E3\n1\u20E3|2\u20E3|3\u20E3|4\u20E3|5\u20E3|6\u20E3|7\u20E3|8\u20E3|9\u20E3|#\u20E3|\*\u20E3|\uD83C(?:\uDDE6\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF2|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFD|\uDDFF)|\uDDE7\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFC|\uDDFE|\uDDFF)|\uDDE8\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDE9\uD83C(?:\uDDEA|\uDDEC|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDFF)|\uDDEA\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDED|\uDDF7|\uDDF8|\uDDF9|\uDDFA)|\uDDEB\uD83C(?:\uDDEE|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDF7)|\uDDEC\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF1|\uDDF2|\uDDF3|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFE)|\uDDED\uD83C(?:\uDDF0|\uDDF2|\uDDF3|\uDDF7|\uDDF9|\uDDFA)|\uDDEE\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9)|\uDDEF\uD83C(?:\uDDEA|\uDDF2|\uDDF4|\uDDF5)|\uDDF0\uD83C(?:\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDF2|\uDDF3|\uDDF5|\uDDF7|\uDDFC|\uDDFE|\uDDFF)|\uDDF1\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDEE|\uDDF0|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFE)|\uDDF2\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDF3\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFF)|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C(?:\uDDE6|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF7|\uDDF8|\uDDF9|\uDDFC|\uDDFE)|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C(?:\uDDEA|\uDDF4|\uDDF8|\uDDFA|\uDDFC)|\uDDF8\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDE9|\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFD|\uDDFE|\uDDFF)|\uDDF9\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF9|\uDDFB|\uDDFC|\uDDFF)|\uDDFA\uD83C(?:\uDDE6|\uDDEC|\uDDF2|\uDDF8|\uDDFE|\uDDFF)|\uDDFB\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDEE|\uDDF3|\uDDFA)|\uDDFC\uD83C(?:\uDDEB|\uDDF8)|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C(?:\uDDEA|\uDDF9)|\uDDFF\uD83C(?:\uDDE6|\uDDF2|\uDDFC)))|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD79\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED0\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3]|\uD83E[\uDD10-\uDD18\uDD80-\uDD84\uDDC0]/g; - -},{}],131:[function(_dereq_,module,exports){ -//just some of the most common emoticons -//faster than -//http://stackoverflow.com/questions/28077049/regex-matching-emoticons -module.exports = { - ':(': true, - ':)': true, - ':P': true, - ':p': true, - ':O': true, - ':3': true, - ':|': true, - ':/': true, - ':\\': true, - ':$': true, - ':*': true, - ':@': true, - ':-(': true, - ':-)': true, - ':-P': true, - ':-p': true, - ':-O': true, - ':-3': true, - ':-|': true, - ':-/': true, - ':-\\': true, - ':-$': true, - ':-*': true, - ':-@': true, - ':^(': true, - ':^)': true, - ':^P': true, - ':^p': true, - ':^O': true, - ':^3': true, - ':^|': true, - ':^/': true, - ':^\\': true, - ':^$': true, - ':^*': true, - ':^@': true, - '):': true, - '(:': true, - '$:': true, - '*:': true, - ')-:': true, - '(-:': true, - '$-:': true, - '*-:': true, - ')^:': true, - '(^:': true, - '$^:': true, - '*^:': true, - '<3': true, - ' { - tags[k].downward = []; - //look for tags with this as parent - for (let i = 0; i < keys.length; i++) { - if (tags[keys[i]].isA && tags[keys[i]].isA === k) { - tags[k].downward.push(keys[i]); - } - } - }); -}; -module.exports = addDownword; - -},{}],136:[function(_dereq_,module,exports){ -'use strict'; - -//list of inconsistent parts-of-speech -module.exports = [ - //top-level pos are all inconsistent - [ - 'Noun', - 'Verb', - 'Adjective', - 'Adverb', - 'Determiner', - 'Conjunction', - 'Preposition', - 'QuestionWord', - 'Expression', - 'Url', - 'PhoneNumber', - 'Email', - 'Emoji' - ], - //exlusive-nouns - ['Person', 'Organization', 'Value', 'Place', 'Actor', 'Demonym', 'Pronoun'], - //acronyms - ['Acronym', 'Pronoun', 'Actor', 'Unit', 'Address'], - ['Acronym', 'Plural'], - //things that can't be plural - ['Plural', 'Singular'], - // ['Plural', 'Pronoun'], - // ['Plural', 'Person'], - // ['Plural', 'Organization'], - // ['Plural', 'Currency'], - // ['Plural', 'Ordinal'], - //exlusive-people - ['MaleName', 'FemaleName'], - ['FirstName', 'LastName', 'Honorific'], - //adjectives - ['Comparative', 'Superlative'], - //values - ['Value', 'Verb', 'Adjective'], - // ['Value', 'Year'], - ['Ordinal', 'Cardinal'], - ['TextValue', 'NumericValue'], - ['NiceNumber', 'TextValue'], - ['Ordinal', 'Currency'], //$5.50th - //verbs - ['PastTense', 'PresentTense', 'FutureTense'], - ['Pluperfect', 'Copula', 'Modal', 'Participle', 'Infinitive', 'Gerund', 'FuturePerfect', 'PerfectTense'], - ['Auxiliary', 'Noun', 'Value'], - //date - ['Month', 'WeekDay', 'Year', 'Duration', 'Holiday'], - ['Particle', 'Conjunction', 'Adverb', 'Preposition'], - ['Date', 'Verb', 'Adjective', 'Person'], - ['Date', 'Money', 'RomanNumeral', 'Fraction'], - //a/an -> 1 - ['Value', 'Determiner'], - ['Url', 'Value', 'HashTag', 'PhoneNumber', 'Emoji'], - //roman numerals - ['RomanNumeral', 'Fraction', 'NiceNumber'], - ['RomanNumeral', 'Money'], - //cases - ['UpperCase', 'TitleCase', 'CamelCase'], - //phrases - ['VerbPhrase', 'Noun', 'Adjective', 'Value'], - //QuestionWord - ['QuestionWord', 'VerbPhrase'], - //acronyms - ['Acronym', 'VerbPhrase'], -]; - -},{}],137:[function(_dereq_,module,exports){ -'use strict'; -const conflicts = _dereq_('./conflicts'); -const nouns = _dereq_('./tags/nouns'); -const verbs = _dereq_('./tags/verbs'); -const values = _dereq_('./tags/values'); -const dates = _dereq_('./tags/dates'); -const misc = _dereq_('./tags/misc'); -const addDownward = _dereq_('./addDownward'); - -//used for pretty-printing on the server-side -const colors = { - Noun: 'blue', - Date: 'red', - Value: 'red', - Verb: 'green', - Auxiliary: 'green', - Negative: 'green', - VerbPhrase: 'green', - Preposition: 'cyan', - Condition: 'cyan', - Conjunction: 'cyan', - Determiner: 'cyan', - Adjective: 'magenta', - Adverb: 'cyan' -}; - -//extend tagset with new tags -const addIn = function(obj, tags) { - Object.keys(obj).forEach(k => { - tags[k] = obj[k]; - }); -}; - -//add tags to remove when tagging this one -const addConflicts = function(tags) { - Object.keys(tags).forEach(k => { - tags[k].notA = {}; - for (let i = 0; i < conflicts.length; i++) { - let arr = conflicts[i]; - if (arr.indexOf(k) !== -1) { - arr = arr.filter(a => a !== k); - arr.forEach(e => { - tags[k].notA[e] = true; - }); - } - } - tags[k].notA = Object.keys(tags[k].notA); - }); -}; - -const addColors = function(tags) { - Object.keys(tags).forEach(k => { - if (colors[k]) { - tags[k].color = colors[k]; - return; - } - if (tags[k].isA && colors[tags[k].isA]) { - tags[k].color = colors[tags[k].isA]; - return; - } - if (tags[k].isA && tags[tags[k].isA].color) { - tags[k].color = tags[tags[k].isA].color; - } - }); -}; - -const build = () => { - let tags = {}; - addIn(nouns, tags); - addIn(verbs, tags); - addIn(values, tags); - addIn(dates, tags); - addIn(misc, tags); - //downstream - addDownward(tags); - //add enemies - addConflicts(tags); - //for nice-logging - addColors(tags); - return tags; -}; -module.exports = build(); - -},{"./addDownward":135,"./conflicts":136,"./tags/dates":138,"./tags/misc":139,"./tags/nouns":140,"./tags/values":141,"./tags/verbs":142}],138:[function(_dereq_,module,exports){ -module.exports = { - Date: {}, //not a noun, but usually is - Month: { - isA: 'Date', - also: 'Singular' - }, - WeekDay: { - isA: 'Date', - also: 'Noun' - }, - RelativeDay: { - isA: 'Date' - }, - Year: { - isA: 'Date' - }, - Duration: { - isA: 'Date', - also: 'Noun' - }, - Time: { - isA: 'Date', - also: 'Noun' - }, - Holiday: { - isA: 'Date', - also: 'Noun' - } -}; - -},{}],139:[function(_dereq_,module,exports){ -module.exports = { - Adjective: {}, - Comparable: { - isA: 'Adjective' - }, - Comparative: { - isA: 'Adjective' - }, - Superlative: { - isA: 'Adjective' - }, - - NumberRange: { - isA: 'Contraction' - }, - Adverb: {}, - - Currency: {}, - //glue - Determiner: {}, - Conjunction: {}, - Preposition: {}, - QuestionWord: {}, - RelativeProunoun: { - isA: 'Pronoun' - }, - Expression: {}, - Abbreviation: {}, - Url: {}, - PhoneNumber: {}, - HashTag: {}, - AtMention: { - is: 'Noun' - }, - Emoji: {}, - Email: {}, - - //non-exclusive - Condition: {}, - VerbPhrase: {}, - Auxiliary: {}, - Negative: {}, - Contraction: {}, - - TitleCase: {}, - CamelCase: {}, - UpperCase: {}, - Hyphenated: {}, - Acronym: {}, - ClauseEnd: {}, - - // Quotes - Quotation: {}, - StartQuotation: { - isA: 'Quotation' - }, - EndQuotation: { - isA: 'Quotation' - }, - //parentheses - Parentheses: {}, - EndBracket: { - isA: 'Parentheses' - }, - StartBracket: { - isA: 'Parentheses' - } -}; - -},{}],140:[function(_dereq_,module,exports){ -module.exports = { - Noun: {}, - // - singular - Singular: { - isA: 'Noun' - }, - //a specific thing that's capitalized - ProperNoun: { - isA: 'Noun' - }, - - // -- people - Person: { - isA: 'Singular' - }, - FirstName: { - isA: 'Person' - }, - MaleName: { - isA: 'FirstName' - }, - FemaleName: { - isA: 'FirstName' - }, - LastName: { - isA: 'Person' - }, - Honorific: { - isA: 'Noun' - }, - Place: { - isA: 'Singular' - }, - - // -- places - Country: { - isA: 'Place' - }, - City: { - isA: 'Place' - }, - Region: { - isA: 'Place' - }, - Address: { - isA: 'Place' - }, - Organization: { - isA: 'Singular' - }, - SportsTeam: { - isA: 'Organization' - }, - Company: { - isA: 'Organization' - }, - School: { - isA: 'Organization' - }, - - // - plural - Plural: { - isA: 'Noun' - }, - Uncountable: { - //(not plural or singular) - isA: 'Noun' - }, - Pronoun: { - isA: 'Noun' - }, - //a word for someone doing something -'plumber' - Actor: { - isA: 'Noun' - }, - //a gerund-as-noun - 'swimming' - Activity: { - isA: 'Noun' - }, - //'kilograms' - Unit: { - isA: 'Noun' - }, - //'Canadians' - Demonym: { - isA: 'Noun' - }, - //`john's` - Possessive: { - isA: 'Noun' - } -}; - -},{}],141:[function(_dereq_,module,exports){ -module.exports = { - Value: {}, - Ordinal: { - isA: 'Value' - }, - Cardinal: { - isA: 'Value' - }, - Multiple: { - isA: 'Value' - }, - RomanNumeral: { - isA: 'Cardinal' - }, - Fraction: { - isA: 'Value' - }, - TextValue: { - isA: 'Value' - }, - NumericValue: { - isA: 'Value' - }, - NiceNumber: { - isA: 'Value' - }, - Money: { - //isA: 'Cardinal' - }, - Percent: { - isA: 'Value' - } -}; - -},{}],142:[function(_dereq_,module,exports){ -module.exports = { - Verb: { - isA: 'VerbPhrase' - }, - PresentTense: { - isA: 'Verb' - }, - Infinitive: { - isA: 'PresentTense' - }, - Gerund: { - isA: 'PresentTense' - }, - PastTense: { - isA: 'Verb' - }, - PerfectTense: { - isA: 'Verb' - }, - FuturePerfect: { - isA: 'Verb' - }, - Pluperfect: { - isA: 'Verb' - }, - Copula: { - isA: 'Verb' - }, - Modal: { - isA: 'Verb' - }, - Participle: { - isA: 'Verb' - }, - Particle: { - isA: 'Verb' - }, - PhrasalVerb: { - isA: 'Verb' - } -}; - -},{}],143:[function(_dereq_,module,exports){ -'use strict'; -const fns = _dereq_('./paths').fns; -const build_whitespace = _dereq_('./whitespace'); -const makeUID = _dereq_('./makeUID'); -//normalization -const addNormal = _dereq_('./methods/normalize/normalize').addNormal; -const addRoot = _dereq_('./methods/normalize/root'); - -const Term = function(str, world) { - this.tags = {}; - this._text = fns.ensureString(str); - - // this.world = world; - Object.defineProperty(this, 'world', { - enumerable: false, // hide it from for..in - value: world - }); - // this.world = function() { - // return world; - // }; - //seperate whitespace from the text - let parsed = build_whitespace(this._text); - this.whitespace = parsed.whitespace; - this._text = parsed.text; - this.parent = null; - this.silent_term = ''; - this.lumped = false; - //normalize the _text - addNormal(this); - addRoot(this); - //has this term been modified - this.dirty = false; - //make a unique id for this term - this.uid = makeUID(this.normal); - - //getters/setters - Object.defineProperty(this, 'text', { - get: function() { - return this._text; - }, - set: function(txt) { - txt = txt || ''; - this._text = txt.trim(); - this.dirty = true; - // if (this._text !== txt) { - // console.log('|' + txt + '|'); - // console.log(build_whitespace(txt)); - // this.whitespace = build_whitespace(txt); - // console.log(this.whitespace); - // } - this.normalize(); - } - }); - //bit faster than .constructor.name or w/e - Object.defineProperty(this, 'isA', { - get: function() { - return 'Term'; - } - }); -}; - -/**run each time a new text is set */ -Term.prototype.normalize = function() { - addNormal(this); - addRoot(this); - return this; -}; -/** where in the sentence is it? zero-based. */ -Term.prototype.index = function() { - let ts = this.parentTerms; - if (!ts) { - return null; - } - return ts.terms.indexOf(this); -}; -/** make a copy with no originals to the original */ -Term.prototype.clone = function() { - let term = new Term(this._text, this.world); - term.tags = fns.copy(this.tags); - term.whitespace = fns.copy(this.whitespace); - term.silent_term = this.silent_term; - return term; -}; - -_dereq_('./methods/misc')(Term); -_dereq_('./methods/out')(Term); -_dereq_('./methods/tag')(Term); -_dereq_('./methods/case')(Term); -_dereq_('./methods/punctuation')(Term); - -module.exports = Term; - -},{"./makeUID":144,"./methods/case":146,"./methods/misc":147,"./methods/normalize/normalize":149,"./methods/normalize/root":150,"./methods/out":153,"./methods/punctuation":156,"./methods/tag":158,"./paths":161,"./whitespace":162}],144:[function(_dereq_,module,exports){ -'use strict'; -//this is a not-well-thought-out way to reduce our dependence on `object===object` original stuff -//generates a unique id for this term -//may need to change when the term really-transforms? not sure. -const uid = (str) => { - let nums = ''; - for(let i = 0; i < 5; i++) { - nums += parseInt(Math.random() * 9, 10); - } - return str + '-' + nums; -}; -module.exports = uid; - -},{}],145:[function(_dereq_,module,exports){ -'use strict'; -// const tagSet = require('../paths').tags; -const boringTags = { - Auxiliary: 1, - Possessive: 1, - TitleCase: 1, - ClauseEnd: 1, - Comma: 1, - CamelCase: 1, - UpperCase: 1, - Hyphenated: 1, - VerbPhrase: 1, - EndBracket: 1, - StartBracket: 1, - Parentheses: 1, - Quotation: 1, -}; - -const bestTag = function(t) { - const tagSet = t.world.tags; - let tags = Object.keys(t.tags); - tags = tags.sort(); //alphabetical, first - //then sort by #of parent tags - tags = tags.sort((a, b) => { - //bury the tags we dont want - if (!tagSet[a]) { - return 1; - } - if (boringTags[b] || !tagSet[b]) { - return -1; - } - if (tagSet[a].downward.length > tagSet[b].downward.length) { - return 1; - } - return 1; - }); - return tags[0]; -}; -module.exports = bestTag; - -},{}],146:[function(_dereq_,module,exports){ -'use strict'; - -const addMethods = Term => { - const methods = { - toUpperCase: function() { - this.text = this._text.toUpperCase(); - this.tag('#UpperCase', 'toUpperCase'); - return this; - }, - toLowerCase: function() { - this.text = this._text.toLowerCase(); - this.unTag('#TitleCase'); - this.unTag('#UpperCase'); - return this; - }, - toTitleCase: function() { - this.text = this._text.replace(/^ *[a-z]/, x => x.toUpperCase()); - this.tag('#TitleCase', 'toTitleCase'); - return this; - }, - //(camelCase() is handled in `./terms` ) - - /** is it titlecased because it deserves it? Like a person's name? */ - needsTitleCase: function() { - const titleCases = [ - 'Person', - 'Place', - 'Organization', - 'Acronym', - 'UpperCase', - 'Currency', - 'RomanNumeral', - 'Month', - 'WeekDay', - 'Holiday', - 'Demonym' - ]; - for (let i = 0; i < titleCases.length; i++) { - if (this.tags[titleCases[i]]) { - return true; - } - } - //specific words that keep their titlecase - //https://en.wikipedia.org/wiki/Capitonym - const irregulars = ['i', 'god', 'allah']; - for (let i = 0; i < irregulars.length; i++) { - if (this.normal === irregulars[i]) { - return true; - } - } - return false; - } - }; - //hook them into result.proto - Object.keys(methods).forEach(k => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; - -},{}],147:[function(_dereq_,module,exports){ -'use strict'; -const isAcronym = _dereq_('./normalize/isAcronym'); -const bestTag = _dereq_('./bestTag'); - -//regs- -const hasVowel = /[aeiouy]/i; -const hasLetter = /[a-z]/; -const hasNumber = /[0-9]/; - -const addMethods = (Term) => { - - const methods = { - /** which tag best-represents this term?*/ - bestTag: function () { - return bestTag(this); - }, - - /** is this term like F.B.I. or NBA */ - isAcronym: function () { - return isAcronym(this._text); - }, - /** check if it is word-like in english */ - isWord: function () { - let t = this; - //assume a contraction produces a word-word - if (t.silent_term) { - return true; - } - //no letters or numbers - if (/[a-z|A-Z|0-9]/.test(t.text) === false) { - return false; - } - //has letters, but with no vowels - if (t.normal.length > 3 && hasLetter.test(t.normal) === true && hasVowel.test(t.normal) === false && t.isAcronym() === false) { - return false; - } - //has numbers but not a 'value' - if (hasNumber.test(t.normal) === true && t.tags.hasOwnProperty('Value') === false) { - //s4e - if (/[a-z][0-9][a-z]/.test(t.normal) === true) { - return false; - } - //ensure it looks like a 'value' eg '-$4,231.00' - // if (/^([$-])*?([0-9,\.])*?([s\$%])*?$/.test(t.normal) === false) { - // return false; - // } - } - return true; - } - }; - //hook them into result.proto - Object.keys(methods).forEach((k) => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; - -},{"./bestTag":145,"./normalize/isAcronym":148}],148:[function(_dereq_,module,exports){ -'use strict'; -//regs - -const periodAcronym = /([A-Z]\.)+[A-Z]?,?$/; -const oneLetterAcronym = /^[A-Z]\.,?$/; -const noPeriodAcronym = /[A-Z]{2}('s|,)?$/; - -/** does it appear to be an acronym, like FBI or M.L.B. */ -const isAcronym = function(str) { - //like N.D.A - if (periodAcronym.test(str) === true) { - return true; - } - //like 'F.' - if (oneLetterAcronym.test(str) === true) { - return true; - } - //like NDA - if (noPeriodAcronym.test(str) === true) { - return true; - } - return false; -}; -module.exports = isAcronym; - -},{}],149:[function(_dereq_,module,exports){ -'use strict'; -const killUnicode = _dereq_('./unicode'); -const isAcronym = _dereq_('./isAcronym'); - -//some basic operations on a string to reduce noise -exports.normalize = function(str) { - str = str || ''; - str = str.toLowerCase(); - str = str.trim(); - let original = str; - //(very) rough ASCII transliteration - bjŏrk -> bjork - str = killUnicode(str); - //#tags, @mentions - str = str.replace(/^[#@]/, ''); - //punctuation - str = str.replace(/[,;.!?]+$/, ''); - // coerce single curly quotes - str = str.replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g, '\''); - // coerce double curly quotes - str = str.replace(/[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g, '"'); - //coerce Unicode ellipses - str = str.replace(/\u2026/g, '...'); - //en-dash - str = str.replace(/\u2013/g, '-'); - //lookin'->looking (make it easier for conjugation) - if (/[a-z][^aeiou]in['’]$/.test(str) === true) { - str = str.replace(/in['’]$/, 'ing'); - } - //turn re-enactment to reenactment - if (/^(re|un)-?[^aeiou]./.test(str) === true) { - str = str.replace('-', ''); - } - //strip leading & trailing grammatical punctuation - if (/^[:;]/.test(str) === false) { - str = str.replace(/\.{3,}$/g, ''); - str = str.replace(/['",\.!:;\?\)]+$/g, ''); - str = str.replace(/^['"\(]+/g, ''); - } - //do this again.. - str = str.trim(); - //oh shucks, - if (str === '') { - str = original; - } - return str; -}; - -exports.addNormal = function(term) { - let str = term._text || ''; - str = exports.normalize(str); - //compact acronyms - if (isAcronym(term._text)) { - str = str.replace(/\./g, ''); - } - //nice-numbers - str = str.replace(/([0-9]),([0-9])/g, '$1$2'); - term.normal = str; -}; - -// console.log(normalize('Dr. V Cooper')); - -},{"./isAcronym":148,"./unicode":151}],150:[function(_dereq_,module,exports){ -'use strict'; -// -const rootForm = function(term) { - let str = term.normal || term.silent_term || ''; - //handle apostrophes and stuff (go further than normalize()) - str = str.replace(/'s\b/, ''); - str = str.replace(/'$/, ''); - term.root = str; -}; - -module.exports = rootForm; - -},{}],151:[function(_dereq_,module,exports){ -'use strict'; -//a hugely-ignorant, and widely subjective transliteration of latin, cryllic, greek unicode characters to english ascii. -//approximate visual (not semantic or phonetic) relationship between unicode and ascii characters -//http://en.wikipedia.org/wiki/List_of_Unicode_characters -//https://docs.google.com/spreadsheet/ccc?key=0Ah46z755j7cVdFRDM1A2YVpwa1ZYWlpJM2pQZ003M0E -let compact = { - '!': '¡', - '?': '¿Ɂ', - '"': '“”"❝❞', - '\'': '‘‛❛❜', - '-': '—–', - 'a': 'ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАДадѦѧӐӑӒӓƛɅæ', - 'b': 'ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬбвъьѢѣҌҍҔҕƥƾ', - 'c': '¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾϿЄСсєҀҁҪҫ', - 'd': 'ÐĎďĐđƉƊȡƋƌǷ', - 'e': 'ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ', - 'f': 'ƑƒϜϝӺӻҒғӶӷſ', - 'g': 'ĜĝĞğĠġĢģƓǤǥǦǧǴǵ', - 'h': 'ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ', - 'I': 'ÌÍÎÏ', - 'i': 'ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії', - 'j': 'ĴĵǰȷɈɉϳЈј', - 'k': 'ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ', - 'l': 'ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ', - 'm': 'ΜϺϻМмӍӎ', - 'n': 'ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ', - 'o': 'ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ¤ƍΏ', - 'p': 'ƤƿΡρϷϸϼРрҎҏÞ', - 'q': 'Ɋɋ', - 'r': 'ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ', - 's': 'ŚśŜŝŞşŠšƧƨȘșȿςϚϛϟϨϩЅѕ', - 't': 'ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮϯТт҂Ҭҭ', - 'u': 'µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύϑЏЦЧцџҴҵҶҷӋӌӇӈ', - 'v': 'νѴѵѶѷ', - 'w': 'ŴŵƜωώϖϢϣШЩшщѡѿ', - 'x': '×ΧχϗϰХхҲҳӼӽӾӿ', - 'y': 'ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ', - 'z': 'ŹźŻżŽžƩƵƶȤȥɀΖζ' -}; -//decompress data into two hashes -let unicode = {}; -Object.keys(compact).forEach(function (k) { - compact[k].split('').forEach(function (s) { - unicode[s] = k; - }); -}); - -const killUnicode = (str) => { - let chars = str.split(''); - chars.forEach((s, i) => { - if (unicode[s]) { - chars[i] = unicode[s]; - } - }); - return chars.join(''); -}; -module.exports = killUnicode; -// console.log(killUnicode('bjŏȒk—Ɏó')); - -},{}],152:[function(_dereq_,module,exports){ -'use strict'; -const paths = _dereq_('../../paths'); -const fns = paths.fns; -const tagset = paths.tags; - -//a nicer logger for the client-side -const clientSide = (t) => { - let color = 'silver'; - let tags = Object.keys(t.tags); - for(let i = 0; i < tags.length; i++) { - if (tagset[tags[i]] && tagset[tags[i]].color) { - color = tagset[tags[i]].color; - break; - } - } - let word = fns.leftPad(t.text, 12); - word += ' ' + tags; - console.log('%c ' + word, 'color: ' + color); -}; -module.exports = clientSide; - -},{"../../paths":161}],153:[function(_dereq_,module,exports){ -'use strict'; -const renderHtml = _dereq_('./renderHtml'); -const clientDebug = _dereq_('./client'); -const serverDebug = _dereq_('./server'); - -const methods = { - /** a pixel-perfect reproduction of the input, with whitespace preserved */ - text: function(r) { - return (r.whitespace.before || '') + r._text + (r.whitespace.after || ''); - }, - /** a lowercased, punctuation-cleaned, whitespace-trimmed version of the word */ - normal: function(r) { - return r.normal; - }, - /** even-more normalized than normal */ - root: function(r) { - return r.root || r.normal; - }, - /** the &encoded term in a span element, with POS as classNames */ - html: function(r) { - return renderHtml(r); - }, - /** a simplified response for Part-of-Speech tagging*/ - tags: function(r) { - return { - text: r.text, - normal: r.normal, - tags: Object.keys(r.tags) - }; - }, - /** check-print information for the console */ - debug: function(t) { - if (typeof window === 'object') { - clientDebug(t); - } else { - serverDebug(t); - } - } -}; - -const addMethods = Term => { - //hook them into result.proto - Term.prototype.out = function(fn) { - if (!methods[fn]) { - fn = 'text'; - } - return methods[fn](this); - }; - return Term; -}; - -module.exports = addMethods; - -},{"./client":152,"./renderHtml":154,"./server":155}],154:[function(_dereq_,module,exports){ -'use strict'; -//turn xml special characters into apersand-encoding. -//i'm not sure this is perfectly safe. -const escapeHtml = (s) => { - const HTML_CHAR_MAP = { - '<': '<', - '>': '>', - '&': '&', - '"': '"', - '\'': ''', - ' ': ' ' - }; - return s.replace(/[<>&"' ]/g, function(ch) { - return HTML_CHAR_MAP[ch]; - }); -}; - -//remove html elements already in the text -//not tested! -//http://stackoverflow.com/questions/295566/sanitize-rewrite-html-on-the-client-side -const sanitize = (html) => { - const tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*'; - const tagOrComment = new RegExp( - '<(?:' - // Comment body. - + '!--(?:(?:-*[^->])*--+|-?)' - // Special "raw text" elements whose content should be elided. - + '|script\\b' + tagBody + '>[\\s\\S]*?[\\s\\S]*?', - 'gi'); - let oldHtml; - do { - oldHtml = html; - html = html.replace(tagOrComment, ''); - } while (html !== oldHtml); - return html.replace(/ tag !== 'Term'); - classes = classes.map(c => 'nl-' + c); - classes = classes.join(' '); - let text = sanitize(t.text); - text = escapeHtml(text); - let el = '' + text + ''; - return escapeHtml(t.whitespace.before) + el + escapeHtml(t.whitespace.after); -}; - -module.exports = renderHtml; - -},{}],155:[function(_dereq_,module,exports){ -'use strict'; -const fns = _dereq_('../../paths').fns; - -//pretty-print a term on the nodejs console -const serverDebug = function(t) { - let tags = Object.keys(t.tags) - .map(tag => { - return fns.printTag(tag); - }) - .join(', '); - let word = t.text; - word = '\'' + fns.yellow(word || '-') + '\''; - let silent = ''; - if (t.silent_term) { - silent = '[' + t.silent_term + ']'; - } - word = fns.leftPad(word, 20); - word += fns.leftPad(silent, 8); - console.log(' ' + word + ' ' + ' - ' + tags); -}; -module.exports = serverDebug; - -},{"../../paths":161}],156:[function(_dereq_,module,exports){ -'use strict'; -// const endPunct = /([^\/,:;.()!?]{0,1})([\/,:;.()!?]+)$/i; -const endPunct = /([a-z0-9 ])([,:;.!?]+)$/i; //old - -const addMethods = Term => { - const methods = { - /** the punctuation at the end of this term*/ - getPunctuation: function() { - let m = this.text.match(endPunct); - if (m) { - return m[2]; - } - m = this.whitespace.after.match(endPunct); - if (m) { - return m[2]; - } - return null; - }, - - setPunctuation: function(punct) { - this.killPunctuation(); - this.text += punct; - if (punct === ',') { - this.tags.Comma = true; - } - return this; - }, - - /** check if the term ends with a comma */ - hasComma: function() { - if (this.getPunctuation() === ',') { - return true; - } - return false; - }, - - killPunctuation: function() { - this.text = this._text.replace(endPunct, '$1'); - delete this.tags.Comma; - delete this.tags.ClauseEnd; - return this; - } - }; - //hook them into result.proto - Object.keys(methods).forEach(k => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; - -},{}],157:[function(_dereq_,module,exports){ -'use strict'; - -//recursively-check compatibility of this tag and term -const canBe = function(term, tag) { - const tagset = term.world.tags; - //fail-fast - if (tagset[tag] === undefined) { - return true; - } - //loop through tag's contradictory tags - let enemies = tagset[tag].notA || []; - for (let i = 0; i < enemies.length; i++) { - if (term.tags[enemies[i]] === true) { - return false; - } - } - if (tagset[tag].isA !== undefined) { - return canBe(term, tagset[tag].isA); //recursive - } - return true; -}; - -module.exports = canBe; - -},{}],158:[function(_dereq_,module,exports){ -'use strict'; -const setTag = _dereq_('./setTag'); -const unTag = _dereq_('./unTag'); -const canBe = _dereq_('./canBe'); - -//symbols used in sequential taggers which mean 'do nothing' -//.tag('#Person #Place . #City') -const ignore = { - '.': true -}; -const addMethods = (Term) => { - - const methods = { - /** set the term as this part-of-speech */ - tag: function(tag, reason) { - if (ignore[tag] !== true) { - setTag(this, tag, reason); - } - }, - /** remove this part-of-speech from the term*/ - unTag: function(tag, reason) { - if (ignore[tag] !== true) { - unTag(this, tag, reason); - } - }, - /** is this tag compatible with this word */ - canBe: function (tag) { - tag = tag || ''; - if (typeof tag === 'string') { - //everything can be '.' - if (ignore[tag] === true) { - return true; - } - tag = tag.replace(/^#/, ''); - } - return canBe(this, tag); - } - }; - - //hook them into term.prototype - Object.keys(methods).forEach((k) => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; - -},{"./canBe":157,"./setTag":159,"./unTag":160}],159:[function(_dereq_,module,exports){ -'use strict'; -//set a term as a particular Part-of-speech -const path = _dereq_('../../paths'); -const log = path.log; -const fns = path.fns; -const unTag = _dereq_('./unTag'); -// const tagset = path.tags; -// const tagset = require('../../../tagset'); - -const putTag = (term, tag, reason) => { - const tagset = term.world.tags; - tag = tag.replace(/^#/, ''); - //already got this - if (term.tags[tag] === true) { - return; - } - term.tags[tag] = true; - log.tag(term, tag, reason); - - //extra logic per-each POS - if (tagset[tag]) { - //drop any conflicting tags - let enemies = tagset[tag].notA || []; - for (let i = 0; i < enemies.length; i++) { - if (term.tags[enemies[i]] === true) { - unTag(term, enemies[i], reason); - } - } - //apply implicit tags - if (tagset[tag].isA) { - let doAlso = tagset[tag].isA; - if (term.tags[doAlso] !== true) { - putTag(term, doAlso, ' --> ' + tag); //recursive - } - } - } -}; - -//give term this tag -const wrap = function(term, tag, reason) { - if (!term || !tag) { - return; - } - const tagset = term.world.tags; - //handle multiple tags - if (fns.isArray(tag)) { - tag.forEach(t => putTag(term, t, reason)); //recursive - return; - } - putTag(term, tag, reason); - //add 'extra' tag (for some special tags) - if (tagset[tag] && tagset[tag].also !== undefined) { - putTag(term, tagset[tag].also, reason); - } -}; - -module.exports = wrap; - -},{"../../paths":161,"./unTag":160}],160:[function(_dereq_,module,exports){ -'use strict'; -//set a term as a particular Part-of-speech -const path = _dereq_('../../paths'); -const log = path.log; - -//remove a tag from a term -const unTag = (term, tag, reason) => { - const tagset = term.world.tags; - if (term.tags[tag]) { - log.unTag(term, tag, reason); - delete term.tags[tag]; - - //delete downstream tags too - if (tagset[tag]) { - let also = tagset[tag].downward; - for (let i = 0; i < also.length; i++) { - unTag(term, also[i], ' - - - '); - } - } - } -}; - -const wrap = (term, tag, reason) => { - if (!term || !tag) { - return; - } - //support '*' flag - remove all-tags - if (tag === '*') { - term.tags = {}; - return; - } - //remove this tag - unTag(term, tag, reason); - return; -}; -module.exports = wrap; - -},{"../../paths":161}],161:[function(_dereq_,module,exports){ -module.exports = { - fns: _dereq_('../fns'), - log: _dereq_('../log'), - tags: _dereq_('../tags') -}; - -},{"../fns":3,"../log":6,"../tags":137}],162:[function(_dereq_,module,exports){ -'use strict'; -//punctuation regs- are we having fun yet? -const before = /^(\s|-+|\.\.+|\/|"|\u0022|\uFF02|\u0027|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\u00AB|\u2039|\u2035|\u2036|\u2037|\u301D|\u0060|\u301F)+/u; -// const after = /(\s+|-+|\.\.+|"|\u0022|\uFF02|\u0027|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4)+$/u; -const afterSoft = /(\s+|-+|\.\.+|"|\u0022|\uFF02|\u0027|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4)+[,;.!? ]*$/u; -const minusNumber = /^( *)-(\$|€|¥|£)?([0-9])/; - -//seperate the 'meat' from the trailing/leading whitespace. -//works in concert with ./src/text/tokenize.js -const build_whitespace = (str) => { - let whitespace = { - before: '', - after: '' - }; - //get before punctuation/whitespace - //mangle 'far - fetched', but don't mangle '-2' - let m = str.match(minusNumber); - if (m !== null) { - whitespace.before = m[1]; - str = str.replace(/^ */, ''); - } else { - m = str.match(before); - if (m !== null) { - whitespace.before = m[0]; - str = str.replace(before, ''); - } - } - //get after punctuation/whitespace - m = str.match(afterSoft); - if (m !== null) { - str = str.replace(afterSoft, ''); - whitespace.after = m[0]; - } - return { - whitespace: whitespace, - text: str - }; -}; -module.exports = build_whitespace; - -},{}],163:[function(_dereq_,module,exports){ -'use strict'; -const Term = _dereq_('../term'); -const wordlike = /\S/; -const isBoundary = /^[!?.]+$/; - -const notWord = { - '.': true, - '-': true, //dash - '–': true, //en-dash - '—': true, //em-dash - '--': true, - '...': true -}; - -const hasHyphen = function(str) { - //dont split 're-do' - if (/^(re|un)-?[^aeiou]./.test(str) === true) { - return false; - } - //letter-number - let reg = /^([a-z`"'/]+)(-|–|—)([a-z0-9].*)/i; - if (reg.test(str) === true) { - return true; - } - //number-letter - // reg = /^([0-9]+)(-|–|—)([a-z].*)/i; - // if (reg.test(str) === true) { - // return true; - // } - //support weird number-emdash combo '2010–2011' - let reg2 = /^([0-9]+)(–|—)([0-9].*)/i; - if (reg2.test(str)) { - return true; - } - return false; -}; - -//support splitting terms like "open/closed" -const hasSlash = function(word) { - const reg = /[a-z]\/[a-z]/; - if (reg.test(word)) { - //only one slash though - if (word.split(/\//g).length === 2) { - return true; - } - } - return false; -}; - -//turn a string into an array of terms (naiive for now, lumped later) -const fromString = function(str, world) { - let result = []; - let arr = []; - //start with a naiive split - str = str || ''; - if (typeof str === 'number') { - str = String(str); - } - const firstSplit = str.split(/(\S+)/); - for (let i = 0; i < firstSplit.length; i++) { - const word = firstSplit[i]; - if (hasHyphen(word) === true) { - //support multiple-hyphenated-terms - const hyphens = word.split(/[-–—]/); - for (let o = 0; o < hyphens.length; o++) { - if (o === hyphens.length - 1) { - arr.push(hyphens[o]); - } else { - arr.push(hyphens[o] + '-'); - } - } - } else if (hasSlash(word) === true) { - const slashes = word.split(/\//); - arr.push(slashes[0]); - arr.push('/' + slashes[1]); - } else { - arr.push(word); - } - } - //greedy merge whitespace+arr to the right - let carry = ''; - for (let i = 0; i < arr.length; i++) { - //if it's more than a whitespace - if ( - wordlike.test(arr[i]) === true && - notWord.hasOwnProperty(arr[i]) === false && - isBoundary.test(arr[i]) === false - ) { - result.push(carry + arr[i]); - carry = ''; - } else { - carry += arr[i]; - } - } - //handle last one - if (carry && result.length > 0) { - result[result.length - 1] += carry; //put it on the end - } - return result.map(t => new Term(t, world)); -}; -module.exports = fromString; - -},{"../term":143}],164:[function(_dereq_,module,exports){ -'use strict'; - -//getters/setters for the Terms class -module.exports = { - - parent: { - get: function() { - return this.refText || this; - }, - set: function(r) { - this.refText = r; - return this; - } - }, - - parentTerms: { - get: function() { - return this.refTerms || this; - }, - set: function(r) { - this.refTerms = r; - return this; - } - }, - - dirty: { - get: function() { - for(let i = 0; i < this.terms.length; i++) { - if (this.terms[i].dirty === true) { - return true; - } - } - return false; - }, - set: function(dirt) { - this.terms.forEach((t) => { - t.dirty = dirt; - }); - } - }, - - refTerms: { - get: function() { - return this._refTerms || this; - }, - set: function(ts) { - this._refTerms = ts; - return this; - } - }, - found: { - get: function() { - return this.terms.length > 0; - } - }, - length: { - get: function() { - return this.terms.length; - } - }, - isA: { - get: function() { - return 'Terms'; - } - }, - whitespace: { - get: function() { - return { - before: (str) => { - this.firstTerm().whitespace.before = str; - return this; - }, - after: (str) => { - this.lastTerm().whitespace.after = str; - return this; - }, - }; - } - }, - - -}; - -},{}],165:[function(_dereq_,module,exports){ -'use strict'; -const build = _dereq_('./build'); -const getters = _dereq_('./getters'); -let w = _dereq_('../world'); - -//Terms is an array of Term objects, and methods that wrap around them -const Terms = function(arr, world, refText, refTerms) { - this.terms = arr; - this.world = world || w; - this.refText = refText; - this._refTerms = refTerms; - this.get = n => { - return this.terms[n]; - }; - //apply getters - let keys = Object.keys(getters); - for (let i = 0; i < keys.length; i++) { - Object.defineProperty(this, keys[i], getters[keys[i]]); - } -}; - -Terms.fromString = function(str, world) { - let termArr = build(str, world); - let ts = new Terms(termArr, world, null); - //give each term a original to this ts - ts.terms.forEach(t => { - t.parentTerms = ts; - }); - return ts; -}; - -// Terms = require('./methods/lookup')(Terms); -_dereq_('./match')(Terms); -_dereq_('./methods/tag')(Terms); -_dereq_('./methods/loops')(Terms); -_dereq_('./match/not')(Terms); -_dereq_('./methods/delete')(Terms); -_dereq_('./methods/insert')(Terms); -_dereq_('./methods/misc')(Terms); -_dereq_('./methods/out')(Terms); -_dereq_('./methods/replace')(Terms); -_dereq_('./methods/split')(Terms); -_dereq_('./methods/transform')(Terms); -_dereq_('./methods/lump')(Terms); -module.exports = Terms; - -},{"../world":215,"./build":163,"./getters":164,"./match":166,"./match/not":176,"./methods/delete":177,"./methods/insert":178,"./methods/loops":179,"./methods/lump":181,"./methods/misc":182,"./methods/out":183,"./methods/replace":184,"./methods/split":185,"./methods/tag":186,"./methods/transform":187}],166:[function(_dereq_,module,exports){ -'use strict'; -const syntax = _dereq_('./lib/syntax'); -const startHere = _dereq_('./lib/startHere'); -const Text = _dereq_('../../text'); -const match = _dereq_('./lib'); - -const matchMethods = Terms => { - const methods = { - //support regex-like whitelist-match - match: function (reg, verbose) { - //fail-fast #1 - if (this.terms.length === 0) { - return new Text([], this.world, this.parent); - } - //fail-fast #2 - if (!reg) { - return new Text([], this.world, this.parent); - } - let matches = match(this, reg, verbose); - matches = matches.map(a => { - return new Terms(a, this.world, this.refText, this.refTerms); - }); - return new Text(matches, this.world, this.parent); - }, - - /**return first match */ - matchOne: function (str) { - //fail-fast - if (this.terms.length === 0) { - return null; - } - let regs = syntax(str); - for (let t = 0; t < this.terms.length; t++) { - //don't loop through if '^' - if (regs[0] && regs[0].starting && t > 0) { - break; - } - let m = startHere(this, t, regs); - if (m) { - return m; - } - } - return null; - }, - - /**return first match */ - has: function (str) { - return this.matchOne(str) !== null; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = matchMethods; - -},{"../../text":192,"./lib":170,"./lib/startHere":174,"./lib/syntax":175}],167:[function(_dereq_,module,exports){ -'use strict'; -//applies the reg capture group setting to the term -const applyCaptureGroup = (term, reg) => { - if (reg.capture) { - term.captureGroup = true; - } else { - term.captureGroup = undefined; - } -}; -module.exports = applyCaptureGroup; -},{}],168:[function(_dereq_,module,exports){ -'use strict'; -//take all the matches, and if there is a [capture group], only return that. -const onlyCaptureGroup = function(matches) { - let results = []; - matches.forEach((terms) => { - //if there's no capture group, we good. - if (terms.filter(t => t.captureGroup === true).length === 0) { - results.push(terms); - return; - } - //otherwise, just return them as seperate subsets - let current = []; - for(let i = 0; i < terms.length; i += 1) { - if (terms[i].captureGroup) { - current.push(terms[i]); - } else if (current.length > 0) { - results.push(current); - current = []; - } - } - if (current.length > 0) { - results.push(current); - } - }); - return results; -}; -module.exports = onlyCaptureGroup; - -},{}],169:[function(_dereq_,module,exports){ -'use strict'; -// -//find easy reasons to skip running the full match on this -const fastPass = (ts, regs) => { - for (let i = 0; i < regs.length; i++) { - let reg = regs[i]; - let found = false; - //we can't cheat on these fancy rules: - if (reg.optional === true || reg.negative === true || reg.minMax !== undefined) { - continue; - } - //look-for missing term-matches - if (reg.normal !== undefined) { - for (let o = 0; o < ts.terms.length; o++) { - if (ts.terms[o].normal === reg.normal || ts.terms[o].silent_term === reg.normal) { - found = true; - break; - } - //we can't handle lumped-terms with this method - if (ts.terms[o].lumped === true) { - return false; - } - } - if (found === false) { - return true; - } - } - //look for missing tags - if (reg.tag !== undefined) { - for (let o = 0; o < ts.terms.length; o++) { - if (ts.terms[o].tags[reg.tag] === true) { - found = true; - break; - } - } - if (found === false) { - return true; - } - } - } - return false; -}; -module.exports = fastPass; - -},{}],170:[function(_dereq_,module,exports){ -'use strict'; -const syntax = _dereq_('./syntax'); -const startHere = _dereq_('./startHere'); -const fastPass = _dereq_('./fastPass'); -const handleCaptureGroup = _dereq_('./captureGroup'); - -//ensure we have atleast one non-optional demand -// const isTautology = function(regs) { -// for (let i = 0; i < regs.length; i++) { -// if (!regs[i].optional && !regs[i].astrix && !regs[i].anyOne) { -// return false; -// } -// } -// return true; -// }; - -//make a reg syntax from a text object -const findFromTerms = function(ts) { - if (!ts) { - return []; - } - let arr = ts.terms.map(t => { - return { - id: t.uid - }; - }); - return arr; -}; -// -const match = (ts, reg, verbose) => { - //parse for backwards-compatibility - if (typeof reg === 'string') { - reg = syntax(reg); - } else if (reg && reg.isA === 'Text') { - reg = findFromTerms(reg.list[0]); - } else if (reg && reg.isA === 'Terms') { - reg = findFromTerms(reg); - } - if (!reg || reg.length === 0) { - return []; - } - //do a fast-pass for easy negatives - if (fastPass(ts, reg, verbose) === true) { - return []; - } - //ok, start long-match - let matches = []; - for (let t = 0; t < ts.terms.length; t += 1) { - //don't loop through if '^' - if (t > 0 && reg[0] && reg[0].starting) { - break; - } - let m = startHere(ts, t, reg, verbose); - if (m && m.length > 0) { - matches.push(m); - //handle capture-groups subset - // let hasCapture=matches - //ok, don't try to match these again. - let skip = m.length - 1; - t += skip; //this could use some work - } - } - //handle capture-group subset - matches = handleCaptureGroup(matches); - return matches; -}; -module.exports = match; - -},{"./captureGroup":168,"./fastPass":169,"./startHere":174,"./syntax":175}],171:[function(_dereq_,module,exports){ -'use strict'; -const applyCaptureGroup = _dereq_('./applyCaptureGroup'); - -//compare 1 term to one reg -const perfectMatch = (term, reg) => { - if (!term || !reg) { - return false; - } - //support '.' - any - if (reg.anyOne === true) { - return true; - } - //pos-match - if (reg.tag !== undefined) { - return term.tags[reg.tag]; - } - //id-match - if (reg.id !== undefined) { - return reg.id === term.uid; - } - //text-match - if (reg.normal !== undefined) { - return reg.normal === term.normal || reg.normal === term.silent_term; - } - //suffix matches '-nny' - if (reg.suffix === true && reg.partial !== undefined) { - const len = term.normal.length; - return term.normal.substr(len - reg.partial.length, len) === reg.partial; - } - //prefix matches 'fun-' - if (reg.prefix === true && reg.partial !== undefined) { - return term.normal.substr(0, reg.partial.length) === reg.partial; - } - //infix matches '-nn-' - if (reg.infix === true && reg.partial) { - return term.normal.indexOf(reg.partial) !== -1; - } - //full-on regex-match '/a*?/' - if (reg.regex !== undefined) { - return reg.regex.test(term.normal) || reg.regex.test(term.text); - } - //one-of term-match - if (reg.oneOf !== undefined) { - for (let i = 0; i < reg.oneOf.tagArr.length; i++) { - if (term.tags.hasOwnProperty(reg.oneOf.tagArr[i]) === true) { - return true; - } - } - return reg.oneOf.terms.hasOwnProperty(term.normal) || reg.oneOf.terms.hasOwnProperty(term.silent_term); - } - return false; -}; - -//wrap above method, to support '!' negation -const isMatch = (term, reg, verbose) => { - if (!term || !reg) { - return false; - } - let found = perfectMatch(term, reg, verbose); - //reverse it for .not() - if (reg.negative) { - found = !Boolean(found); - } - if (found) { - //only apply capture group settings to matches - applyCaptureGroup(term, reg); - } - return found; -}; -module.exports = isMatch; - -},{"./applyCaptureGroup":167}],172:[function(_dereq_,module,exports){ -'use strict'; - -const almostMatch = (reg_str, term) => { - let want = term.normal.substr(0, reg_str.length); - return want === reg_str; -}; - -// match ['john', 'smith'] regs, when the term is lumped -const lumpMatch = function(term, regs, reg_i) { - let reg_str = regs[reg_i].normal; - //is this a partial match? 'tony'& 'tony hawk' - if (reg_str !== undefined && almostMatch(reg_str, term)) { - //try to grow it - reg_i = reg_i + 1; - for (reg_i; reg_i < regs.length; reg_i++) { - reg_str += ' ' + regs[reg_i].normal; - // is it now perfect? - if (reg_str === term.normal) { - return reg_i; - } - // is it still almost? - if (almostMatch(reg_str, term) === false) { - return null; - } - } - } - return null; -}; - -module.exports = lumpMatch; - -},{}],173:[function(_dereq_,module,exports){ -arguments[4][73][0].apply(exports,arguments) -},{"../../paths":189,"dup":73}],174:[function(_dereq_,module,exports){ -'use strict'; -const lumpMatch = _dereq_('./lumpMatch'); -const isMatch = _dereq_('./isMatch'); -const applyCaptureGroup = _dereq_('./applyCaptureGroup'); - -// match everything until this point - '*' -const greedyUntil = (ts, i, reg) => { - for (; i < ts.length; i++) { - if (isMatch(ts.terms[i], reg)) { - return i; - } - } - return null; -}; - -//keep matching this reg as long as possible -const greedyOf = (ts, i, reg, until) => { - for (; i < ts.length; i++) { - let t = ts.terms[i]; - //found next reg ('until') - if (until && isMatch(t, until)) { - return i; - } - //stop here - if (!isMatch(t, reg)) { - return i; - } - } - return i; -}; - -//try and match all regs, starting at this term -const startHere = (ts, startAt, regs, verbose) => { - let term_i = startAt; - //check each regex-thing - for (let reg_i = 0; reg_i < regs.length; reg_i++) { - let term = ts.terms[term_i]; - let reg = regs[reg_i]; - let next_reg = regs[reg_i + 1]; - - if (!term) { - //we didn't need it anyways - if (reg.optional === true) { - continue; - } - return null; - } - - //catch '^' errors - if (reg.starting === true && term_i > 0) { - return null; - } - - //catch '$' errors - if (reg.ending === true && term_i !== ts.length - 1 && !reg.minMax) { - return null; - } - - //support '*' - if (reg.astrix === true) { - //just grab until the end.. - if (!next_reg) { - let terms = ts.terms.slice(startAt, ts.length); - //apply capture group settings for all wildcard terms - for (let wildcardTerm_i = term_i - startAt; wildcardTerm_i < terms.length; wildcardTerm_i++) { - applyCaptureGroup(terms[wildcardTerm_i], reg); - } - return terms; - } - let foundAt = greedyUntil(ts, term_i, regs[reg_i + 1]); - if (!foundAt) { - return null; - } - //apply capture group settings for all wildcard terms - for (let wildcardTerm_i = term_i; wildcardTerm_i < foundAt; wildcardTerm_i++) { - applyCaptureGroup(ts.terms[wildcardTerm_i], reg) - } - term_i = foundAt + 1; - reg_i += 1; - continue; - } - - //support '#Noun{x,y}' - if (regs[reg_i].minMax !== undefined) { - let min = regs[reg_i].minMax.min || 0; - let max = regs[reg_i].minMax.max; - let until = regs[reg_i + 1]; - for (let i = 0; i < max; i++) { - //ergh, please clean this loop up.. - let t = ts.terms[term_i + i]; - if (!t) { - return null; - } - //end here - if (isMatch(t, reg) === false) { - return null; - } - //should we be greedier? - if (i < min - 1) { - continue; //gotta keep going! - } - //we can end here, after the minimum - if (!until) { - term_i += 1; - break; - } - // we're greedy-to-now - if (i >= min && isMatch(t, until)) { - break; - } - //end with a greedy-match for next term - let nextT = ts.terms[term_i + i + 1]; - if (nextT && isMatch(nextT, until)) { - term_i += i + 2; - reg_i += 1; - break; - } else if (i === max - 1) { - //we've maxed-out - return null; - } - } - continue; - } - - //if optional, check next one - if (reg.optional === true) { - let until = regs[reg_i + 1]; - term_i = greedyOf(ts, term_i, reg, until); - continue; - } - - //check a perfect match - if (isMatch(term, reg, verbose)) { - term_i += 1; - //try to greedy-match '+' - if (reg.consecutive === true) { - let until = regs[reg_i + 1]; - term_i = greedyOf(ts, term_i, reg, until); - } - continue; - } - - if (term.silent_term && !term.normal) { - //skip over silent contraction terms - //we will continue on it, but not start on it - if (reg_i === 0) { - return null; - } - //try the next term, but with this regex again - term_i += 1; - reg_i -= 1; - continue; - } - - //handle partial-matches of lumped terms - let lumpUntil = lumpMatch(term, regs, reg_i, verbose); - if (lumpUntil !== null) { - reg_i = lumpUntil; - term_i += 1; - continue; - } - - //was it optional anways? - if (reg.optional === true) { - continue; - } - return null; - } - return ts.terms.slice(startAt, term_i); -}; - -module.exports = startHere; - -},{"./applyCaptureGroup":167,"./isMatch":171,"./lumpMatch":172}],175:[function(_dereq_,module,exports){ -'use strict'; -// parse a search lookup term find the regex-like syntax in this term -const fns = _dereq_('./paths').fns; -//regs- -const range = /\{[0-9,]+\}$/; - -//trim char#0 -const noFirst = function(str) { - return str.substr(1, str.length); -}; -const noLast = function(str) { - return str.substring(0, str.length - 1); -}; - -//turn 'regex-like' search string into parsed json -const parse_term = function(term) { - term = term || ''; - term = term.trim(); - - let reg = {}; - //order matters here - - //1-character hasta be a text-match - if (term.length === 1 && term !== '.' && term !== '*') { - reg.normal = term.toLowerCase(); - return reg; - } - //negation ! flag - if (term.charAt(0) === '!') { - term = noFirst(term); - reg.negative = true; - } - //leading ^ flag - if (term.charAt(0) === '^') { - term = noFirst(term); - reg.starting = true; - } - //trailing $ flag means ending - if (term.charAt(term.length - 1) === '$') { - term = noLast(term); - reg.ending = true; - } - //optional flag - if (term.charAt(term.length - 1) === '?') { - term = noLast(term); - reg.optional = true; - } - //atleast-one-but-greedy flag - if (term.charAt(term.length - 1) === '+') { - term = noLast(term); - reg.consecutive = true; - } - //prefix/suffix/infix matches - if (term.charAt(term.length - 1) === '_') { - term = noLast(term); - reg.prefix = true; - //try both '-match-' - if (term.charAt(0) === '_') { - term = noFirst(term); - reg.prefix = undefined; - reg.infix = true; - } - reg.partial = term; - term = ''; - } else if (term.charAt(0) === '_') { - term = noFirst(term); - reg.suffix = true; - reg.partial = term; - term = ''; - } - //min/max any '{1,3}' - if (term.charAt(term.length - 1) === '}' && range.test(term) === true) { - let m = term.match(/\{([0-9])*,? ?([0-9]+)\}/); - reg.minMax = { - min: parseInt(m[1], 10) || 0, - max: parseInt(m[2], 10) - }; - term = term.replace(range, ''); - } - //pos flag - if (term.charAt(0) === '#') { - term = noFirst(term); - reg.tag = fns.titleCase(term); - term = ''; - } - //support /regex/ mode - if (term.charAt(0) === '/' && term.charAt(term.length - 1) === '/') { - term = noLast(term); - term = noFirst(term); - //actually make the regex - reg.regex = new RegExp(term, 'i'); - term = ''; - } - //one_of options flag - if (term.charAt(0) === '(' && term.charAt(term.length - 1) === ')') { - term = noLast(term); - term = noFirst(term); - let arr = term.split(/\|/g); - reg.oneOf = { - terms: {}, - tagArr: [] - }; - arr.forEach(str => { - //try a tag match - if (str.charAt(0) === '#') { - let tag = str.substr(1, str.length); - tag = fns.titleCase(tag); - reg.oneOf.tagArr.push(tag); - } else { - reg.oneOf.terms[str] = true; - } - }); - term = ''; - } - //a period means any one term - if (term === '.') { - reg.anyOne = true; - term = ''; - } - //a * means anything until sentence end - if (term === '*') { - reg.astrix = true; - term = ''; - } - if (term !== '') { - //support \ encoding of #[]()*+?^ - term = term.replace(/\\([\\#\*\.\[\]\(\)\+\?\^])/g, ''); - reg.normal = term.toLowerCase(); - } - return reg; -}; - -//turn a match string into an array of objects -const parse_all = function(input) { - input = input || ''; - let regs = input.split(/ +/); - //bundle-up multiple-words inside parentheses - for(let i = 0; i < regs.length; i += 1) { - if (regs[i].indexOf('(') !== -1 && regs[i].indexOf(')') === -1) { - let nextWord = regs[i + 1]; - if (nextWord && nextWord.indexOf('(') === -1 && nextWord.indexOf(')') !== -1) { - regs[i + 1] = regs[i] + ' ' + regs[i + 1]; - regs[i] = ''; - } - } - } - regs = regs.filter((f) => f); - let captureOn = false; - regs = regs.map((reg) => { - let hasEnd = false; - //support [#Noun] capture-group syntax - if (reg.charAt(0) === '[') { - reg = noFirst(reg); - captureOn = true; - } - if (reg.charAt(reg.length - 1) === ']') { - reg = noLast(reg); - captureOn = false; - hasEnd = true; - } - reg = parse_term(reg); - if (captureOn === true || hasEnd === true) { - reg.capture = true; - } - return reg; - }); - return regs; -}; - -module.exports = parse_all; -// console.log(JSON.stringify(parse_all('the (canadian|united states|british) senate'), null, 2)); - -},{"./paths":173}],176:[function(_dereq_,module,exports){ -'use strict'; -// -const syntax = _dereq_('./lib/syntax'); -const startHere = _dereq_('./lib/startHere'); -const Text = _dereq_('../../text'); - -const addfns = Terms => { - const fns = { - //blacklist from a {word:true} object - notObj: function(r, obj) { - let matches = []; - let current = []; - r.terms.forEach(t => { - //TODO? support multi-word blacklists - //we should blacklist this term - if (obj.hasOwnProperty(t.normal)) { - if (current.length) { - matches.push(current); - } - current = []; - } else { - current.push(t); - } - }); - //add remainder - if (current.length) { - matches.push(current); - } - matches = matches.map(a => { - return new Terms(a, r.world, r.refText, r.refTerms); - }); - return new Text(matches, r.world, r.parent); - }, - - //blacklist from a match string - notString: function(r, want, verbose) { - let matches = []; - let regs = syntax(want); - let terms = []; - //try the match starting from each term - for (let i = 0; i < r.terms.length; i++) { - let bad = startHere(r, i, regs, verbose); - if (bad && bad.length > 0) { - //reset matches - if (terms.length > 0) { - matches.push(terms); - terms = []; - } - //skip these terms now - i += bad.length - 1; - continue; - } - terms.push(r.terms[i]); - } - //remaining ones - if (terms.length > 0) { - matches.push(terms); - } - matches = matches.map(a => { - return new Terms(a, r.world, r.refText, r.refTerms); - }); - // return matches - return new Text(matches, r.world, r.parent); - } - }; - //blacklist from a [word, word] array - fns.notArray = function(r, arr) { - let obj = arr.reduce((h, a) => { - h[a] = true; - return h; - }, {}); - return fns.notObj(r, obj); - }; - fns.notText = function(r, m) { - let arr = m.out('array'); //i guess this is fine.. - return fns.notArray(r, arr); - }; - - /**return everything but these matches*/ - Terms.prototype.not = function(want, verbose) { - //support [word, word] blacklist - if (typeof want === 'object') { - let type = Object.prototype.toString.call(want); - if (type === '[object Array]') { - return fns.notArray(this, want, verbose); - } - if (type === '[object Object]') { - if (want.isA === 'Text') { - return fns.notText(this, want, verbose); - } else { - return fns.notObj(this, want, verbose); - } - } - } - if (typeof want === 'string') { - return fns.notString(this, want, verbose); - } - return this; - }; - return Terms; -}; - -module.exports = addfns; - -},{"../../text":192,"./lib/startHere":174,"./lib/syntax":175}],177:[function(_dereq_,module,exports){ -'use strict'; -const mutate = _dereq_('../mutate'); - -const addMethod = (Terms) => { - - //hook it into Terms.proto - Terms.prototype.delete = function (reg) { - //don't touch parent if empty - if (!this.found) { - return this; - } - //remove all selected - if (!reg) { - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - return this; - } - //only remove a portion of this - let found = this.match(reg); - if (found.found) { - let r = mutate.deleteThese(this, found); - return r; - } - return this.parentTerms; - }; - - return Terms; -}; - -module.exports = addMethod; - -},{"../mutate":188}],178:[function(_dereq_,module,exports){ -'use strict'; -const mutate = _dereq_('../mutate'); - -//whitespace -const addSpaceAt = (ts, i) => { - if (!ts.terms.length || !ts.terms[i]) { - return ts; - } - ts.terms[i].whitespace.before = ' '; - return ts; -}; - -const insertMethods = (Terms) => { - - //accept any sorta thing - const ensureTerms = function(input, world) { - if (input.isA === 'Terms') { - return input; - } - if (input.isA === 'Term') { - return new Terms([input], world); - } - //handle a string - let ts = Terms.fromString(input, world); - ts.tagger(); - return ts; - }; - - const methods = { - - insertBefore: function (input, tag) { - let original_l = this.terms.length; - let ts = ensureTerms(input, this.world); - if (tag) { - ts.tag(tag); - } - let index = this.index(); - //pad a space on parent - addSpaceAt(this.parentTerms, index); - if (index > 0) { - addSpaceAt(ts, 0); //if in middle of sentence - } - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, ts); - //also copy them to current selection - if (this.terms.length === original_l) { - this.terms = ts.terms.concat(this.terms); - } - return this; - }, - - insertAfter: function (input, tag) { - let original_l = this.terms.length; - let ts = ensureTerms(input, this.world); - if (tag) { - ts.tag(tag); - } - let index = this.terms[this.terms.length - 1].index(); - //beginning whitespace to ts - addSpaceAt(ts, 0); - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index + 1, ts); - //also copy them to current selection - if (this.terms.length === original_l) { - this.terms = this.terms.concat(ts.terms); - } - return this; - }, - - insertAt: function (index, input, tag) { - if (index < 0) { - index = 0; - } - let original_l = this.terms.length; - let ts = ensureTerms(input, this.world); - //tag that thing too - if (tag) { - ts.tag(tag); - } - if (index > 0) { - addSpaceAt(ts, 0); //if in middle of sentence - } - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, ts); - //also copy them to current selection - if (this.terms.length === original_l) { - //splice the new terms into this (yikes!) - Array.prototype.splice.apply(this.terms, [index, 0].concat(ts.terms)); - } - //beginning whitespace to ts - if (index === 0) { - this.terms[0].whitespace.before = ''; - ts.terms[ts.terms.length - 1].whitespace.after = ' '; - } - return this; - } - - }; - - //hook them into result.proto - Object.keys(methods).forEach((k) => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = insertMethods; - -},{"../mutate":188}],179:[function(_dereq_,module,exports){ -'use strict'; -//these methods are simply term-methods called in a loop - -const addMethods = (Terms) => { - - const foreach = [ - // ['tag'], - // ['unTag'], - // ['canBe'], - ['toUpperCase', 'UpperCase'], - ['toLowerCase'], - ['toTitleCase', 'TitleCase'], - // ['toCamelCase', 'CamelCase'], - ]; - - foreach.forEach((arr) => { - let k = arr[0]; - let tag = arr[1]; - let myFn = function () { - let args = arguments; - this.terms.forEach((t) => { - t[k].apply(t, args); - }); - if (tag) { - this.tag(tag, k); - } - return this; - }; - Terms.prototype[k] = myFn; - }); - return Terms; -}; - -module.exports = addMethods; - -},{}],180:[function(_dereq_,module,exports){ -'use strict'; -const Term = _dereq_('../../../term'); -//merge two term objects.. carefully - -const makeText = (a, b) => { - let text = a.whitespace.before + a.text + a.whitespace.after; - text += b.whitespace.before + b.text + b.whitespace.after; - return text; -}; - -const combine = function(s, i) { - let a = s.terms[i]; - let b = s.terms[i + 1]; - if (!b) { - return; - } - let text = makeText(a, b); - s.terms[i] = new Term(text, a.context); - s.terms[i].normal = a.normal + ' ' + b.normal; - s.terms[i].lumped = true; - s.terms[i].parentTerms = s.terms[i + 1].parentTerms; - s.terms[i + 1] = null; - s.terms = s.terms.filter((t) => t !== null); - return; -}; - -module.exports = combine; - -},{"../../../term":143}],181:[function(_dereq_,module,exports){ -'use strict'; -const combine = _dereq_('./combine'); -const mutate = _dereq_('../../mutate'); - -//merge-together our current match into one term -const combineThem = function(ts, tags) { - let len = ts.terms.length; - for(let i = 0; i < len; i++) { - combine(ts, 0); - } - let lumped = ts.terms[0]; - lumped.tags = tags; - return lumped; -}; - -const lumpMethods = (Terms) => { - - Terms.prototype.lump = function () { - //collect the tags up - let index = this.index(); - let tags = {}; - this.terms.forEach((t) => { - Object.keys(t.tags).forEach((tag) => tags[tag] = true); - }); - //just lump the whole-thing together - if (this.parentTerms === this) { - let lumped = combineThem(this, tags); - this.terms = [lumped]; - return this; - } - //otherwise lump just part of it. delete/insert. - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - //merge-together our current match into one term - let lumped = combineThem(this, tags); - //put it back (in the same place) - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, lumped); - return this; - }; - - return Terms; -}; - -module.exports = lumpMethods; - -},{"../../mutate":188,"./combine":180}],182:[function(_dereq_,module,exports){ -'use strict'; -const tagger = _dereq_('../../tagger'); - -const miscMethods = Terms => { - const methods = { - tagger: function() { - tagger(this); - return this; - }, - firstTerm: function() { - return this.terms[0]; - }, - lastTerm: function() { - return this.terms[this.terms.length - 1]; - }, - all: function() { - return this.parent; - }, - data: function() { - return { - text: this.out('text'), - normal: this.out('normal') - }; - }, - term: function(n) { - return this.terms[n]; - }, - first: function() { - let t = this.terms[0]; - return new Terms([t], this.world, this.refText, this.refTerms); - }, - last: function() { - let t = this.terms[this.terms.length - 1]; - return new Terms([t], this.world, this.refText, this.refTerms); - }, - slice: function(start, end) { - let terms = this.terms.slice(start, end); - return new Terms(terms, this.world, this.refText, this.refTerms); - }, - index: function() { - let parent = this.parentTerms; - let first = this.terms[0]; - if (!parent || !first) { - return null; //maybe.. - } - for (let i = 0; i < parent.terms.length; i++) { - if (first === parent.terms[i]) { - return i; - } - } - return null; - }, - termIndex: function() { - let first = this.terms[0]; - let ref = this.refText || this; - if (!ref || !first) { - return null; //maybe.. - } - let n = 0; - for (let i = 0; i < ref.list.length; i++) { - let ts = ref.list[i]; - for (let o = 0; o < ts.terms.length; o++) { - if (ts.terms[o] === first) { - return n; - } - n += 1; - } - } - return n; - }, - //number of characters in this match - chars: function() { - return this.terms.reduce((i, t) => { - i += t.whitespace.before.length; - i += t.text.length; - i += t.whitespace.after.length; - return i; - }, 0); - }, - //just .length - wordCount: function() { - return this.terms.length; - }, - /** punctuation */ - setPunctuation: function(punct) { - let last = this.terms[this.terms.length - 1]; - last.setPunctuation(punct); - }, - getPunctuation: function() { - let lastTerm = this.last().terms[0]; - if (!lastTerm) { - return ''; - } - return lastTerm.getPunctuation() || ''; - }, - //this has term-order logic, so has to be here - toCamelCase: function() { - this.toTitleCase(); - this.terms.forEach((t, i) => { - if (i !== 0) { - t.whitespace.before = ''; - } - t.whitespace.after = ''; - }); - this.tag('#CamelCase', 'toCamelCase'); - return this; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = miscMethods; - -},{"../../tagger":95}],183:[function(_dereq_,module,exports){ -'use strict'; -const fns = _dereq_('../paths').fns; - -const methods = { - text: function(ts) { - return ts.terms.reduce((str, t) => { - str += t.out('text'); - return str; - }, ''); - }, - //like 'text', but no leading/trailing whitespace - match: function(ts) { - let str = ''; - let len = ts.terms.length; - for (let i = 0; i < len; i++) { - if (i > 0) { - str += ts.terms[i].whitespace.before; - } - str += ts.terms[i].text.replace(/[,.?!]$/, ''); //remove comma - if (i < len - 1) { - str += ts.terms[i].whitespace.after; - } - } - return str; - }, - - normal: function(ts) { - let terms = ts.terms.filter(t => { - return t.text; - }); - terms = terms.map(t => { - return t.normal; //+ punct; - }); - return terms.join(' '); - }, - - grid: function(ts) { - let str = ' '; - str += ts.terms.reduce((s, t) => { - s += fns.leftPad(t.text, 11); - return s; - }, ''); - return str + '\n\n'; - }, - - color: function(ts) { - return ts.terms.reduce((s, t) => { - s += fns.printTerm(t); - return s; - }, ''); - }, - csv: function(ts) { - return ts.terms.map(t => t.normal.replace(/,/g, '')).join(','); - }, - - newlines: function(ts) { - return ts.terms - .reduce((str, t) => { - str += t.out('text').replace(/\n/g, ' '); - return str; - }, '') - .replace(/^\s/, ''); - }, - /** no punctuation, fancy business **/ - root: function(ts) { - return ts.terms.map(t => t.silent_term || t.root).join(' ').toLowerCase(); - }, - - html: function(ts) { - return ts.terms.map(t => t.render.html()).join(' '); - }, - debug: function(ts) { - ts.terms.forEach(t => { - t.out('debug'); - }); - }, - custom: function(ts, obj) { - return ts.terms.map((t) => { - return Object.keys(obj).reduce((h, k) => { - if (obj[k] && t[k]) { - if (typeof t[k] === 'function') { - h[k] = t[k](); - } else { - h[k] = t[k]; - } - } - return h; - }, {}); - }); - } -}; -methods.plaintext = methods.text; -methods.normalize = methods.normal; -methods.normalized = methods.normal; -methods.colors = methods.color; -methods.tags = methods.terms; - -const renderMethods = Terms => { - Terms.prototype.out = function(fn) { - if (typeof fn === 'string') { - if (methods[fn]) { - return methods[fn](this); - } - } else if (fns.isObject(fn) === true) { //support .out({}) - return methods.custom(this, fn); - } - return methods.text(this); - }; - //check method - Terms.prototype.debug = function() { - return methods.debug(this); - }; - return Terms; -}; - -module.exports = renderMethods; - -},{"../paths":189}],184:[function(_dereq_,module,exports){ -'use strict'; -const mutate = _dereq_('../mutate'); - -const replaceMethods = Terms => { - const methods = { - /**swap this for that */ - replace: function(str1, str2, keepTags) { - //in this form, we 'replaceWith' - if (str2 === undefined) { - return this.replaceWith(str1, keepTags); - } - this.match(str1).replaceWith(str2, keepTags); - return this; - }, - - /**swap this for that */ - replaceWith: function(str, keepTags) { - let newTs = Terms.fromString(str, this.world); - newTs.tagger(); - //if instructed, apply old tags to new terms - if (keepTags) { - this.terms.forEach((t, i) => { - let tags = Object.keys(t.tags); - if (newTs.terms[i] !== undefined) { - tags.forEach(tg => newTs.terms[i].tag(tg, 'from-memory')); - } - }); - } - //keep its ending punctation.. - let endPunct = this.getPunctuation(); - //grab the insertion place.. - let index = this.index(); - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, newTs); - this.terms = newTs.terms; - //add-in the punctuation at the end.. - if (this.terms.length > 0) { - this.terms[this.terms.length - 1].whitespace.after += endPunct; - } - return this; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = replaceMethods; - -},{"../mutate":188}],185:[function(_dereq_,module,exports){ -'use strict'; - -//break apart a termlist into (before, match after) -const breakUpHere = (terms, ts) => { - let firstTerm = ts.terms[0]; - let len = ts.terms.length; - for (let i = 0; i < terms.length; i++) { - if (terms[i] === firstTerm) { - return { - before: terms.slice(0, i), - match: terms.slice(i, i + len), - after: terms.slice(i + len, terms.length) - }; - } - } - return { - after: terms - }; -}; - -const splitMethods = Terms => { - const methods = { - /** at the end of the match, split the terms **/ - splitAfter: function(reg, verbose) { - let ms = this.match(reg, verbose); //Array[ts] - let termArr = this.terms; - let all = []; - ms.list.forEach(lookFor => { - let section = breakUpHere(termArr, lookFor); - if (section.before && section.match) { - all.push(section.before.concat(section.match)); - } - termArr = section.after; - }); - //add the remaining - if (termArr.length) { - all.push(termArr); - } - //make them termlists - all = all.map(ts => { - let parent = this.refText; //|| this; - return new Terms(ts, this.world, parent, this.refTerms); - }); - return all; - }, - - /** return only before & after the match**/ - splitOn: function(reg, verbose) { - let ms = this.match(reg, verbose); //Array[ts] - let termArr = this.terms; - let all = []; - ms.list.forEach(lookFor => { - let section = breakUpHere(termArr, lookFor); - if (section.before) { - all.push(section.before); - } - if (section.match) { - all.push(section.match); - } - termArr = section.after; - }); - //add the remaining - if (termArr.length) { - all.push(termArr); - } - //make them termlists - all = all.filter(a => a && a.length); - all = all.map(ts => new Terms(ts, this.world, ts.refText, this.refTerms)); - return all; - }, - - /** at the start of the match, split the terms**/ - splitBefore: function(reg, verbose) { - let ms = this.match(reg, verbose); //Array[ts] - let termArr = this.terms; - let all = []; - ms.list.forEach(lookFor => { - let section = breakUpHere(termArr, lookFor); - if (section.before) { - all.push(section.before); - } - if (section.match) { - all.push(section.match); - } - termArr = section.after; - }); - //add the remaining - if (termArr.length) { - all.push(termArr); - } - //cleanup-step: merge all (middle) matches with the next one - for (let i = 0; i < all.length; i++) { - for (let o = 0; o < ms.length; o++) { - if (ms.list[o].terms[0] === all[i][0]) { - if (all[i + 1]) { - all[i] = all[i].concat(all[i + 1]); - all[i + 1] = []; - } - } - } - } - //make them termlists - all = all.filter(a => a && a.length); - all = all.map(ts => new Terms(ts, ts.world, ts.refText, this.refTerms)); - return all; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = splitMethods; -exports = splitMethods; - -},{}],186:[function(_dereq_,module,exports){ -'use strict'; -const addMethod = Terms => { - const methods = { - tag: function(tag, reason) { - let tags = []; - if (typeof tag === 'string') { - tags = tag.split(' '); - } - //fancy version: - if (tags.length > 1) { - //do indepenent tags for each term: - this.terms.forEach((t, i) => { - t.tag(tags[i], reason); - }); - return this; - } - //non-fancy version: - this.terms.forEach(t => { - t.tag(tag, reason); - }); - return this; - }, - - unTag: function(tag, reason) { - let tags = []; - if (typeof tag === 'string') { - tags = tag.split(' '); - } - //fancy version: - if (tags.length > 1) { - //do indepenent tags for each term: - this.terms.forEach((t, i) => { - t.unTag(tags[i], reason); - }); - return this; - } - //non-fancy version: - this.terms.forEach(t => { - t.unTag(tag, reason); - }); - return this; - }, - - //which terms are consistent with this tag - canBe: function(tag) { - let terms = this.terms.filter(t => t.canBe(tag)); - return new Terms(terms, this.world, this.refText, this.refTerms); - } - }; - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = addMethod; - -},{}],187:[function(_dereq_,module,exports){ -'use strict'; - -const transforms = Terms => { - const methods = { - clone: function() { - // this.world = this.world.clone(); - let terms = this.terms.map(t => { - return t.clone(); - }); - return new Terms(terms, this.world, this.refText, null); //, this.refTerms - }, - hyphenate: function() { - this.terms.forEach((t, i) => { - if (i !== this.terms.length - 1) { - t.whitespace.after = '-'; - } - if (i !== 0) { - t.whitespace.before = ''; - } - }); - return this; - }, - dehyphenate: function() { - this.terms.forEach(t => { - if (t.whitespace.after === '-') { - t.whitespace.after = ' '; - } - }); - return this; - }, - trim: function() { - if (this.length <= 0) { - return this; - } - this.terms[0].whitespace.before = ''; - this.terms[this.terms.length - 1].whitespace.after = ''; - return this; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = transforms; - -},{}],188:[function(_dereq_,module,exports){ -'use strict'; -// -const getTerms = (needle) => { - let arr = []; - if (needle.isA === 'Terms') { - arr = needle.terms; - } else if (needle.isA === 'Text') { - arr = needle.flatten().list[0].terms; - } else if (needle.isA === 'Term') { - arr = [needle]; - } - return arr; -}; - -//remove them -exports.deleteThese = (source, needle) => { - let arr = getTerms(needle); - source.terms = source.terms.filter((t) => { - for (let i = 0; i < arr.length; i++) { - if (t === arr[i]) { - return false; - } - } - return true; - }); - return source; -}; - -//add them -exports.insertAt = (terms, i, needle) => { - needle.dirty = true; - let arr = getTerms(needle); - //handle whitespace - if (i > 0 && arr[0] && !arr[0].whitespace.before) { - arr[0].whitespace.before = ' '; - } - //gnarly splice - //-( basically - terms.splice(i+1, 0, arr) ) - Array.prototype.splice.apply(terms, [i, 0].concat(arr)); - return terms; -}; - -},{}],189:[function(_dereq_,module,exports){ -module.exports = { - fns: _dereq_('../fns'), - Term: _dereq_('../term') -}; - -},{"../fns":3,"../term":143}],190:[function(_dereq_,module,exports){ -'use strict'; -const Text = _dereq_('./index'); -const tokenize = _dereq_('./tokenize'); -const paths = _dereq_('./paths'); -const Terms = paths.Terms; -const fns = paths.fns; - -const fromString = (str, world) => { - let sentences = []; - //allow pre-tokenized input - if (fns.isArray(str)) { - sentences = str; - } else { - str = fns.ensureString(str); - sentences = tokenize(str); - } - let list = sentences.map(s => Terms.fromString(s, world)); - - let doc = new Text(list, world); - //give each ts a ref to the result - doc.list.forEach(ts => { - ts.refText = doc; - }); - return doc; -}; -module.exports = fromString; - -},{"./index":192,"./paths":205,"./tokenize":207}],191:[function(_dereq_,module,exports){ -module.exports = { - /** did it find anything? */ - found: function() { - return this.list.length > 0; - }, - /** just a handy wrap*/ - parent: function() { - return this.original || this; - }, - /** how many Texts are there?*/ - length: function() { - return this.list.length; - }, - /** nicer than constructor.call.name or whatever*/ - isA: function() { - return 'Text'; - }, - /** the whitespace before and after this match*/ - whitespace: function() { - return { - before: str => { - this.list.forEach(ts => { - ts.whitespace.before(str); - }); - return this; - }, - after: str => { - this.list.forEach(ts => { - ts.whitespace.after(str); - }); - return this; - } - }; - } -}; - -},{}],192:[function(_dereq_,module,exports){ -'use strict'; -//a Text is an array of termLists -const getters = _dereq_('./getters'); - -function Text(arr, world, original) { - this.list = arr || []; - if (typeof world === 'function') { - world = world(); - } - this.world = () => { - return world; - }; - this.original = original; - //apply getters - let keys = Object.keys(getters); - for (let i = 0; i < keys.length; i++) { - Object.defineProperty(this, keys[i], { - get: getters[keys[i]] - }); - } -} -module.exports = Text; - -Text.addMethods = function(cl, obj) { - let fns = Object.keys(obj); - for (let i = 0; i < fns.length; i++) { - cl.prototype[fns[i]] = obj[fns[i]]; - } -}; - -//make a sub-class of this class easily -Text.makeSubset = function(methods, find) { - let Subset = function(arr, world, original) { - Text.call(this, arr, world, original); - }; - //inheritance - Subset.prototype = Object.create(Text.prototype); - Text.addMethods(Subset, methods); - Subset.find = find; - return Subset; -}; - -//apply instance methods -_dereq_('./methods/misc')(Text); -_dereq_('./methods/loops')(Text); -_dereq_('./methods/match')(Text); -_dereq_('./methods/out')(Text); -_dereq_('./methods/sort')(Text); -_dereq_('./methods/split')(Text); -_dereq_('./methods/normalize')(Text); -_dereq_('./subsets')(Text); - -//apply subset methods -const subset = { - acronyms: _dereq_('../subset/acronyms'), - adjectives: _dereq_('../subset/adjectives'), - adverbs: _dereq_('../subset/adverbs'), - contractions: _dereq_('../subset/contractions'), - dates: _dereq_('../subset/dates'), - nouns: _dereq_('../subset/nouns'), - people: _dereq_('../subset/people'), - sentences: _dereq_('../subset/sentences'), - terms: _dereq_('../subset/terms'), - possessives: _dereq_('../subset/possessives'), - values: _dereq_('../subset/values'), - verbs: _dereq_('../subset/verbs'), - ngrams: _dereq_('../subset/ngrams'), - startGrams: _dereq_('../subset/ngrams/startGrams'), - endGrams: _dereq_('../subset/ngrams/endGrams') -}; -Object.keys(subset).forEach(k => { - Text.prototype[k] = function(num, arg) { - let sub = subset[k]; - let m = sub.find(this, num, arg); - return new subset[k](m.list, this.world, this.parent); - }; -}); -//aliases -Text.prototype.words = Text.prototype.terms; - -},{"../subset/acronyms":9,"../subset/adjectives":10,"../subset/adverbs":17,"../subset/contractions":23,"../subset/dates":25,"../subset/ngrams":35,"../subset/ngrams/endGrams":32,"../subset/ngrams/startGrams":36,"../subset/nouns":38,"../subset/people":49,"../subset/possessives":51,"../subset/sentences":52,"../subset/terms":58,"../subset/values":65,"../subset/verbs":75,"./getters":191,"./methods/loops":193,"./methods/match":194,"./methods/misc":195,"./methods/normalize":196,"./methods/out":197,"./methods/sort":202,"./methods/split":204,"./subsets":206}],193:[function(_dereq_,module,exports){ -'use strict'; -//this methods are simply loops around each termList object. -const methods = [ - 'toTitleCase', - 'toUpperCase', - 'toLowerCase', - 'toCamelCase', - - 'hyphenate', - 'dehyphenate', - 'trim', - - 'insertBefore', - 'insertAfter', - 'insertAt', - - 'replace', - 'replaceWith', - - 'delete', - 'lump', - - 'tagger', - - // 'tag', - 'unTag', -]; - -const addMethods = (Text) => { - methods.forEach((k) => { - Text.prototype[k] = function () { - for(let i = 0; i < this.list.length; i++) { - this.list[i][k].apply(this.list[i], arguments); - } - return this; - }; - }); - - //add an extra optimisation for tag method - Text.prototype.tag = function() { - //fail-fast optimisation - if (this.list.length === 0) { - return this; - } - for(let i = 0; i < this.list.length; i++) { - this.list[i].tag.apply(this.list[i], arguments); - } - return this; - }; -}; - -module.exports = addMethods; - -},{}],194:[function(_dereq_,module,exports){ -'use strict'; -const syntaxParse = _dereq_('../../../terms/match/lib/syntax'); -const Terms = _dereq_('../../../terms'); - -const splitMethods = Text => { - //support "#Noun word" regex-matches - const matchReg = function(r, reg, verbose) { - //parse the 'regex' into some json - let list = []; - reg = syntaxParse(reg); - r.list.forEach(ts => { - //an array of arrays - let matches = ts.match(reg, verbose); - matches.list.forEach(ms => { - list.push(ms); - }); - }); - let parent = r.parent || r; - return new Text(list, r.world(), parent); - }; - - //support {word:true} whitelist - const matchObj = function(r, obj) { - let matches = []; - r.list.forEach(ts => { - ts.terms.forEach(t => { - if (obj.hasOwnProperty(t.normal) === true) { - matches.push(t); - } - }); - }); - matches = matches.map(t => { - return new Terms([t], r.world(), r, t.parentTerms); - }); - return new Text(matches, r.world(), r.parent); - }; - - //support [word, word] whitelist - const matchArr = function(r, arr) { - //its faster this way - let obj = arr.reduce((h, a) => { - h[a] = true; - return h; - }, {}); - return matchObj(r, obj); - }; - - //take a Text object as a match - const matchTextObj = function(r, m) { - let arr = m.out('array'); //i guess this is fine.. - return matchArr(r, arr); - }; - - const methods = { - /** do a regex-like search through terms and return a subset */ - match: function(reg, verbose) { - //fail-fast - if (this.list.length === 0 || reg === undefined || reg === null) { - let parent = this.parent || this; - return new Text([], this.world(), parent); - } - //match "#Noun word" regex - if (typeof reg === 'string' || typeof reg === 'number') { - return matchReg(this, reg, verbose); - } - //match [word, word] whitelist - let type = Object.prototype.toString.call(reg); - if (type === '[object Array]') { - return matchArr(this, reg); - } - //match {word:true} whitelist - if (type === '[object Object]') { - if (reg.isA === 'Text') { - return matchTextObj(this, reg); - } else { - return matchObj(this, reg); - } - } - return this; - }, - - not: function(reg, verbose) { - let list = []; - this.list.forEach(ts => { - let found = ts.not(reg, verbose); - list = list.concat(found.list); - }); - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - if: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === true) { - list.push(this.list[i]); - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - ifNo: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === false) { - list.push(this.list[i]); - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - has: function(reg) { - for (let i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === true) { - return true; - } - } - return false; - }, - - /**find a match, and return everything infront of it*/ - before: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - let m = this.list[i].matchOne(reg); - if (m) { - let index = m[0].index(); - let found = this.list[i].slice(0, index); - if (found.length > 0) { - list.push(found); - } - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - /**find a match, and return everything after of it*/ - after: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - let m = this.list[i].matchOne(reg); - if (m) { - let lastTerm = m[m.length - 1]; - let index = lastTerm.index(); - let found = this.list[i].slice(index + 1, this.list[i].length); - if (found.length > 0) { - list.push(found); - } - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - } - }; - //alias 'and' - methods.and = methods.match; - methods.notIf = methods.ifNo; - methods.only = methods.if; - methods.onlyIf = methods.if; - - //hook them into result.proto - Text.addMethods(Text, methods); - return Text; -}; - -module.exports = splitMethods; - -},{"../../../terms":165,"../../../terms/match/lib/syntax":175}],195:[function(_dereq_,module,exports){ -'use strict'; -const Terms = _dereq_('../../terms'); - -const miscMethods = Text => { - const methods = { - all: function() { - return this.parent; - }, - index: function() { - return this.list.map(ts => ts.index()); - }, - wordCount: function() { - return this.terms().length; - }, - data: function() { - return this.list.map(ts => ts.data()); - }, - /* javascript array loop-wrappers */ - map: function(fn) { - return this.list.map((ts, i) => { - let text = new Text([ts], this.world); - return fn(text, i); - }); - }, - forEach: function(fn) { - this.list.forEach((ts, i) => { - let text = new Text([ts], this.world); - fn(text, i); - }); - return this; - }, - filter: function(fn) { - let list = this.list.filter((ts, i) => { - let text = new Text([ts], this.world); - return fn(text, i); - }); - return new Text(list, this.world); - }, - reduce: function(fn, h) { - return this.list.reduce((_h, ts) => { - let text = new Text([ts], this.world); - return fn(_h, text); - }, h); - }, - find: function(fn) { - for (let i = 0; i < this.list.length; i++) { - let ts = this.list[i]; - let text = new Text([ts], this.world); - if (fn(text)) { - return text; - } - } - return undefined; - }, - /**copy data properly so later transformations will have no effect*/ - clone: function() { - let list = this.list.map(ts => { - return ts.clone(); - }); - return new Text(list, this.world); //this.lexicon, this.parent - }, - - /** get the nth term of each result*/ - term: function(n) { - let list = this.list.map(ts => { - let arr = []; - let el = ts.terms[n]; - if (el) { - arr = [el]; - } - return new Terms(arr, this.world, this.refText, this.refTerms); - }); - return new Text(list, this.world, this.parent); - }, - firstTerm: function() { - return this.match('^.'); - }, - lastTerm: function() { - return this.match('.$'); - }, - - /** grab a subset of the results*/ - slice: function(start, end) { - this.list = this.list.slice(start, end); - return this; - }, - - /** use only the nth result*/ - get: function(n) { - //return an empty result - if ((!n && n !== 0) || !this.list[n]) { - return new Text([], this.world, this.parent); - } - let ts = this.list[n]; - return new Text([ts], this.world, this.parent); - }, - /**use only the first result */ - first: function(n) { - if (!n && n !== 0) { - return this.get(0); - } - return new Text(this.list.slice(0, n), this.world, this.parent); - }, - /**use only the last result */ - last: function(n) { - if (!n && n !== 0) { - return this.get(this.list.length - 1); - } - let end = this.list.length; - let start = end - n; - return new Text(this.list.slice(start, end), this.world, this.parent); - }, - - concat: function() { - //any number of params - for (let i = 0; i < arguments.length; i++) { - let p = arguments[i]; - if (typeof p === 'object') { - //Text() - if (p.isA === 'Text' && p.list) { - this.list = this.list.concat(p.list); - } - //Terms() - if (p.isA === 'Terms') { - this.list.push(p); - } - } - } - return this; - }, - - /** make it into one sentence/termlist */ - flatten: function() { - let terms = []; - this.list.forEach(ts => { - terms = terms.concat(ts.terms); - }); - //dont create an empty ts - if (!terms.length) { - return new Text(null, this.world, this.parent); - } - let ts = new Terms(terms, this.world, this, null); - return new Text([ts], this.world, this.parent); - }, - - /** see if these terms can become this tag*/ - canBe: function(tag) { - this.list.forEach(ts => { - ts.terms = ts.terms.filter(t => { - return t.canBe(tag); - }); - }); - return this; - }, - - /** sample part of the array */ - random: function(n) { - n = n || 1; - let r = Math.floor(Math.random() * this.list.length); - let arr = this.list.slice(r, r + n); - //if we're off the end, add some from the start - if (arr.length < n) { - let diff = n - arr.length; - if (diff > r) { - diff = r; //prevent it from going full-around - } - arr = arr.concat(this.list.slice(0, diff)); - } - return new Text(arr, this.world, this.parent); - }, - setPunctuation: function(punct) { - this.list.forEach((ts) => ts.setPunctuation(punct)); - return this; - }, - getPunctuation: function(num) { - //support num param - if (num || num === 0) { - if (!this.list[num]) { - return ''; - } - return this.list[num].getPunctuation(); - } - return this.list.map((ts) => ts.getPunctuation()); - }, - //jquery-like api aliases - offset: function() { - return this.out('offset'); - }, - text: function() { - return this.out('text'); - } - }; - //aliases - methods.eq = methods.get; - methods.join = methods.flatten; - Text.addMethods(Text, methods); -}; - -module.exports = miscMethods; - -},{"../../terms":165}],196:[function(_dereq_,module,exports){ -'use strict'; -const unicode = _dereq_('../../term/methods/normalize/unicode'); -// -const defaults = { - whitespace: true, - case: true, - numbers: true, - punctuation: true, - unicode: true, - contractions: true, - acronyms: true, - - parentheses: false, - possessives: false, - plurals: false, - verbs: false, - honorifics: false, -}; - -const methods = { - /** make only one space between each word */ - whitespace: r => { - r.terms().list.forEach((ts, i) => { - let t = ts.terms[0]; - if (i > 0 && !t.silent_term) { - t.whitespace.before = ' '; - } else if (i === 0) { - t.whitespace.before = ''; - } - t.whitespace.after = ''; - //add normalized quotation symbols - if (t.tags.StartQuotation === true) { - t.whitespace.before += '"'; - } - if (t.tags.EndQuotation === true) { - t.whitespace.after = '"' + t.whitespace.after; - } - }); - return r; - }, - - /** make first-word titlecase, and people, places titlecase */ - case: r => { - r.list.forEach(ts => { - ts.terms.forEach((t, i) => { - if (i === 0 || t.tags.Person || t.tags.Place || t.tags.Organization) { - // ts.toTitleCase() //fixme: too weird here. - } else { - ts.toLowerCase(); - } - }); - }); - return r; - }, - - /** turn 'five' to 5, and 'fifth' to 5th*/ - numbers: r => { - r.values().toNumber(); - return r; - }, - - /** remove commas, semicolons - but keep sentence-ending punctuation*/ - punctuation: r => { - r.list.forEach(ts => { - if (!ts.terms.length) { - return; - } - - //first-term punctuation - ts.terms[0]._text = ts.terms[0]._text.replace(/^¿/, ''); - //middle-terms - for (let i = 0; i < ts.terms.length - 1; i++) { - let t = ts.terms[i]; - //remove non-sentence-ending stuff - t._text = t._text.replace(/[:;,]$/, ''); - } - //replace !!! with ! - let last = ts.terms[ts.terms.length - 1]; - last._text = last._text.replace(/\.+$/, '.'); - last._text = last._text.replace(/!+$/, '!'); - last._text = last._text.replace(/\?+!?$/, '?'); //support '?!' - }); - return r; - }, - - // turn Björk into Bjork - unicode: r => { - r.list.forEach((ts) => { - ts.terms.forEach((t) => { - t.text = unicode(t.text); - }); - }); - return r; - }, - - //expand all contractions - contractions: r => { - r.contractions().expand(); - return r; - }, - //remove periods from acronyms, like F.B.I. - acronyms: r => { - r.acronyms().stripPeriods(); - return r; - }, - //turn david's → david - possessives: r => { - r.possessives().strip(); - return r; - }, - //strip out parts in (brackets) - parentheses: r => { - r.parentheses().delete(); - return r; - }, - //turn sandwhiches → sandwhich - plurals: r => { //todo:this has a non-cooperative bug - r.nouns().toSingular(); - return r; - }, - //turn ate → eat - verbs: r => { - r.verbs().toInfinitive(); - return r; - }, - - //turn 'Sergeant Pepper to 'Pepper' - honorifics: r => { - r = r.delete('#Honorific'); - return r; - } -}; - -const addMethods = Text => { - Text.prototype.normalize = function (options) { - let doc = this; - //set defaults - options = options || {}; - let obj = Object.assign({}, defaults); - let keys = Object.keys(options); - keys.forEach((k) => { - obj[k] = options[k]; - }); - //do each type of normalization - Object.keys(obj).forEach(fn => { - if (obj[fn] && methods[fn] !== undefined) { - doc = methods[fn](doc); - } - }); - return doc; - }; -}; -module.exports = addMethods; - -},{"../../term/methods/normalize/unicode":151}],197:[function(_dereq_,module,exports){ -'use strict'; -const topk = _dereq_('./topk'); -const offset = _dereq_('./offset'); -const termIndex = _dereq_('./indexes'); -const fns = _dereq_('../paths').fns; - -const methods = { - text: r => { - return r.list.reduce((str, ts) => { - str += ts.out('text'); - return str; - }, ''); - }, - match: r => { - return r.list.reduce((str, ts) => { - str += ts.out('match'); - return str; - }, ''); - }, - normal: r => { - return r.list - .map(ts => { - let str = ts.out('normal'); - let last = ts.last(); - if (last) { - let punct = ts.getPunctuation(); - if (punct === '.' || punct === '!' || punct === '?') { - str += punct; - } - } - return str; - }) - .join(' '); - }, - root: r => { - return r.list - .map(ts => { - return ts.out('root'); - }) - .join(' '); - }, - /** output where in the original output string they are*/ - offsets: r => { - return offset(r); - }, - /** output the tokenized location of this match*/ - index: r => { - return termIndex(r); - }, - grid: r => { - return r.list.reduce((str, ts) => { - str += ts.out('grid'); - return str; - }, ''); - }, - color: r => { - return r.list.reduce((str, ts) => { - str += ts.out('color'); - return str; - }, ''); - }, - array: r => { - return r.list.map(ts => { - return ts.out('normal'); - }); - }, - csv: r => { - return r.list - .map(ts => { - return ts.out('csv'); - }) - .join('\n'); - }, - newlines: r => { - return r.list - .map(ts => { - return ts.out('newlines'); - }) - .join('\n'); - }, - json: r => { - return r.list.reduce((arr, ts) => { - let terms = ts.terms.map(t => { - return { - text: t.text, - normal: t.normal, - tags: t.tag - }; - }); - arr.push(terms); - return arr; - }, []); - }, - html: r => { - let html = r.list.reduce((str, ts) => { - let sentence = ts.terms.reduce((sen, t) => { - sen += '\n ' + t.out('html'); - return sen; - }, ''); - return (str += '\n ' + sentence + '\n '); - }, ''); - return ' ' + html + '\n'; - }, - terms: r => { - let arr = []; - r.list.forEach(ts => { - ts.terms.forEach(t => { - arr.push({ - text: t.text, - normal: t.normal, - tags: Object.keys(t.tags) - }); - }); - }); - return arr; - }, - debug: r => { - console.log('===='); - r.list.forEach(ts => { - console.log(' --'); - ts.debug(); - }); - return r; - }, - topk: r => { - return topk(r); - }, - custom: (r, obj) => { - return r.list.map((ts) => ts.out(obj)); - } -}; -methods.plaintext = methods.text; -methods.normalized = methods.normal; -methods.colors = methods.color; -methods.tags = methods.terms; -methods.offset = methods.offsets; -methods.idexes = methods.index; -methods.frequency = methods.topk; -methods.freq = methods.topk; -methods.arr = methods.array; - - - -const addMethods = Text => { - Text.prototype.out = function(fn) { - if (typeof fn === 'string') { - if (methods[fn]) { - return methods[fn](this); - } - } else if (fns.isObject(fn) === true) { //support .out({}) - return methods.custom(this, fn); - } - return methods.text(this); - }; - Text.prototype.debug = function() { - return methods.debug(this); - }; - return Text; -}; - -module.exports = addMethods; - -},{"../paths":201,"./indexes":198,"./offset":199,"./topk":200}],198:[function(_dereq_,module,exports){ -'use strict'; -//find where in the original text this match is found, by term-counts -const termIndex = (r) => { - let result = []; - //find the ones we want - let want = {}; - r.terms().list.forEach((ts) => { - want[ts.terms[0].uid] = true; - }); - - //find their counts - let sum = 0; - let parent = r.all(); - parent.list.forEach((ts, s) => { - ts.terms.forEach((t, i) => { - if (want[t.uid] !== undefined) { - result.push({ - text: t.text, - normal: t.normal, - term: sum, - sentence: s, - sentenceTerm: i - }); - } - sum += 1; - }); - }); - - return result; -}; -module.exports = termIndex; - -},{}],199:[function(_dereq_,module,exports){ -'use strict'; -/** say where in the original output string they are found*/ - -const findOffset = (parent, term) => { - let sum = 0; - for(let i = 0; i < parent.list.length; i++) { - for(let o = 0; o < parent.list[i].terms.length; o++) { - let t = parent.list[i].terms[o]; - if (t.uid === term.uid) { - return sum; - } else { - sum += t.whitespace.before.length + t._text.length + t.whitespace.after.length; - } - } - } - return null; -}; - -//like 'text' for the middle, and 'normal' for the start+ends -//used for highlighting the actual words, without whitespace+punctuation -const trimEnds = function(ts) { - let terms = ts.terms; - if (terms.length <= 2) { - return ts.out('normal'); - } - //the start - let str = terms[0].normal; - //the middle - for(let i = 1; i < terms.length - 1; i++) { - let t = terms[i]; - str += t.whitespace.before + t.text + t.whitespace.after; - } - //the end - str += ' ' + terms[ts.terms.length - 1].normal; - return str; -}; - -//map over all-dem-results -const allOffset = (r) => { - let parent = r.all(); - return r.list.map((ts) => { - let words = []; - for(let i = 0; i < ts.terms.length; i++) { - words.push(ts.terms[i].normal); - } - let nrml = trimEnds(ts); - let txt = ts.out('text'); - let startAt = findOffset(parent, ts.terms[0]); - let beforeWord = ts.terms[0].whitespace.before; - let wordStart = startAt + beforeWord.length; - return { - text: txt, - normal: ts.out('normal'), - //where we begin - offset: startAt, - length: txt.length, - wordStart: wordStart, - wordEnd: wordStart + nrml.length, - // wordLength: words.join(' ').length - }; - }); -}; -module.exports = allOffset; - -},{}],200:[function(_dereq_,module,exports){ -'use strict'; -// -const topk = function (r, n) { - //count occurance - let count = {}; - r.list.forEach((ts) => { - let str = ts.out('root'); - count[str] = count[str] || 0; - count[str] += 1; - }); - //turn into an array - let all = []; - Object.keys(count).forEach((k) => { - all.push({ - normal: k, - count: count[k], - }); - }); - //add percentage - all.forEach((o) => { - o.percent = parseFloat(((o.count / r.list.length) * 100).toFixed(2)); - }); - //sort by freq - all = all.sort((a, b) => { - if (a.count > b.count) { - return -1; - } - return 1; - }); - if (n) { - all = all.splice(0, n); - } - return all; -}; - -module.exports = topk; - -},{}],201:[function(_dereq_,module,exports){ -module.exports = _dereq_('../paths'); - -},{"../paths":205}],202:[function(_dereq_,module,exports){ -'use strict'; -const sorter = _dereq_('./methods'); - -const addMethods = (Text) => { - - const fns = { - - /**reorder result.list alphabetically */ - sort: function (method) { - //default sort - method = method || 'alphabetical'; - method = method.toLowerCase(); - if (!method || method === 'alpha' || method === 'alphabetical') { - return sorter.alpha(this, Text); - } - if (method === 'chron' || method === 'chronological') { - return sorter.chron(this, Text); - } - if (method === 'length') { - return sorter.lengthFn(this, Text); - } - if (method === 'freq' || method === 'frequency') { - return sorter.freq(this, Text); - } - if (method === 'wordcount') { - return sorter.wordCount(this, Text); - } - return this; - }, - - /**reverse the order of result.list */ - reverse: function () { - this.list = this.list.reverse(); - return this; - }, - - unique: function () { - let obj = {}; - this.list = this.list.filter((ts) => { - let str = ts.out('root'); - if (obj.hasOwnProperty(str)) { - return false; - } - obj[str] = true; - return true; - }); - return this; - } - }; - //hook them into result.proto - Text.addMethods(Text, fns); - return Text; -}; - -module.exports = addMethods; - -},{"./methods":203}],203:[function(_dereq_,module,exports){ -'use strict'; - -//perform sort on pre-computed values -const sortEm = function(arr) { - arr = arr.sort((a, b) => { - if (a.index > b.index) { - return 1; - } - if (a.index === b.index) { - return 0; - } - return -1; - }); - //return ts objects - return arr.map((o) => o.ts); -}; - -//alphabetical sorting of a termlist array -exports.alpha = function(r) { - r.list.sort((a, b) => { - //#1 performance speedup - if (a === b) { - return 0; - } - //#2 performance speedup - if (a.terms[0] && b.terms[0]) { - if (a.terms[0].root > b.terms[0].root) { - return 1; - } - if (a.terms[0].root < b.terms[0].root) { - return -1; - } - } - //regular compare - if (a.out('root') > b.out('root')) { - return 1; - } - return -1; - }); - return r; -}; - -//the order they were recieved (chronological~) -exports.chron = function(r) { - //pre-compute indexes - let tmp = r.list.map((ts) => { - return { - ts: ts, - index: ts.termIndex() - }; - }); - r.list = sortEm(tmp); - return r; -}; - -//shortest matches first -exports.lengthFn = function(r) { - //pre-compute indexes - let tmp = r.list.map((ts) => { - return { - ts: ts, - index: ts.chars() - }; - }); - r.list = sortEm(tmp).reverse(); - return r; -}; - -//count the number of terms in each match -exports.wordCount = function(r) { - //pre-compute indexes - let tmp = r.list.map((ts) => { - return { - ts: ts, - index: ts.length - }; - }); - r.list = sortEm(tmp); - return r; -}; - -//sort by frequency (like topk) -exports.freq = function(r) { - //get counts - let count = {}; - r.list.forEach((ts) => { - let str = ts.out('root'); - count[str] = count[str] || 0; - count[str] += 1; - }); - //pre-compute indexes - let tmp = r.list.map((ts) => { - let num = count[ts.out('root')] || 0; - return { - ts: ts, - index: num * -1 //quick-reverse it - }; - }); - r.list = sortEm(tmp); - return r; -}; - -},{}],204:[function(_dereq_,module,exports){ -'use strict'; - -const splitMethods = (Text) => { - - const methods = { - /** turn result into two seperate results */ - splitAfter: function(reg, verbose) { - let list = []; - this.list.forEach((ts) => { - ts.splitAfter(reg, verbose).forEach((mts) => { - list.push(mts); - }); - }); - this.list = list; - return this; - }, - /** turn result into two seperate results */ - splitBefore: function(reg, verbose) { - let list = []; - this.list.forEach((ts) => { - ts.splitBefore(reg, verbose).forEach((mts) => { - list.push(mts); - }); - }); - this.list = list; - return this; - }, - /** turn result into two seperate results */ - splitOn: function(reg, verbose) { - let list = []; - this.list.forEach((ts) => { - ts.splitOn(reg, verbose).forEach((mts) => { - list.push(mts); - }); - }); - this.list = list; - return this; - }, - }; - - //hook them into result.proto - Text.addMethods(Text, methods); - return Text; -}; - -module.exports = splitMethods; - -},{}],205:[function(_dereq_,module,exports){ -arguments[4][201][0].apply(exports,arguments) -},{"../paths":8,"dup":201}],206:[function(_dereq_,module,exports){ -'use strict'; -const isQuestion = _dereq_('../subset/sentences/isQuestion'); -const addSubsets = Text => { - //these subsets have no instance methods, so are simply a 'find' method. - const subsets = { - clauses: function (n) { - let r = this.splitAfter('#ClauseEnd'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - hashTags: function (n) { - let r = this.match('#HashTag').terms(); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - organizations: function (n) { - let r = this.splitAfter('#Comma'); - r = r.match('#Organization+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - phoneNumbers: function (n) { - let r = this.splitAfter('#Comma'); - r = r.match('#PhoneNumber+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - places: function (n) { - let r = this.splitAfter('#Comma'); - r = r.match('#Place+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - quotations: function (n) { - let matches = this.match('#Quotation+'); - let found = []; - matches.list.forEach((ts) => { - let open = 0; - let start = null; - //handle nested quotes - 'startQuote->startQuote->endQuote->endQuote' - ts.terms.forEach((t, i) => { - if (t.tags.StartQuotation === true) { - if (open === 0) { - start = i; - } - open += 1; - } - if (open > 0 && t.tags.EndQuotation === true) { - open -= 1; - } - if (open === 0 && start !== null) { - found.push(ts.slice(start, i + 1)); - start = null; - } - }); - //maybe we messed something up.. - if (start !== null) { - found.push(ts.slice(start, ts.terms.length)); - } - }); - matches.list = found; - if (typeof n === 'number') { - matches = matches.get(n); - } - return matches; - }, - topics: function (n) { - let r = this.clauses(); - // Find people, places, and organizations - let yup = r.people(); - yup.concat(r.places()); - yup.concat(r.organizations()); - let ignore = ['someone', 'man', 'woman', 'mother', 'brother', 'sister', 'father']; - yup = yup.not(ignore); - //return them to normal ordering - yup.sort('chronological'); - // yup.unique() //? not sure - if (typeof n === 'number') { - yup = yup.get(n); - } - return yup; - }, - urls: function (n) { - let r = this.match('#Url'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - questions: function (n) { - let r = this.all(); - if (typeof n === 'number') { - r = r.get(n); - } - let list = r.list.filter(ts => isQuestion(ts)); - return new Text(list, this.world, this.parent); - }, - statements: function (n) { - let r = this.all(); - if (typeof n === 'number') { - r = r.get(n); - } - let list = r.list.filter(ts => isQuestion(ts) === false); - return new Text(list, this.world, this.parent); - }, - parentheses: function (n) { - let r = this.match('#Parentheses+'); - //split-up consecutive ones - r = r.splitAfter('#EndBracket'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - }; - - Object.keys(subsets).forEach(k => { - Text.prototype[k] = subsets[k]; - }); - return Text; -}; -module.exports = addSubsets; - -},{"../subset/sentences/isQuestion":53}],207:[function(_dereq_,module,exports){ -//(Rule-based sentence boundary segmentation) - chop given text into its proper sentences. -// Ignore periods/questions/exclamations used in acronyms/abbreviations/numbers, etc. -// @spencermountain 2017 MIT -'use strict'; -const abbreviations = Object.keys(_dereq_('../world/more-data/abbreviations')); -// \u203D - Interrobang -// \u2E18 - Inverted Interrobang -// \u203C - Double Exclamation Mark -// \u2047 - Double Question Mark -// \u2048 - Question Exclamation Mark -// \u2049 - Exclamation Question Mark -// \u2026 - Ellipses Character - -//regs- -const abbrev_reg = new RegExp( - '\\b(' + abbreviations.join('|') + ')[.!?\u203D\u2E18\u203C\u2047-\u2049] *$', - 'i' -); -const acronym_reg = /[ .][A-Z]\.? *$/i; -const ellipses_reg = /(?:\u2026|\.{2,}) *$/; - -// Match different formats of new lines. (Mac: \r, Linux: \n, Windows: \r\n) -const new_line = /((?:\r?\n|\r)+)/; -const naiive_sentence_split = /(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g; - -const letter_regex = /[a-z0-9\u0000-\u007F]/i; //support an all-unicode sentence, i guess -const not_ws_regex = /\S/; - -// Start with a regex: -const naiive_split = function(text) { - let all = []; - //first, split by newline - let lines = text.split(new_line); - for (let i = 0; i < lines.length; i++) { - //split by period, question-mark, and exclamation-mark - let arr = lines[i].split(naiive_sentence_split); - for (let o = 0; o < arr.length; o++) { - all.push(arr[o]); - } - } - return all; -}; - -const sentence_parser = function(text) { - text = text || ''; - text = String(text); - let sentences = []; - // First do a greedy-split.. - let chunks = []; - // Ensure it 'smells like' a sentence - if (!text || typeof text !== 'string' || not_ws_regex.test(text) === false) { - return sentences; - } - // Start somewhere: - let splits = naiive_split(text); - // Filter-out the grap ones - for (let i = 0; i < splits.length; i++) { - let s = splits[i]; - if (s === undefined || s === '') { - continue; - } - //this is meaningful whitespace - if (not_ws_regex.test(s) === false) { - //add it to the last one - if (chunks[chunks.length - 1]) { - chunks[chunks.length - 1] += s; - continue; - } else if (splits[i + 1]) { - //add it to the next one - splits[i + 1] = s + splits[i + 1]; - continue; - } - } - //else, only whitespace, no terms, no sentence - chunks.push(s); - } - - //detection of non-sentence chunks: - //loop through these chunks, and join the non-sentence chunks back together.. - for (let i = 0; i < chunks.length; i++) { - let c = chunks[i]; - //should this chunk be combined with the next one? - if (chunks[i + 1] && letter_regex.test(c) && (abbrev_reg.test(c) || acronym_reg.test(c) || ellipses_reg.test(c))) { - chunks[i + 1] = c + (chunks[i + 1] || ''); - } else if (c && c.length > 0 && letter_regex.test(c)) { - //this chunk is a proper sentence.. - sentences.push(c); - chunks[i] = ''; - } - } - //if we never got a sentence, return the given text - if (sentences.length === 0) { - return [text]; - } - return sentences; -}; - -module.exports = sentence_parser; -// console.log(sentence_parser('john f. kennedy')); - -},{"../world/more-data/abbreviations":216}],208:[function(_dereq_,module,exports){ -module.exports=`{"words":"Comparative¦better|Superlative¦earlier|PresentTense¦sounds|Value¦a few|Noun¦autumn,daylight9eom,here,no doubt,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Copula¦a1is,w0;as,ere;m,re|Condition¦if,unless|PastTense¦be2came,d1had,mea0sa1taken,we0;nt;id;en,gan|Gerund¦accord0be0develop0go0result0stain0;ing|Negative¦n0;ever,o0;!n,t|QuestionWord¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s|Singular¦a06bZcUdQeOfLgKhGici0Ajel07kitty,lFmDnCoBp8question mark,r7s4t1us 0;dollVstW; rex,a1h0ic,ragedy,v show;ere,i07;l03x return;ky,t0uper bowl,yst06;ri04u0;dIff;alZi02oom;a1robl02u0;dCrpo8;rt,tE;cean,thers;othiXumbG;ayfTeeNo0;del,nopoS;iRunch;ead start,o0;lPme1u0;se;! run;adfMirlIlaci8od,rand slam,ulM;amiLly,olLr1un0;diN;iGosD;conomy,gg,ner3v0xampG;ent;eath,inn2o0ragonfG;cument6g0iFlFor;gy;er;an3eiliFhocol2i0ottage,redit card;ty,vil w0;ar;ate;ary;ankiAel7les9o2reakfast,u0;n0tterf6;ti8;dy,tt2y0;fri0;end;le;d1l0noma0;ly; homin2verti0;si0;ng;em|Infinitive¦0:6Y;1:7C;2:7A;3:79;4:5F;5:74;6:6D;7:6L;8:78;9:6W;A:73;B:76;C:6R;D:68;E:7D;F:60;a6Qb69c5Bd4Je43f3Qg3Jh3Ci2Zj2Xk2Tl2Km2Bn28o24p1Pques3Rr0Xs05tWuRvOwHyG;awn,ield;aJe24hist7iIoGre6H;nd0rG;k,ry;n,pe,sh,th0;lk,nHrGsh,tCve;n,raE;d0t;aHiGo8;ew,sA;l6Rry;nHpGr3se;gra4Wli49;dGi8lo65;erGo;go,mi5H;aNeMhKie,oJrHuGwi5;ne,rn;aGe0Ui60u5y;de,in,nsf0p,v5O;r37uC;ank,rG;eat2Vi2;nd,st;ke,lk,rg5Os8;a06c03eZhWi4Jkip,lVmUneTo56pQtJuGwitC;bmAck,ff0gge5ppHrGspe6;ge,pri1rou53vi2;ly,o3D;aLeKoJrHuG;dy,mb7;aDeGi2;ngth2Lss,tC;p,re;m,p;in,ke,r0Yy;iHlaFoil,rinG;g,k7;n,t;ak,e3E;aFe22i7o5B;am,e1Qip;aHiv0oG;ck,ut;re,ve;arCeIle6nHr2tG;!t7;d,se;k,m;aHo4rG;atCew;le,re;il,ve;a05eIisk,oHuG;b,in,le,n,sh;am,ll;a01cZdu9fYgXje6lUmTnt,pQquPsKtJvGwa5V;eGiew,o4U;al,l,rG;se,t;aDi4u42;eJi5oItG;!o4rG;i6uc20;l2rt;mb7nt,r2;e5i4;air,eHlGo40reseE;a9y;at;aDemb0i3Wo2;aHeGi2y;a1nt;te,x;a5Dr4A;act1Yer,le6u1;a12ei2k5PoGyc7;gni2Cnci7rd;ch,li2Bs5N;i1nG;ge,k;aTerSiRlPoNrIuG;b21ll,mp,rGsh,t;cha1s4Q;ai1eJiEoG;cHdu9greBhibAmi1te5vG;e,i2U;eBlaim;di6pa4ss,veE;iEp,rtr43sGur;e,t;a3RuG;g,n3;ck,le;fo32mAsi5;ck,iErt4Mss,u1y;bIccur,ff0pera8utweHverGwe;co47lap,ta3Qu1whelm;igh;ser2taD;eHotG;e,i9;ed,gle6;aLeKiIoHuG;ltip3Frd0;nit14ve;nGrr13;d,g7us;asu4lt,n0Qr3ssa3;intaDke d40na3rHtG;ch,t0;ch,k39ry;aMeLiIoGu1F;aGck,ok,ve;d,n;ft,ke,mAnHstGve;!en;e,k;a2Gc0Ht;b0Qck,uG;gh,nC;eIiHnoG;ck,w;ck,ll,ss;ep;am,oDuG;d3mp;gno4mQnGss3I;cOdica8flu0NhNsKtIvG;eGol2;nt,st;erGrodu9;a6fe4;i5tG;aGru6;ll;abAibA;lu1Fr1D;agi22pG;lemeEo20ro2;aKeIi4oHuG;nt,rry;ld fa5n03pe,st;aGlp;d,t;nd7ppGrm,te;en;aLet,loBoKrIuG;arGeBi14;ant39d;aGip,ow,umb7;b,sp;es,ve1I;in,th0ze;aQeaPiNlLoIracHuncG;ti3I;tu4;cus,lHrG;ce,eca5m,s30;d,l22;aFoG;at,od,w;gu4lGniFx;e,l;r,tu4;il,ll,vG;or;a13cho,dAle6mSnPstNvalua8xG;a0AcLerKi5pGte16;a15eHlaDoGreB;rt,se;ct,riG;en9;ci1t;el,han3;abGima8;liF;ab7couXdHfor9ga3han9j03riCsu4t0vG;isi2Vy;!u4;body,er3pG;hasiGow0;ze;a06eUiMoLrHuG;mp;aIeHiGop;ft;am,ss;g,in;!d3ubt;e,ff0p,re6sHvG;e,iXor9;aJcGli13miBpl18tinguiF;oGuB;uGv0;ra3;gr1YppG;ear,ro2;al,cNem,fLliv0ma0Cny,pKsHterG;mi0D;cribe,er2iHtrG;oy;gn,re;a08e07i6osA;eGi08y;at,ct;iIlHrG;ea1;a4i04;de;ma3n9re,te;a0Ae09h06i8l03oJrGut;aHeGoBuFy;a8dA;ck,ve;llYmSnHok,py,uGv0;gh,nt;cePdu6fMsKtIvG;eGin9;rt,y;aDin0XrG;a5ibu8ol;iGtitu8;d0st;iHoGroE;rm;gu4rm;rn;biKe,foJmaIpG;a4laD;re;nd;rt;ne;ap1e6;aHiGo1;ng,p;im,w;aHeG;at,ck,w;llen3n3r3se;a1nt0;ll,ncHrGt0u1;e,ry;el;aUeQloPoNrKuG;dgIlHrG;n,y;ly;et;aHuF;sh;ke;a5mb,o5rrGth0un9;ow;ck;ar,coSgDlHnefAtrG;ay;ie2ong;in;nGse;!g;band0Jc0Bd06ffo05gr04id,l01mu1nYppTrQsKttGvoid,waA;acIeHra6;ct;m0Fnd;h,k;k,sG;eIiHocia8uG;me;gn,st;mb7rt;le;chHgGri2;ue;!i2;eaJlIroG;aCve;ch;aud,y;l,r;noun9sw0tG;icipa8;ce;lHt0;er;e3ow;ee;rd;aRdIju5mAoR;it;st;!reB;ss;cJhie2knowled3tiva8;te;ge;ve;eIouEu1;se;nt;pt;on|Actor¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt|Honorific¦aObrigadiNcHdGexcellency,fiBking,liDmaAofficNp6queen,r3s0taoiseach,vice5;e0ultJ;c0rgeaC;ond liAretary;abbi,e0;ar0verend; adJ;astFr0;eside6i0ofessE;me ministEnce0;!ss;gistrate,r4yB;eld mar3rst l0;ady,i0;eutena0;nt;shA;oct5utchess;aptain,hance3o0;lonel,mmand4ngress0unci2;m0wom0;an;ll0;or;er;d0yatullah;mir0;al|SportsTeam¦0:1M;1:1T;2:1U;a1Rb1Dc0Zd0Qfc dallas,g0Nhouston 0Mindiana0Ljacksonville jagua0k0Il0Fm02newVoRpKqueens parkJrIsAt5utah jazz,vancouver whitecaps,w3yY;ashington 3est ham0Xh16;natio21redski1wizar12;ampa bay 6e5o3;ronto 3ttenham hotspur;blu1Hrapto0;nnessee tita1xasD;buccanee0ra1G;a7eattle 5heffield0Qporting kansas13t3;. louis 3oke12;c1Srams;mari02s3;eah1IounI;cramento Sn 3;antonio spu0diego 3francisco gi0Bjose earthquak2;char0EpaB;eal salt lake,o04; ran0C;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat2steele0;il3oenix su1;adelphia 3li2;eagl2philNunE;dr2;akland 4klahoma city thunder,r3;i10lando magic;athle0Trai3;de0; 3castle05;england 6orleans 5york 3;city fc,giUje0Lkn02me0Lred bul19y3;anke2;pelica1sain0J;patrio0Irevolut3;ion;aBe9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Rvi3;kings;imberwolv2wi1;re0Cuc0W;dolphi1heat,marli1;mphis grizz3ts;li2;nchester 5r3vN;i3li1;ne0;c00u0H;a4eicesterYos angeles 3;clippe0dodFlaA; galaxy,ke0;ansas city 3nH;chiefs,ro3;ya0M; pace0polis colX;astr0Edynamo,rockeWtexa1;i4olden state warrio0reen bay pac3;ke0;anT;.c.Aallas 7e3i0Cod5;nver 5troit 3;lio1pisto1ti3;ge0;bronc06nuggeO;cowboUmav3;er3;ic06; uX;arCelNh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki2;brow1cavalie0india1;benga03re3;ds;arlotte horCicago 3;b4cubs,fire,wh3;iteE;ea0ulY;di3olina panthe0;ff3naW; c3;ity;altimore ElAoston 7r3uffalo bilT;av2e5ooklyn 3;ne3;ts;we0;cel4red3; sox;tics;ackburn rove0u3;e ja3;ys;rs;ori3rave1;ol2;rizona Ast8tlanta 3;brav2falco1h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls|Uncountable¦0:1C;a1Hb1Bc12e0Wf0Qg0Mh0Gi0Dj0Cknowled1Gl07mYnXoWpRrOsCt8vi7w1;a5ea0Ai4o1;o2rld1;! seI;d,l;ldlife,ne;rmth,t0;neg0Xol08;e3hund0ime,oothpaste,r1una;affRou1;ble,sers,t;a,nnis;aAcene07e9h8il7now,o6p3te2u1;g0Rnshi0L;am,el;ace2e1;ciOed;!c12;ap,cc0ft0B;k,v0;eep,opp0O;riJ;d07fe0Wl1nd;m0Qt;ain,e1i0W;c1laxa0Csearch;ogni0Brea0B;a4e2hys0Elast9o1ress00;rk,w0;a1pp0trol;ce,nR;p0tiK;il,xygen;ews,oi0C;a7ea5i4o3u1;mps,s1;ic;nHo08;lk,st;sl1t;es;chine1il,themat00; learn02ry;aught0e3i2u1;ck,g07;ghtnZqu0CteratI;a1isH;th0;ewel7usti08;ce,mp1nformaOtself;ati1ortan06;en05;a4isto3o1;ck1mework,n1spitali01;ey;ry;ir,lib1ppi9;ut;o2r1um,ymnastJ;a7ound;l1ssip;d,f;i5lour,o2ruit,urnit1;ure;od,rgive1wl;ne1;ss;c6sh;conom9duca5lectriciMn3quip4th9very1;body,o1thB;ne;joy1tertain1;ment;tiC;a8elcius,h4iv3loth6o1urrency;al,ffee,ld w1nfusiAttA;ar;ics;aos,e1;e2w1;ing;se;ke,sh;a3eef,is2lood,read,utt0;er;on;g1ss;ga1;ge;c4dvi3irc2mnes1rt;ty;raft;ce;id|Unit¦0:17;a12b10c0Md0Le0Jf0Fg0Bh08in07joule0k01lZmOnNoMpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Lb,d0Rears old,o1;tt0F;att0b;able4b3e2on1sp;!ne0;a2r0B;!l,sp;spo03; ft,uare 1;c0Gd0Ff3i0Dkilo0Hm1ya0C;e0Kil1;e0li0F;eet0o0B;t,uart0;a3e2i1ou0Nt;c0Knt0;rcent,t00;!scals;hms,uVz;an0GewtR;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;²,³;e1g,z;ct1rtz0;aWogP;al2b,ig9ra1;in0m0;!l1;on0;a3emtOl1tG; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,l,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s|Pronoun¦'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s|Organization¦0:44;a39b2Qc2Ad22e1Yf1Ug1Mh1Hi1Ej1Ak18l14m0Tn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0You1w0Y;gov,tu2R;a3e1orld trade organizati3Z;lls fargo,st1;fie23inghou17;l1rner br3B;-m12gree30l street journ25m12;an halNeriz3Uisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Qps;es33i1;lev2Wted natio2T; mobi2Jaco bePd bMeAgi frida9h3im horto2Smz,o1witt2V;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen31daily ma2Vguess w2holli0rolling st1Ns1w2;mashing pumpki2Nuprem0;ho;ea1lack eyed pe3Dyrds;ch bo1tl0;ys;l2s1;co,la m13;efoni08us;a6e4ieme2Fnp,o2pice gir5ta1ubaru;rbucks,to2L;ny,undgard1;en;a2Px pisto1;ls;few24insbu25msu1W;.e.m.,adiohead,b6e3oyal 1yan2V;b1dutch she4;ank;/max,aders dige1Ed 1vl30;bu1c1Thot chili peppe2Ilobst27;ll;c,s;ant2Tizno2D;an5bs,e3fiz23hilip morrBi2r1;emier25octer & gamb1Qudenti14;nk floyd,zza hut;psi26tro1uge09;br2Ochina,n2O; 2ason1Wda2E;ld navy,pec,range juli2xf1;am;us;aAb9e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0L;l,s;c,stl3tflix,w1; 1sweek;kids on the block,york09;e,é;a,c;nd1Rs2t1;ional aca2Co,we0P;a,cYd0N;aAcdonald9e5i3lb,o1tv,yspace;b1Knsanto,ody blu0t1;ley crue,or0N;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt11z1V;'ore08a3e1g,ittle caesa1H;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1H;art;iffy lu0Jo3pmorgan1sa;! cha1;se;hnson & johns1Py d1O;bm,hop,n1tv;g,te1;l,rpol; & m,asbro,ewlett-packaSi3o1sbc,yundai;me dep1n1G;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Gu1;cci,ns n ros0;ldman sachs,o1;dye1g09;ar;axo smith kliYencore;electr0Gm1;oto0S;a3bi,da,edex,i1leetwood mac,oFrito-l08;at,nancial1restoU; tim0;cebook,nnie mae;b04sa,u3xxon1; m1m1;ob0E;!rosceptics;aiml08e5isney,o3u1;nkin donuts,po0Tran dur1;an;j,w j1;on0;a,f leppa2ll,peche mode,r spiegXstiny's chi1;ld;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra03;al;ca c5l4m1o08st03;ca2p1;aq;st;dplLgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Fy;dbury,pital o1rl's jr;ne;aFbc,eBf9l5mw,ni,o1p,rexiteeV;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roW;ckbuster video,omingda1;le; g1g1;oodriM;cht3e ge0n & jer2rkshire hathaw1;ay;ryG;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bWcRdidQerosmith,ig,lKmEnheuser-busDol,pple9r6s3t&t,v2y1;er;is,on;hland1sociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c|Demonym¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an|Region¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma|Possessive¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne|Currency¦$,aud,bRcPdKeurJfIgbp,hkd,inr,jpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotyRł;en,uanQ;af,of;h0t5;e0il5;k0q0;elL;iel,oubleKp,upeeK;e2ound st0;er0;lingH;n0soG;ceFn0;ies,y;e0i7;i,mpi6;n,r0wanzaByatB;!onaAw;ori7ranc9t;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s|Country¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an|City¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg|FemaleName¦0:G0;1:G4;2:FT;3:FF;4:FE;5:ER;6:FU;7:ET;8:GH;9:F1;A:GD;B:E7;C:EI;D:FQ;E:GA;F:FN;G:C8;aE4bD6cB9dAJe9Hf92g8Ih85i7Uj6Wk61l4Pm3An2Vo2Sp2Hqu2Fr1Ps0Rt05ursu7vVwPyMzH;aKeIoH;e,la,ra;lHna;da,ma;da,ra;as7GeIol1UvH;et5onBA;le0sen3;an9endBPhiB5iH;lJnH;if3BniHo0;e,f3A;a,helmi0lHma;a,ow;aNeKiH;cIviH;an9YenG4;kD1tor3;da,l8Wnus,rH;a,nHoniD4;a,iDE;leHnesEF;nDOrH;i1y;aTeQhOiNoKrHu7y4;acG6iHu0F;c3na,sH;h9Nta;nIrH;a,i;i9Kya;a5KffaCIna,s6;al3eHomasi0;a,l8Ho6Zres1;g7Vo6YrIssH;!a,ie;eCi,ri8;bOliNmLnJrIs6tHwa0;ia0um;a,yn;iHya;a,ka,s6;a4e4iHmCCra;!ka;a,t6;at6it6;a06carlet2Ze05hViTkye,oRtNuIyH;bFMlvi1;e,sIzH;an2Uet5ie,y;anHi8;!a,e,nH;aFe;aJeH;fHl3EphH;an2;cFBr73;f3nHphi1;d4ia,ja,ya;er4lv3mon1nHobh76;dy;aLeHirlBNo0y7;ba,e0i7lJrH;iHrBRyl;!d71;ia,lBX;ki4nJrIu0w0yH;la,na;i,leAon,ron;a,da,ia,nHon;a,on;l60re0;bNdMi9lLmJndIrHs6vannaF;aFi0;ra,y;aHi4;nt6ra;lBPome;e,ie;in1ri0;a03eYhWiUoIuH;by,thBM;bRcQlPnOsIwe0xH;an95ie,y;aIeHie,lE;ann8ll1marBHtB;!lHnn1;iHyn;e,nH;a,d7X;da,i,na;an9;hel55io;bin,erByn;a,cHkki,na,ta;helC2ki;ea,iannE0oH;da,n13;an0bJgi0i0nHta,y0;aHee;!e,ta;a,eH;cATkaF;chHe,i0mo0n5FquCGvDy0;aCFelHi9;!e,le;een2iH;a0nn;aNeMhKoJrH;iHudenAX;scil1Uyamva9;lly,rt3;ilome0oebe,ylH;is,lis;arl,ggy,nelope,r7t4;ige,m0Fn4Po7rvaBDtIulH;a,et5in1;ricHsy,tA9;a,e,ia;ctav3deIf86lHph86;a,ga,iv3;l3t5;aReQiKoHy7;eIrH;aFeDma;ll1mi;aLcJkHla,na,s6ta;iHki;!ta;hoB4k8ColH;a,eBJ;!mh;l7Una,risC;dJi5PnIo23taH;li1s6;cy,et5;eAiCQ;a01ckenz2eViLoIrignayani,uriBIyrH;a,na,tAV;i4ll9ZnH;a,iH;ca,ka,qB7;a,chPkaOlKmi,nJrHtzi;aHiam;!n9;a,dy,erva,h,n2;a,dJi9LlH;iHy;cent,e;red;!e7;ae7el3I;ag4LgLi,lIrH;edi62isCyl;an2iHliC;nHsAP;a,da;!an,han;b09c9Gd07e,g05i04l02n00rLtKuIv6TxGyHz2;a,bell,ra;de,rH;a,eD;h77il9t2;a,cTgPiKjor2l6Jn2s6tJyH;!aHbe5RjaAlou;m,n9V;a,ha,i0;!aJbAOeIja,lEna,sHt54;!a,ol,sa;!l07;!h,m,nH;!a,e,n1;arJeIie,oHr3Lueri5;!t;!ry;et3JiB;elHi62y;a,l1;dHon,ue7;akranBy;iHlo97;a,ka,n9;a,re,s2;daHg2;!l2Y;alEd2elHge,isBJon0;eiAin1yn;el,le;a0Je09iXoRuLyH;d3la,nH;!a,dIe9VnHsAT;!a,e9U;a,sAR;aB4cKelJiClIna,pHz;e,iB;a,u;a,la;iHy;a2Ce,l27n9;is,l1IrItt2uH;el7is1;aJeIi8na,rH;aGi8;lei,n1tB;!in1;aRbQd3lMnJsIv3zH;!a,be4Let5z2;a,et5;a,dH;a,sHy;ay,ey,i,y;a,iaJlH;iHy;a8Je;!n4G;b7Verty;!n5T;aOda,e0iMla,nLoJslAUtHx2;iHt2;c3t3;la,nHra;a,ie,o4;a,or1;a,gh,laH;!ni;!h,nH;a,d4e,n4O;cOdon7Ui7kes6na,rNtLurJvIxHy7;mi;ern1in3;a,eHie,yn;l,n;as6is6oH;nya,ya;a,isC;ey,ie,y;a01eWhadija,iOoNrJyH;lHra;a,ee,ie;isHy5D;!tH;a,en,iHy;!e,n48;ri,urtn9C;aNerMl9BmJrHzzy;a,stH;en,in;!berlH;eHi,y;e,y;a,stD;!na,ra;el6QiKlJnIrH;a,i,ri;d4na;ey,i,l9Ss2y;ra,s6;c8Yi5YlPma7nyakumari,rNss5MtKviByH;!e,lH;a,eH;e,i7A;a5FeIhHi3PlEri0y;arGerGie,leDr9Hy;!lyn75;a,en,iHl4Vyn;!ma,n31sC;ei74i,l2;a05eWilUoNuH;anLdKliHstG;aIeHsC;!nAt0W;!n8Z;e,i2Ry;a,iB;!anMcelEd5Wel73han6JlKni,sIva0yH;a,ce;eHie;fi0lEphG;eHie;en,n1;!a,e,n36;!i10lH;!i0Z;anMle0nJrIsH;i5Rsi5R;i,ri;!a,el6Rif1RnH;a,et5iHy;!e,f1P;a,e74iInH;a,e73iH;e,n1;cMd1mi,nIqueliAsmin2Uvie4yAzH;min8;a8eIiH;ce,e,n1s;!lHsCt06;e,le;inIk2lEquelH;in1yn;da,ta;da,lQmOnNo0rMsIvaH;!na;aIiHob6W;do4;!belHdo4;!a,e,l2G;en1i0ma;a,di4es,gr5T;el9ogH;en1;a,eAia0o0se;aNeKilIoHyacin1N;ll2rten1H;a5HdHla5H;a,egard;ath0XiIlHnrietBrmiAst0X;en25ga;di;il78lLnKrHtt2yl78z6G;iHmo4Hri4I;etH;!te;aFnaF;ey,l2;aZeUiPlNold13rJwH;enHyne19;!dolE;acIetHisel9;a,chD;e,ieH;!la;adys,enHor3yn1Z;a,da,na;aKgi,lIna,ov74selH;a,e,le;da,liH;an;!n0;mZnJorgIrH;aldGi,m2Utru76;et5i5W;a,eHna;s1Ovieve;briel3Hil,le,rnet,yle;aSePio0loNrH;anIe9iH;da,e9;!cH;esIiHoi0H;n1s3X;!ca;!rH;a,en45;lIrnH;!an9;ec3ic3;rItiHy8;ma;ah,rah;d0GileDkBl01mVn4DrSsNtMuLvH;aJelIiH;e,ta;in0Byn;!ngelG;geni1la,ni3T;h55ta;meral9peranKtH;eIhHrel7;er;l2Rr;za;iHma,nestGyn;cHka,n;a,ka;eKilJmH;aHie,y;!liA;ee,i1y;lHrald;da,y;aUeSiNlMma,no4oKsJvH;a,iH;na,ra;a,ie;iHuiH;se;a,en,ie,y;a0c3da,nKsHzaI;aHe;!beH;th;!a,or;anor,nH;!a;in1na;en,iHna,wi0;e,th;aXeLiKoHul2W;lor54miniq41n32rHtt2;a,eDis,la,othHthy;ea,y;an0AnaFonAx2;anQbPde,eOiMja,lJmetr3nHsir4X;a,iH;ce,se;a,iIla,orHphiA;es,is;a,l5M;dHrdH;re;!d4Pna;!b2EoraFra;a,d4nH;!a,e;hl3i0mNnLphn1rIvi1YyH;le,na;a,by,cIia,lH;a,en1;ey,ie;a,et5iH;!ca,el1Cka;arHia;is;a0Se0Oh06i04lWoKrIynH;di,th3;istHy06;al,i0;lQnNrIurH;tn1F;aKdJiHnJriA;!nH;a,e,n1;el3;!l1T;n2sH;tanHuelo;ce,za;eHleD;en,t5;aJeoIotH;il4D;!pat4;ir8rJudH;et5iH;a,ne;a,e,iH;ce,sY;a4er4ndH;i,y;aQeNloe,rH;isIyH;stal;sy,tH;aIen,iHy;!an1e,n1;!l;lseIrH;!i8yl;a,y;nMrH;isKlImH;aiA;a,eHot5;n1t5;!sa;d4el1RtH;al,el1Q;cIlH;es5i3H;el3ilH;e,ia,y;iZlYmilXndWrOsMtHy7;aKeJhHri0;erGleDrEy;in1;ri0;li0ri0;a2IsH;a2Hie;a,iNlLmeJolIrH;ie,ol;!e,in1yn;lHn;!a,la;a,eHie,y;ne,y;na,sC;a0Ei0E;a,e,l1;isBl2;tlH;in,yn;arb0DeZianYlWoUrH;andSeQiJoIyH;an0nn;nwEok8;an2PdgLg0KtH;n29tH;!aInH;ey,i,y;ny;etH;!t8;an0e,nH;da,na;i8y;bbi8nH;iBn2;ancHossom,ythe;a,he;ca;aScky,lin9niBrOssNtJulaFvH;!erlH;ey,y;hIsy,tH;e,i11y8;!anH;ie,y;!ie;nHt6yl;adIiH;ce;et5iA;!triH;ce,z;a4ie,ra;aliy2Bb26d1Ng1Ji1Bl0Um0Pn03rYsPthe0uLvJyH;anHes6;a,na;a,eHr27;ry;drJgusIrH;el3o4;ti0;a,ey,i,y;hItrH;id;aLlHt1Q;eIi8yH;!n;e,iHy;gh;!nH;ti;iJleIpiB;ta;en,n1t5;an1AelH;le;aZdXeVgRiPja,nItoHya;inet5n3;!aKeIiHmJ;e,ka;!mHt5;ar2;!belIliCmU;sa;!le;ka,sHta;a,sa;elHie;a,iH;a,ca,n1qH;ue;!t5;te;je7rea;la;!bImHstas3;ar3;el;aJberIel3iHy;e,na;!ly;l3n9;da;aUba,eOiLlJma,ta,yH;a,c3sH;a,on,sa;iHys0K;e,s0J;a,cIna,sHza;a,ha,on,sa;e,ia;c3is6jaJna,ssaJxH;aHia;!nd4;nd4;ra;ia;i0nIyH;ah,na;a,is,naF;c6da,leDmMnslLsH;haFlH;inHyX;g,n;!h;ey;ee;en;at6g2nH;es;ie;ha;aWdiTelMrH;eJiH;anMenH;a,e,ne;an0;na;aLeKiIyH;nn;a,n1;a,e;!ne;!iH;de;e,lEsH;on;yn;!lH;iAyn;ne;agaKbIiH;!gaJ;ey,i8y;!e;il;ah|Place¦aMbKcIdHeFfEgBhAi9jfk,kul,l7m5new eng4ord,p2s1the 0upJyyz;bronx,hamptons;fo,oho,under2yd;acifMek,h0;l,x;land;a0co,idDuc;libu,nhattK;a0gw,hr;s,x;ax,cn,ndianGst;arlem,kg,nd;ay village,re0;at 0enwich;britain,lak2;co,ra;urope,verglad0;es;en,fw,own1xb;dg,gk,hina0lt;town;cn,e0kk,rooklyn;l air,verly hills;frica,m5ntar1r1sia,tl0;!ant1;ct0;ic0; oce0;an;ericas,s|Person¦a01bZcTdQeOfMgJhHinez,jFkEleDmAnettPo9p7r4s3t2uncle,v0womL;a0irgin maH;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussaQcarlett johanssRistZlobodan milosevic,omeone,tepGuC;ay romano,eese witherspoQo1ush limbau0;gh;d stewart,naldinho,sario;a0ipV;lmUris hiltM;prah winfrOra;an,essiaen,itt romnNo0ubarek;m0thR;!my;bron james,e;anye west,iefer sutherland,obe bryaN;aime,effersFk rowli0;ng;alle ber0ulk hog3;ry;astBentlem1irl,rand0uy;fa2mo2;an;a0ella;thF;ff0meril lagasse,zekiel;ie;a0enzel washingt4ick wolf,ude;d0lt3nte;!dy;ar2lint1ous0ruz;in;on;dinal wols1son0;! palm5;ey;arack obama,oy,ro0;!ck,th2;dolf hitl1shton kutch1u0;nt;er|WeekDay¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s|Date¦autumn,daylight9eom,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Time¦a6breakfast 5dinner5e3lunch5m2n0oclock,some5to7;i7o0;on,w;id4or1;od,ve0;ning;time;fternoon,go,ll day,t 0;ni0;ght|Holiday¦0:1Q;1:1P;a1Fb1Bc12d0Ye0Of0Kg0Hh0Di09june07kwanzaa,l04m00nYoVpRrPsFt9v6w4xm03y2;om 2ule;hasho16kippur;hit2int0Xomens equalit8; 0Ss0T;alentines3e2ictor1E;r1Bteran1;! 0;-0ax 0h6isha bav,rinityMu2; b3rke2;y 0;ish2she2;vat;a0Xe prophets birth0;a6eptember14h4imchat tor0Ut 3u2;kk4mmer T;a8p7s6valentines day ;avu2mini atzeret;ot;int 2mhain;a4p3s2valentine1;tephen1;atrick1;ndrew1;amadan,ememberanc0Yos2;a park1h hashana;a3entecost,reside0Zur2;im,ple heart 0;lm2ssovE; s04;rthodox 2stara;christma1easter2goOhoJn0C;! m07;ational 2ew years09;freedom 0nurse1;a2emorial 0lHoOuharram;bMr2undy thurs0;ch0Hdi gr2tin luther k0B;as;a2itRughnassadh;bour 0g baom2ilat al-qadr;er; 2teenth;soliU;d aJmbolc,n2sra and miraj;augurGd2;ependen2igenous people1;c0Bt1;a3o2;ly satur0;lloween,nukkUrvey mil2;k 0;o3r2;ito de dolores,oundhoW;odW;a4east of 2;our lady of guadalupe,the immaculate concepti2;on;ther1;aster8id 3lectYmancip2piphany;atX;al-3u2;l-f3;ad3f2;itr;ha;! 2;m8s2;un0;ay of the dead,ecemb3i2;a de muertos,eciseis de septiembre,wali;er sol2;stice;anad8h4inco de mayo,o3yber m2;on0;lumbu1mmonwealth 0rpus christi;anuk4inese n3ristmas2;! N;ew year;ah;a 0ian tha2;nksgiving;astillCeltaine,lack4ox2;in2;g 0; fri0;dvent,ll 9pril fools,rmistic8s6u2;stral4tum2;nal2; equinox;ia 0;cens2h wednes0sumption of mary;ion 0;e 0;hallows 6s2;ai2oul1t1;nt1;s 0;day;eve|Month¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il|Duration¦centur4d2hour3m0seconds,week3year3;i0onth2;llisecond1nute1;ay0ecade0;!s;ies,y|FirstName¦aEblair,cCdevBj8k6lashawn,m3nelly,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0;ls7nyatta,rry;am0ess1;ie,m0;ie;an,on;as0heyenne;ey,sidy;lexis,ndra,ubr0;ey|LastName¦0:35;1:3A;2:3C;3:2Z;4:2F;a3Bb31c2Od2Ee2Bf25g1Zh1Oi1Jj1Dk16l0Ym0Mn0Io0Fp04rXsLtGvEwBxAy7zh5;a5ou,u;ng,o;a5eun2Uoshi1Jun;ma5ng;da,guc1Zmo27sh21zaQ;iao,u;a6eb0il5o3right,u;li3Bs1;gn0lk0ng,tanabe;a5ivaldi;ssilj37zqu2;a8h7i2Go6r5sui,urn0;an,ynisI;lst0Orr1Uth;at1Uomps1;kah0Unaka,ylor;aDchCeBhimizu,iAmi9o8t6u5zabo;ar2lliv2AzuD;a5ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n6sa5to;ki;ch2dKtos,z;amAeag1Zi8o6u5;bio,iz,sC;b5dri1MgHj0Sme24osevelt,sZux;erts,ins1;c5ve0E;ci,hards1;ir2os;aDe9h7ic5ow20;as5hl0;so;a5illips;m,n1T;ders20et7r6t5;e0Nr4;ez,ry;ers;h21rk0t5vl4;el,te0J;baAg0Alivei00r5;t5w1O;ega,iz;a5eils1guy1Rix1owak,ym1E;gy,ka5var1K;ji5muV;ma;aDeBiAo7u5;ll0n5rr0Bssolini,ñ5;oz;lina,oJr5zart;al0Me5r0U;au,no;hhail4ll0;rci0s5y0;si;eVmmad4r5tsu07;in5tin2;!o;aBe7i5op2uo;!n5u;coln,dholm;fe6n0Qr5w0J;oy;bv5v5;re;mmy,rs14u;aAennedy,imu9le0Lo7u6wo5;k,n;mar,znets4;bay5vacs;asY;ra;hn,rl8to,ur,zl4;a9en8ha3imen2o5u3;h5nYu3;an5ns1;ss1;ki0Es0S;cks1nsse0D;glesi8ke7noue,shik6to,vano5;u,v;awa;da;as;aBe8it7o6u5;!a3b0ghNynh;a3ffmann,rvat;chcock,l0;mingw6nde5rM;rs1;ay;ns0ErrPs6y5;asCes;an4hi5;moI;a8il,o7r6u5;o,tierr2;ayli3ub0;m2nzal2;nd5o,rcia;hi;er9is8lor7o6uj5;ita;st0urni0;es;ch0;nand2;d6insteGsposi5vaK;to;is1wards;aBeAi8omin7u5;bo5rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw6vi5;es,s;in;aEhAlark9o5;hKl5op0rbyn,x;em6li5;ns;an;!e;an7e6iu,o5ristensFu3we;i,ng,u3w,y;!n,on5u3;!g;mpb6rt0st5;ro;ell;aAe7ha3lanco,oyko,r5yrne;ooks,yant;ng;ck6ethov5nnett;en;er,ham;ch,h7iley,rn5;es,i0;er;k,ng;dCl8nd5;ers5r9;en,on,s1;on;eks6iy7var2;ez;ej5;ev;ams|MaleName¦0:CE;1:BK;2:C2;3:BS;4:B4;5:BZ;6:AT;7:9V;8:BC;9:AW;A:AO;B:8W;aB5bA9c98d88e7Hf6Zg6Hh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt07u06v01wOxavi3yHzC;aCor0;cCh8Jne;hDkC;!a5Z;ar51e5Y;ass2i,oDuC;sEu25;nFsEusC;oCsD;uf;ef;at0g;aKeIiDoCyaAQ;lfgang,odrow;lCn1O;bEey,frBJlC;aA6iC;am,e,s;e8Aur;i,nde7sC;!l6t1;de,lDrr5yC;l1ne;lCt3;a94y;aFern1iC;cDha0nceCrg9Cva0;!nt;ente,t5B;lentin49n8Zughn;lyss4Msm0;aTeOhLiJoFrDyC;!l3ro8s1;av9ReCist0oy,um0;nt9Jv55y;bEd7YmCny;!as,mCoharu;aAYie,y;iBy;mCt9;!my,othy;adDeoCia7EomB;!do7O;!de9;dFrC;en8JrC;an8IeCy;ll,n8H;!dy;dgh,ic9Unn3req,ts46;aScotQeOhKiIoGpenc3tCur1Pylve8Jzym1;anEeCua7D;f0phAGvCwa7C;e59ie;!islaw,l6;lom1nA4uC;leyma8ta;dClBm1;!n6;aEeC;lCrm0;d1t1;h6Une,qu0Vun,wn,y8;aCbasti0k1Yl42rg41th,ymo9J;m9n;!tC;!ie,y;lDmCnti22q4Kul;!mAu4;ik,vato6X;aXeThe94iPoGuDyC;an,ou;b6NdDf9pe6SssC;!elAK;ol2Vy;an,bJcIdHel,geGh0landA4mFnEry,sDyC;!ce;coe,s;!a96nA;an,eo;l3Kr;e4Sg3n6oA5ri6A;co,ky;bAe9V;cCl6;ar5Qc5PhDkCo;!ey,ie,y;a87ie;gDid,ub5x,yCza;ansh,nT;g8XiC;na8Ts;ch60fa4lEmDndCpha4sh6Wul,ymo72;alA0ol2Cy;i9Jon;f,ph;ent2inC;cy,t1;aGeEhilDier64ol,reC;st1;!ip,lip;d9Crcy,tC;ar,e2W;b3Udra6Ht46ul;ctav2Wliv3m97rGsDtCum8Vw5;is,to;aDc8TvC;al54;ma;i,l4BvK;athKeIiEoC;aCel,l0ma0r2Y;h,m;cDg4i3KkC;h6Wola;holBkColB;!olB;al,d,il,ls1vC;il52;anCy;!a4i4;aXeUiLoGuDyC;l22r1;hamDr61staC;fa,p4I;ed,mG;dibo,e,hamEis1YntDsCussa;es,he;e,y;ad,ed,mC;ad,ed;cHgu4kFlEnDtchC;!e7;a7Aik;o04t1;e,olC;aj;ah,hCk6;a4eC;al,l;hDlv2rC;le,ri7v2;di,met;ck,hOlMmPnu4rIs1tEuricDxC;!imilian87we7;e,io;eo,hDiBtC;!eo,hew,ia;eCis;us,w;cEio,k81lDqu6Isha7tCv2;i2Jy;in,on;!el,oLus;achCcolm,ik;ai,y;amCdi,moud;adC;ou;aSeOiNlo2ToJuDyC;le,nd1;cFiEkCth3;aCe;!s;gi,s;as,iaC;no;g0nn6SrenEuCwe7;!iC;e,s;!zo;am,on4;a7Cevi,la4UnEoCst3vi;!nC;!a62el;!ny;mDnCr16ur4Vwr4V;ce,d1;ar,o4P;aJeEhaled,iCrist4Xu4Ay3D;er0p,rC;by,k,ollos;en0iFnCrmit,v2;!dDnCt5E;e10y;a7ri4P;r,th;na69rCthem;im,l;aZeRiPoEuC;an,liCst2;an,o,us;aqu2eKhnJnHrFsC;eDhCi7Due;!ua;!ph;dCge;an,i,on;!aCny;h,s,th4Z;!ath4Yie,nA;!l,sCy;ph;an,e,mC;!mA;d,ffHrEsC;sCus;!e;a5KemDmai8oCry;me,ni0Q;i6Wy;!e07rC;ey,y;cId5kHmGrEsDvi3yC;!d5s1;on,p3;ed,od,rCv4O;e51od;al,es,is1;e,ob,ub;k,ob,quC;es;aObrahNchika,gLkeKlija,nuJrHsEtCv0;ai,sC;uki;aCha0i6Hma4sac;ac,iaC;h,s;a,vinCw2;!g;k,nngu53;!r;nacCor;io;im;in,n;aLeGina4WoEuCyd57;be27gCmber4EsE;h,o;m3ra35sCwa3Z;se2;aFctEitEnDrC;be22m0;ry;or;th;bLlKmza,nJo,rEsDyC;a44d5;an,s0;lFo4FrEuCv6;hi41ki,tC;a,o;is1y;an,ey;k,s;!im;ib;aReNiMlenLoJrFuC;illerDsC;!tavo;mo;aEegCov3;!g,orC;io,y;dy,h58nt;nzaCrd1;lo;!n;lbe4Qno,ovan4S;ne,oErC;aCry;ld,rd4O;ffr6rge;bri4l5rCv2;la20r3Fth,y;aSeOiMlKorr0JrC;anEedCitz;!dAeCri25;ri24;cEkC;!ie,lC;in,yn;esKisC;!co,zek;etch3oC;yd;d4lConn;ip;deriEliDng,rnC;an02;pe,x;co;bi0di;ar00dVfrUit0lOmHnGo2rDsteb0th0uge8vCym5zra;an,ere2W;gi,iDnCrol,v2w2;est3Zie;c08k;och,rique,zo;aHerGiDmC;aGe2Q;lDrC;!h0;!io;s1y;nu4;be0Ad1iFliEmDt1viCwood;n,s;er,o;ot1Us;!as,j44sC;ha;a2en;!dAg32mFuDwC;a26in;arC;do;o0Tu0T;l,nC;est;aZePiMoFrEuDwCyl0;ay8ight;a8dl6nc0st2;ag0ew;minGnEri0ugDyC;le;!lB;!a29nCov0;e7ie,y;go,icC;!k;armuDeCll1on,rk;go;id;anJj0lbeImetri9nGon,rFsEvDwCxt3;ay8ey;en,in;hawn,mo09;ek,ri0G;is,nCv3;is,y;rt;!dC;re;lLmJnIrEvC;e,iC;!d;en,iEne7rCyl;eCin,yl;l2Wn;n,o,us;!e,i4ny;iCon;an,en,on;e,lB;as;a07e05hXiar0lMoHrFuDyrC;il,us;rtC;!is;aCistobal;ig;dy,lFnDrC;ey,neli9y;or,rC;ad;by,e,in,l2t1;aHeEiCyJ;fCnt;fo0Dt1;meDt9velaC;nd;nt;rEuDyC;!t1;de;enC;ce;aGeFrisDuC;ck;!tC;i0oph3;st3;d,rlCs;eCie;s,y;cCdric,s11;il;lFmer1rC;ey,lDro7y;ll;!os,t1;eb,v2;ar03eVilUlaToQrDuCyr1;ddy,rtJ;aKeFiEuDyC;an,ce,on;ce,no;an,ce;nDtC;!t;dDtC;!on;an,on;dDndC;en,on;!foCl6y;rd;bDrCyd;is;!by;i8ke;al,lA;nGrCshoi;at,nDtC;!r11;aCie;rd0M;!edict,iDjam2nA;ie,y;to;n6rCt;eCy;tt;ey;ar0Yb0Od0Kgust2hm0Hid5ja0FlZmXnPputsiOrFsaEuCya0ziz;gust9st2;us;hi;aJchIi4jun,maGnEon,tCy0;hCu07;ur;av,oC;ld;an,nd05;el;ie;ta;aq;dHgel00tC;hoFoC;i8nC;!iXy;ne;ny;reCy;!as,s,w;ir,mCos;ar;an,bePd5eJfGi,lFonEphonIt1vC;aNin;on;so,zo;an,en;onDrC;edK;so;c,jaFksandEssaFxC;!and3;er;ar,er;ndC;ro;rtC;!o;ni;en;ad,eC;d,t;in;aDoCri0vik;lfo;mCn;!a;dGeFraDuC;!bakr,lfazl;hCm;am;!l;allFel,oulaye,ulC;!lDrahm0;an;ah,o;ah;av,on|Verb¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en|PhrasalVerb¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut|Modal¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld|Adjective¦0:73;1:7I;2:7O;3:7H;4:7A;5:5A;6:47;7:48;8:4Q;9:5Z;A:7F;B:6X;C:5V;D:6Y;E:71;a6Hb63c5Pd55e4Rf48g40h3Pi34j32k31l2Qm2Fn26o1Qp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6A;d6Czy;despr73s5E;!sa7;eGlFste25;co1Hl o4J;!k5;aGiFola4A;b7Rce versa,ol53;ca2gabo61nilla;ltWnJpGrb58su4tterF;!moB; f33b1NpGsFti1G;ca7et,ide dMtairs;er,i3M;aPbeco6Pconvin26deMeLfair,ivers4knKprecedYrIsGwF;iel1Zritt5X;i1UuF;pervis0specti3;eFu5;cognLgul6Fl6F;own;ndi3v5Rxpect0;cid0rF;!grou5MsF;iz0tood;b7ppeaLssu6EuthorF;iz0;i23ra;aJeHhough4NoGrF;i1oubl0;geth8p,rpD;en5OlFm4Yrr2Tst0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3DoPpOqueami3DtJuFymb62;bHi gener53pFrprisi3;erFre0K;! dup8b,i28;du0seq4S;anda6SeIi0OrFy37;aightFip0; fFfF;or59;adfaBreotyp0;aCec2Fir1IlendDot on; call0le,mb8phist1WrFu0Wvi40;dDry;gnifica2nF;ceCg7;am2Oe8ocki3ut;cFda1em5lfi2Xni1Vpa67re6;o1Fr3U;at56ient27reec56;cr0me,ns serif;aMeIiGoF;buBtt4SuSy4;ghtFv4;!-28f9;ar,bel,condi1du61fres50lHpublic3UsFtard0;is46oF;lu1na2;e1Duc44;bDciF;al,st;aPeNicayu6lacDopuliBrGuF;bl58mp0;eJiGoF;!b09fuEmi30p8;mGor,sFva1;ti6;a4Ue;ciEmF;a0Hi5I;ac20rFti1;feAma2Tplexi3v33;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Lsi45;en,posi1; boa5Fg2Jli6;!ay; gua5DbFli6;eat;eHsF;cFer0Hole1;e6uC;d2Sse;ak0eMiLoFua4O;nJrGtF;ab7;thF;!eF;rn;chala2descri4Zstop;ght5;arby,cessa3Wighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuC;di4EnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abCho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3C;!-0C;nguDst,tt8;ap1Sind5no0A;agg0uF;niOstifi0veni7;de4gno4Blleg4mSnHpso 1VrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenEoxF;ic36;a6i2R;a1er,oce2;iGoF;or;reA;deq3Jppr2Y;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0Q;d2QnE;aKelJiHoFumdr3B;neBok0rrFs07ur5;if2S;ghfalut1OspF;an2Q;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Jiga22lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Dob4;aUeOinNlMoHrF;a1TeFoz1K;e2Dq12tf9;oHrF; keeps,eFm8tuna1;g04ign;liF;sh;ag2Zue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lEr Fux,vori1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiC;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erE;creHeas0gruntl0honeBordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarClJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraDg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainBgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerE;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt|Comparable¦0:41;1:4I;2:45;3:4B;4:2Y;5:3X;a4Ob44c3Od3De35f2Rg2Fh24i1Vj1Uk1Rl1Im1Cn16o14p0Tqu0Rr0IsRtKuIvFw7y6za12;ell27ou3;aBe9hi1Yi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Mt;k,ry;n1Tr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Mse5;like0ti1;aAen9hi8i7ough,r6;anqu2Qen1ue;dy,g3Ume0ny,r09;ck,n,rs2R;d42se;ll,me,rt,s6wd47;te5;aVcarUeThRiQkin0GlMmKoHpGqua1HtAu7w6;eet,ift;b7dd15per0Hr6;e,re2J;sta2Ht4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Hn0W;a1ep,rn;le,rk;e24i3Hright0;ci2Aft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g37m6;!y;ek,nd3F;ck,l0mp4;a6iUort,rill,y;dy,ll0Zrp;cu0Tve0Txy;ce,ed,y;d,fe,int0l1Xv16;aBe9i8o6ude;mantic,o1Ksy,u6;gh,nd;ch,pe,tzy;a6d,mo0J;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aFhoEi1SlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fou00ud;ey,k0;li06or,te1D;a6easa2;in,nt;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd|Adverb¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori|Expression¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la|Preposition¦'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut|Conjunction¦aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh|Determiner¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er","conjugations":"t:ake,ook,,,aken|:can,could,can,_|free:_,,,ing|puk:e,,,ing|ar:ise,ose,,,isen|babys:it,at|:be,was,is,am,been|:is,was,is,being|beat:_,,,ing,en|beg:in,an,,inning,un|ban:_,ned,,ning|bet:_,,,,_|bit:e,_,,ing,ten|ble:ed,d,,,d|bre:ed,d|br:ing,ought,,,ought|broadcast:_,_|buil:d,t,,,t|b:uy,ought,,,ought|cho:ose,se,,osing,sen|cost:_,_|deal:_,t,,,t|d:ie,ied,,ying|d:ig,ug,,igging,ug|dr:aw,ew,,,awn|dr:ink,ank,,,unk|dr:ive,ove,,iving,iven|:eat,ate,,eating,eaten|f:all,ell,,,allen|fe:ed,d,,,d|fe:el,lt|f:ight,ought,,,ought|f:ind,ound|fl:y,ew,,,own|bl:ow,ew,,,own|forb:id,ade|edit:_,,,ing|forg:et,ot,,eting,otten|forg:ive,ave,,iving,iven|fr:eeze,oze,,eezing,ozen|g:et,ot|g:ive,ave,,iving,iven|:go,went,goes,,gone|h:ang,ung,,,ung|ha:ve,d,s,ving,d|hear:_,d,,,d|hid:e,_,,,den|h:old,eld,,,eld|hurt:_,_,,,_|la:y,id,,,id|le:ad,d,,,d|le:ave,ft,,,ft|l:ie,ay,,ying|li:ght,t,,,t|los:e,t,,ing|ma:ke,de,,,de|mean:_,t,,,t|me:et,t,,eting,t|pa:y,id,,,id|read:_,_,,,_|r:ing,ang,,,ung|r:ise,ose,,ising,isen|r:un,an,,unning,un|sa:y,id,ys,,id|s:ee,aw,,eeing,een|s:ell,old,,,old|sh:ine,one,,,one|sho:ot,t,,,t|show:_,ed|s:ing,ang,,,ung|s:ink,ank|s:it,at|slid:e,_,,,_|sp:eak,oke,,,oken|sp:in,un,,inning,un|st:and,ood|st:eal,ole|st:ick,uck|st:ing,ung|:stream,,,,|str:ike,uck,,iking|sw:ear,ore|sw:im,am,,imming|sw:ing,ung|t:each,aught,eaches|t:ear,ore|t:ell,old|th:ink,ought|underst:and,ood|w:ake,oke|w:ear,ore|w:in,on,,inning|withdr:aw,ew|wr:ite,ote,,iting,itten|t:ie,ied,,ying|ski:_,ied|:boil,,,,|miss:_,,_|:act,,,,|compet:e,ed,,ing|:being,were,are,are|impl:y,ied,ies|ic:e,ed,,ing|develop:_,ed,,ing|wait:_,ed,,ing|aim:_,ed,,ing|spil:l,t,,,led|drop:_,ped,,ping|log:_,ged,,ging|rub:_,bed,,bing|smash:_,,es|egg:_,ed|suit:_,ed,,ing|age:_,d,s,ing|shed:_,_,s,ding|br:eak,oke|ca:tch,ught|d:o,id,oes|b:ind,ound|spread:_,_|become:_,,,,_|ben:d,,,,t|br:ake,,,,oken|burn:_,,,,ed|burst:_,,,,_|cl:ing,,,,ung|c:ome,ame,,,ome|cre:ep,,,,pt|cut:_,,,,_|dive:_,,,,d|dream:_,,,,t|fle:e,,,eing,d|fl:ing,,,,ung|got:_,,,,ten|grow:_,,,,n|hit:_,,,,_|ke:ep,,,,pt|kne:el,,,,lt|know:_,,,,n|leap:_,,,,t|len:d,,,,t|lo:ose,,,,st|prove:_,,,,n|put:_,,,,_|quit:_,,,,_|rid:e,,,,den|s:eek,,,,ought|sen:d,,,,t|set:_,,,,_|sew:_,,,,n|shake:_,,,,n|shave:_,,,,d|shut:_,,,,_|s:eat,,,,at|sla:y,,,,in|sle:ep,,,,pt|sn:eak,,,,uck|spe:ed,,,,d|spen:d,,,,t|sp:it,,,,at|split:_,,,,_|spr:ing,,,,ung|st:ink,unk,,,unk|strew:_,,,,n|sw:are,,,,orn|swe:ep,,,,pt|thrive:_,,,,d|undergo:_,,,,ne|upset:_,,,,_|w:eave,,,,oven|we:ep,,,,pt|w:ind,,,,ound|wr:ing,,,,ung","plurals":"addend|um|a,alga|e,alumna|e,alumn|us|i,appendi|x|ces,avocado|s,bacill|us|i,barracks|,beau|x,bus|es,cact|us|i,chateau|x,analys|is|es,diagnos|is|es,parenthes|is|es,prognos|is|es,synops|is|es,thes|is|es,child|ren,circus|es,clothes|,corp|us|ora,criteri|on|a,curricul|um|a,database|s,deer|,echo|es,embargo|es,epoch|s,f|oot|eet,gen|us|era,g|oose|eese,halo|s,hippopotam|us|i,ind|ex|ices,larva|e,lea|f|ves,librett|o|i,loa|f|ves,m|an|en,matri|x|ces,memorand|um|a,modul|us|i,mosquito|es,move|s,op|us|era,ov|um|a,ox|en,pe|rson|ople,phenomen|on|a,quiz|zes,radi|us|i,referend|um|a,rodeo|s,sex|es,shoe|s,sombrero|s,stomach|s,syllab|us|i,tableau|x,thie|f|ves,t|ooth|eeth,tornado|s,tuxedo|s,zero|s","patterns":{"Person":["master of #Noun","captain of the #Noun"]},"regex":{"HashTag":["^#[a-z]+"],"Gerund":["^[a-z]+n['’]$"],"PhoneNumber":["^[0-9]{3}-[0-9]{4}$","^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$"],"Time":["^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$","^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$","^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$","^[PMCE]ST$","^utc ?[+-]?[0-9]+?$","^[a-z0-9]*? o'?clock$"],"Date":["^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$","^[0-9]{1,4}/[0-9]{1,2}/[0-9]{1,4}$"],"Money":["^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?$","^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$"],"Value":["^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?$","^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$","^[0-9.]{1,2}[-–][0-9]{1,2}$"],"NumberRange":["^[0-9.]{1,4}(st|nd|rd|th)?[-–][0-9.]{1,4}(st|nd|rd|th)?$","^[0-9.]{1,2}[-–][0-9]{1,2}$"],"NiceNumber":["^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$"],"NumericValue":["^[-+]?[0-9]+(.[0-9]+)?$","^.?[0-9]+([0-9,.]+)?%$"],"Percent":["^.?[0-9]+([0-9,.]+)?%$"],"Cardinal":["^.?[0-9]+([0-9,.]+)?%$"],"Fraction":["^[0-9]{1,4}/[0-9]{1,4}$"],"LastName":["^ma?c'.*","^o'[drlkn].*"]}}` -},{}],209:[function(_dereq_,module,exports){ -'use strict'; -const conjugate = _dereq_('../subset/verbs/methods/conjugate/faster.js'); - -//extend our current irregular conjugations, overwrite if exists -//also, map the irregulars for easy infinitive lookup - {bought: 'buy'} -const addConjugations = function(obj) { - - Object.keys(obj).forEach((inf) => { - this.conjugations[inf] = this.conjugations[inf] || {}; - //add it to the lexicon - this.words[inf] = this.words[inf] || 'Infinitive'; - Object.keys(obj[inf]).forEach((tag) => { - let word = obj[inf][tag]; - //add this to our conjugations - this.conjugations[inf][tag] = word; - //add it to the lexicon, too - this.words[word] = this.words[word] || tag; - //also denormalize to cache.toInfinitive - this.cache.toInfinitive[obj[inf][tag]] = inf; - }); - //guess the other conjugations - let forms = conjugate(inf, this); - Object.keys(forms).forEach((k) => { - let word = forms[k]; - if (this.words.hasOwnProperty(word) === false) { - this.words[word] = k; - } - }); - }); - return obj; -}; -module.exports = addConjugations; - -},{"../subset/verbs/methods/conjugate/faster.js":79}],210:[function(_dereq_,module,exports){ - -// -const addPatterns = function(obj) { - Object.keys(obj).forEach((k) => { - this.patterns[k] = obj[k]; - }); - return obj; -}; -module.exports = addPatterns; - -},{}],211:[function(_dereq_,module,exports){ -'use strict'; -//put singular->plurals in world, the reverse in cache, -//and both forms in the lexicon -const addPlurals = function(obj) { - Object.keys(obj).forEach((sing) => { - let plur = obj[sing]; - this.plurals[sing] = plur; - //add them both to the lexicon - this.words[plur] = this.words[plur] || 'Plural'; - this.words[sing] = this.words[sing] || 'Singular'; - //denormalize them in cache.toPlural - this.cache.toSingular[plur] = sing; - }); - return obj; -}; -module.exports = addPlurals; - -},{}],212:[function(_dereq_,module,exports){ - -// -const addRegex = function(obj) { - Object.keys(obj).forEach((k) => { - this.regex.push({ - reg: new RegExp(k, 'i'), - tag: obj[k] - }); - }); -}; -module.exports = addRegex; - -},{}],213:[function(_dereq_,module,exports){ -'use strict'; -//add 'downward' tags (that immediately depend on this one) -const addDownword = _dereq_('../tags/addDownward'); - -//extend our known tagset with these new ones -const addTags = function(tags) { - Object.keys(tags).forEach((tag) => { - let obj = tags[tag]; - obj.notA = obj.notA || []; - obj.downward = obj.downward || []; - this.tags[tag] = obj; - }); - addDownword(this.tags); - return tags; -}; -module.exports = addTags; - -},{"../tags/addDownward":135}],214:[function(_dereq_,module,exports){ -'use strict'; -const normalize = _dereq_('../term/methods/normalize/normalize').normalize; -const inflect = _dereq_('../subset/nouns/methods/pluralize'); -const conjugate = _dereq_('../subset/verbs/methods/conjugate/faster.js'); -const adjFns = _dereq_('../subset/adjectives/methods'); -const wordReg = / /; - - -const cleanUp = function(str) { - str = normalize(str); - //extra whitespace - str = str.replace(/\s+/, ' '); - //remove sentence-punctuaion too - str = str.replace(/[.\?,;\!]/g, ''); - return str; -}; - -// -const addWords = function(words) { - //go through each word - Object.keys(words).forEach((word) => { - let tag = words[word]; - word = cleanUp(word); - this.words[word] = tag; - //add it to multi-word cache, - if (wordReg.test(word) === true) { - let arr = word.split(wordReg); - this.cache.firstWords[arr[0]] = true; - } - - //turn singulars into plurals - if (tag === 'Singular') { - let plural = inflect(word, {}); - if (plural && plural !== word) { - this.words[plural] = 'Plural'; - } - return; - } - //turn infinitives into all conjugations - if (tag === 'Infinitive') { - let conj = conjugate(word, this); - Object.keys(conj).forEach((k) => { - this.words[conj[k]] = k; - }); - return; - } - //phrasals like 'pull out' get conjugated too - if (tag === 'PhrasalVerb') { - let arr = word.split(/ /); - let conj = conjugate(arr[0], this); - Object.keys(conj).forEach((k) => { - let form = conj[k] + ' ' + arr[1]; - this.words[form] = 'PhrasalVerb'; - //add it to cache, too - this.cache.firstWords[conj[k]] = true; - }); - return; - } - //turn some adjectives into superlatives - if (tag === 'Comparable') { - let comp = adjFns.toComparative(word); - if (comp && word !== comp) { - this.words[comp] = 'Comparative'; - } - let supr = adjFns.toSuperlative(word); - if (supr && word !== supr) { - this.words[supr] = 'Superlative'; - } - } - }); - - return words; -}; -module.exports = addWords; - -},{"../subset/adjectives/methods":11,"../subset/nouns/methods/pluralize":44,"../subset/verbs/methods/conjugate/faster.js":79,"../term/methods/normalize/normalize":149}],215:[function(_dereq_,module,exports){ -'use strict'; -// const addWords = require('./addWords'); -const fns = _dereq_('../fns'); -let data = _dereq_('./_data'); -let moreData = _dereq_('./more-data'); -let tags = _dereq_('../tags'); -let unpack = _dereq_('./unpack'); -let addTags = _dereq_('./addTags'); -let addWords = _dereq_('./addWords'); -let addRegex = _dereq_('./addRegex'); -let addConjugations = _dereq_('./addConjugations'); -let addPatterns = _dereq_('./addPatterns'); -let addPlurals = _dereq_('./addPlurals'); -let misc = _dereq_('./more-data/misc'); - -//lazier/faster object-merge -const extend = (main, obj) => { - let keys = Object.keys(obj); - for (let i = 0; i < keys.length; i++) { - main[keys[i]] = obj[keys[i]]; - } - return main; -}; - -//class World -let World = function() { - this.words = {}; - this.tags = tags; - this.regex = []; - this.patterns = {}; - this.conjugations = {}; - this.plurals = {}; - //denormalized data for faster-lookups - this.cache = { - firstWords: {}, - toInfinitive: {}, - toSingular: {} - }; -}; - -World.prototype.addTags = addTags; -World.prototype.addWords = addWords; -World.prototype.addRegex = addRegex; -World.prototype.addConjugations = addConjugations; -World.prototype.addPlurals = addPlurals; -World.prototype.addPatterns = addPatterns; - -//make a no-reference copy of all the data -World.prototype.clone = function() { - let w2 = new World(); - ['words', 'firstWords', 'tagset', 'regex', 'patterns', 'conjugations', 'plurals'].forEach((k) => { - if (this[k]) { - w2[k] = fns.copy(this[k]); - } - }); - return w2; -}; - -//add all the things, in all the places -World.prototype.plugin = function(obj) { - //untangle compromise-plugin - obj = unpack(obj); - //add all-the-things to this world object - //(order may matter) - if (obj.tags) { - this.addTags(obj.tags); - } - if (obj.regex) { - this.addRegex(obj.regex); - } - if (obj.patterns) { - this.addPatterns(obj.patterns); - } - if (obj.conjugations) { - this.addConjugations(obj.conjugations); - } - if (obj.plurals) { - this.addPlurals(obj.plurals); - } - if (obj.words) { - this.addWords(obj.words); - } -}; - -//export a default world -let w = new World(); -w.plugin(data); -w.addWords(misc); -moreData.forEach((obj) => { - extend(w.words, obj); -}); - -module.exports = { - w: w, - reBuild: function() { - //export a default world - let w2 = new World(); - w2.plugin(data); - w2.addWords(misc); - moreData.forEach((obj) => { - extend(w2.words, obj); - }); - return w2; - } -}; - -},{"../fns":3,"../tags":137,"./_data":208,"./addConjugations":209,"./addPatterns":210,"./addPlurals":211,"./addRegex":212,"./addTags":213,"./addWords":214,"./more-data":217,"./more-data/misc":219,"./unpack":223}],216:[function(_dereq_,module,exports){ -//these are common word shortenings used in the lexicon and sentence segmentation methods -//there are all nouns,or at the least, belong beside one. -"use strict"; - -//common abbreviations -let compact = { - Noun: [ - "arc", - "al", - "exp", - "fy", - "pd", - "pl", - "plz", - "tce", - "bl", - "ma", - "ba", - "lit", - "ex", - "eg", - "ie", - "ca", - "cca", - "vs", - "etc", - "esp", - "ft", - //these are too ambiguous - "bc", - "ad", - "md", - "corp", - "col" - ], - Organization: [ - "dept", - "univ", - "assn", - "bros", - "inc", - "ltd", - "co", - //proper nouns with exclamation marks - "yahoo", - "joomla", - "jeopardy" - ], - - Place: [ - "rd", - "st", - "dist", - "mt", - "ave", - "blvd", - "cl", - "ct", - "cres", - "hwy", - //states - "ariz", - "cal", - "calif", - "colo", - "conn", - "fla", - "fl", - "ga", - "ida", - "ia", - "kan", - "kans", - - "minn", - "neb", - "nebr", - "okla", - "penna", - "penn", - "pa", - "dak", - "tenn", - "tex", - "ut", - "vt", - "va", - "wis", - "wisc", - "wy", - "wyo", - "usafa", - "alta", - "ont", - "que", - "sask" - ], - - Month: [ - "jan", - "feb", - "mar", - "apr", - "jun", - "jul", - "aug", - "sep", - "sept", - "oct", - "nov", - "dec" - ], - Date: ["circa"], - - //Honorifics - Honorific: [ - "adj", - "adm", - "adv", - "asst", - "atty", - "bldg", - "brig", - "capt", - "cmdr", - "comdr", - "cpl", - "det", - "dr", - "esq", - "gen", - "gov", - "hon", - "jr", - "llb", - "lt", - "maj", - "messrs", - "mister", - "mlle", - "mme", - "mr", - "mrs", - "ms", - "mstr", - "op", - "ord", - "phd", - "prof", - "pvt", - "rep", - "reps", - "res", - "rev", - "sen", - "sens", - "sfc", - "sgt", - "sir", - "sr", - "supt", - "surg" - //miss - //misses - ], - Value: ["no"] -}; - -//unpack the compact terms into the misc lexicon.. -let abbreviations = {}; -const keys = Object.keys(compact); -for (let i = 0; i < keys.length; i++) { - const arr = compact[keys[i]]; - for (let i2 = 0; i2 < arr.length; i2++) { - abbreviations[arr[i2]] = [keys[i], "Abbreviation"]; - } -} -module.exports = abbreviations; - -},{}],217:[function(_dereq_,module,exports){ -module.exports = [ - _dereq_('./abbreviations'), - _dereq_('./irregularAdjectives').lexicon, - _dereq_('./numbers').lexicon, - _dereq_('./orgWords'), -]; - -},{"./abbreviations":216,"./irregularAdjectives":218,"./numbers":220,"./orgWords":221}],218:[function(_dereq_,module,exports){ -'use strict'; -//adjectives that have irregular conjugations to adverb, comparative, and superlative forms -const toAdverb = { - bad: 'badly', - best: 'best', - early: 'early', - fast: 'fast', - good: 'well', - hard: 'hard', - icy: 'icily', - idle: 'idly', - late: 'late', - latter: 'latter', - little: 'little', - long: 'long', - low: 'low', - male: 'manly', - public: 'publicly', - simple: 'simply', - single: 'singly', - special: 'especially', - straight: 'straight', - vague: 'vaguely', - well: 'well', - whole: 'wholly', - wrong: 'wrong' -}; - -const toComparative = { - grey: 'greyer', - gray: 'grayer', - green: 'greener', - yellow: 'yellower', - red: 'redder', - good: 'better', - well: 'better', - bad: 'worse', - sad: 'sadder', - big: 'bigger' -}; - -const toSuperlative = { - nice: 'nicest', - late: 'latest', - hard: 'hardest', - inner: 'innermost', - outer: 'outermost', - far: 'furthest', - worse: 'worst', - bad: 'worst', - good: 'best', - big: 'biggest', - large: 'largest' -}; - -const combine = function(lexicon, obj, tag) { - let keys = Object.keys(obj); - for (let i = 0; i < keys.length; i++) { - lexicon[keys[i]] = 'Comparable'; - if (lexicon[obj[keys[i]]] === undefined) { - lexicon[obj[keys[i]]] = tag; - } - } - return lexicon; -}; -let lexicon = combine({}, toSuperlative, 'Superlative'); -lexicon = combine(lexicon, toComparative, 'Comparative'); -lexicon = combine(lexicon, toAdverb, 'Adverb'); - -module.exports = { - lexicon: lexicon, - toAdverb: toAdverb, - toComparative: toComparative, - toSuperlative: toSuperlative -}; - -},{}],219:[function(_dereq_,module,exports){ -//words that can't be compressed, for whatever reason -module.exports = { - '20th century fox': 'Organization', - '3m': 'Organization', - '7 eleven': 'Organization', - '7-eleven': 'Organization', - g8: 'Organization', - 'motel 6': 'Organization', - vh1: 'Organization', - q1: 'Date', - q2: 'Date', - q3: 'Date', - q4: 'Date', - //misc - records: 'Plural', - '&': 'Conjunction', - was: ['Copula', 'PastTense'] -}; - -},{}],220:[function(_dereq_,module,exports){ -'use strict'; -const cardinal = { - ones: { - // 'a': 1, - zero: 0, - one: 1, - two: 2, - three: 3, - four: 4, - five: 5, - six: 6, - seven: 7, - eight: 8, - nine: 9 - }, - teens: { - ten: 10, - eleven: 11, - twelve: 12, - thirteen: 13, - fourteen: 14, - fifteen: 15, - sixteen: 16, - seventeen: 17, - eighteen: 18, - nineteen: 19 - }, - tens: { - twenty: 20, - thirty: 30, - forty: 40, - fourty: 40, //support typo - fifty: 50, - sixty: 60, - seventy: 70, - eighty: 80, - ninety: 90 - }, - multiples: { - hundred: 1e2, - thousand: 1e3, - // grand: 1e3, - million: 1e6, - billion: 1e9, - trillion: 1e12, - quadrillion: 1e15, - quintillion: 1e18, - sextillion: 1e21, - septillion: 1e24 - } -}; - -const ordinal = { - ones: { - zeroth: 0, - first: 1, - second: 2, - third: 3, - fourth: 4, - fifth: 5, - sixth: 6, - seventh: 7, - eighth: 8, - ninth: 9 - }, - teens: { - tenth: 10, - eleventh: 11, - twelfth: 12, - thirteenth: 13, - fourteenth: 14, - fifteenth: 15, - sixteenth: 16, - seventeenth: 17, - eighteenth: 18, - nineteenth: 19 - }, - tens: { - twentieth: 20, - thirtieth: 30, - fortieth: 40, - fourtieth: 40, //support typo - fiftieth: 50, - sixtieth: 60, - seventieth: 70, - eightieth: 80, - ninetieth: 90 - }, - multiples: { - hundredth: 1e2, - thousandth: 1e3, - millionth: 1e6, - billionth: 1e9, - trillionth: 1e12, - quadrillionth: 1e15, - quintillionth: 1e18, - sextillionth: 1e21, - septillionth: 1e24 - } -}; - -//used for the units -const prefixes = { - yotta: 1, - zetta: 1, - exa: 1, - peta: 1, - tera: 1, - giga: 1, - mega: 1, - kilo: 1, - hecto: 1, - deka: 1, - deci: 1, - centi: 1, - milli: 1, - micro: 1, - nano: 1, - pico: 1, - femto: 1, - atto: 1, - zepto: 1, - yocto: 1, - - square: 1, - cubic: 1, - quartic: 1 -}; - -//create an easy mapping between ordinal-cardinal -let toOrdinal = {}; -let toCardinal = {}; -let lexicon = {}; -Object.keys(ordinal).forEach(k => { - let ord = Object.keys(ordinal[k]); - let card = Object.keys(cardinal[k]); - for (let i = 0; i < card.length; i++) { - toOrdinal[card[i]] = ord[i]; - toCardinal[ord[i]] = card[i]; - lexicon[ord[i]] = ['Ordinal', 'TextValue']; - lexicon[card[i]] = ['Cardinal', 'TextValue']; - if (k === 'multiples') { - lexicon[ord[i]].push('Multiple'); - lexicon[card[i]].push('Multiple'); - } - } -}); - -module.exports = { - toOrdinal: toOrdinal, - toCardinal: toCardinal, - cardinal: cardinal, - ordinal: ordinal, - prefixes: prefixes, - lexicon: lexicon -}; - -},{}],221:[function(_dereq_,module,exports){ -//nouns that also signal the title of an unknown organization -//todo remove/normalize plural forms -const orgWords = [ - 'administration', - 'agence', - 'agences', - 'agencies', - 'agency', - 'airlines', - 'airways', - 'army', - 'assoc', - 'associates', - 'association', - 'assurance', - 'authority', - 'autorite', - 'aviation', - 'bank', - 'banque', - 'board', - 'boys', - 'brands', - 'brewery', - 'brotherhood', - 'brothers', - 'building society', - 'bureau', - 'cafe', - 'caisse', - 'capital', - 'care', - 'cathedral', - 'center', - 'central bank', - 'centre', - 'chemicals', - 'choir', - 'chronicle', - 'church', - 'circus', - 'clinic', - 'clinique', - 'club', - 'co', - 'coalition', - 'coffee', - 'collective', - 'college', - 'commission', - 'committee', - 'communications', - 'community', - 'company', - 'comprehensive', - 'computers', - 'confederation', - 'conference', - 'conseil', - 'consulting', - 'containers', - 'corporation', - 'corps', - 'corp', - 'council', - 'crew', - 'daily news', - 'data', - 'departement', - 'department', - 'department store', - 'departments', - 'design', - 'development', - 'directorate', - 'division', - 'drilling', - 'education', - 'eglise', - 'electric', - 'electricity', - 'energy', - 'ensemble', - 'enterprise', - 'enterprises', - 'entertainment', - 'estate', - 'etat', - 'evening news', - 'faculty', - 'federation', - 'financial', - 'fm', - 'foundation', - 'fund', - 'gas', - 'gazette', - 'girls', - 'government', - 'group', - 'guild', - 'health authority', - 'herald', - 'holdings', - 'hospital', - 'hotel', - 'hotels', - 'inc', - 'industries', - 'institut', - 'institute', - 'institute of technology', - 'institutes', - 'insurance', - 'international', - 'interstate', - 'investment', - 'investments', - 'investors', - 'journal', - 'laboratory', - 'labs', - // 'law', - 'liberation army', - 'limited', - 'local authority', - 'local health authority', - 'machines', - 'magazine', - 'management', - 'marine', - 'marketing', - 'markets', - 'media', - 'memorial', - 'mercantile exchange', - 'ministere', - 'ministry', - 'military', - 'mobile', - 'motor', - 'motors', - 'musee', - 'museum', - // 'network', - 'news', - 'news service', - 'observatory', - 'office', - 'oil', - 'optical', - 'orchestra', - 'organization', - 'partners', - 'partnership', - // 'party', - 'people\'s party', - 'petrol', - 'petroleum', - 'pharmacare', - 'pharmaceutical', - 'pharmaceuticals', - 'pizza', - 'plc', - 'police', - 'polytechnic', - 'post', - 'power', - 'press', - 'productions', - 'quartet', - 'radio', - 'regional authority', - 'regional health authority', - 'reserve', - 'resources', - 'restaurant', - 'restaurants', - 'savings', - 'school', - 'securities', - 'service', - 'services', - 'social club', - 'societe', - 'society', - 'sons', - 'standard', - 'state police', - 'state university', - 'stock exchange', - 'subcommittee', - 'syndicat', - 'systems', - 'telecommunications', - 'telegraph', - 'television', - 'times', - 'tribunal', - 'tv', - 'union', - 'university', - 'utilities', - 'workers' -]; - -module.exports = orgWords.reduce(function(h, str) { - h[str] = 'Noun'; - return h; -}, {}); - -},{}],222:[function(_dereq_,module,exports){ -'use strict'; -//supported verb forms: -const forms = [ - null, - 'PastTense', - 'PresentTense', - 'Gerund', - 'Participle', -]; -// -const unpackVerbs = function(str) { - let verbs = str.split('|'); - return verbs.reduce((h, s) => { - let parts = s.split(':'); - let prefix = parts[0]; - let ends = parts[1].split(','); - //grab the infinitive - let inf = prefix + ends[0]; - if (ends[0] === '_') { - inf = prefix; - } - h[inf] = {}; - //we did the infinitive, now do the rest: - for (let i = 1; i < forms.length; i++) { - let word = parts[0] + ends[i]; - if (ends[i] === '_') { - word = parts[0]; - } - if (ends[i]) { - h[inf][forms[i]] = word; - } - } - return h; - }, {}); -}; -module.exports = unpackVerbs; - -},{}],223:[function(_dereq_,module,exports){ -'use strict'; -const unpack = { - words: _dereq_('efrt-unpack'), - plurals: _dereq_('./plurals'), - conjugations: _dereq_('./conjugations'), - keyValue: _dereq_('./key-value') -}; -/* - == supported plugin fields == - name - words - efrt packed - tags - stringified - regex - key-value - patterns - key-value - plurals - plural-unpack - conjugations - conjugation-unpack -*/ - -const unpackPlugin = function(str) { - let obj = str; - if (typeof str === 'string') { - obj = JSON.parse(str); - } - //words is packed with efrt - if (obj.words && typeof obj.words === 'string') { - obj.words = unpack.words(obj.words); - } - //patterns is pivoted as key-value - if (obj.patterns) { - obj.patterns = unpack.keyValue(obj.patterns); - } - //regex, too - if (obj.regex) { - obj.regex = unpack.keyValue(obj.regex); - } - //plurals is packed in a ad-hoc way - if (obj.plurals && typeof obj.plurals === 'string') { - obj.plurals = unpack.plurals(obj.plurals); - } - //conjugations is packed in another ad-hoc way - if (obj.conjugations && typeof obj.conjugations === 'string') { - obj.conjugations = unpack.conjugations(obj.conjugations); - } - return obj; -}; -module.exports = unpackPlugin; - -},{"./conjugations":222,"./key-value":224,"./plurals":225,"efrt-unpack":1}],224:[function(_dereq_,module,exports){ -'use strict'; -//pivot k:[val,val] -> val:k, val:k -const keyValue = function(obj) { - let keys = Object.keys(obj); - let isCompressed = true; - if (keys[0] && typeof obj[keys[0]] === 'string') { - isCompressed = false; - } - return keys.reduce((h, k) => { - if (isCompressed === true) { - let arr = obj[k]; - arr.forEach((a) => { - if (h[a]) { - //convert val to an array - if (typeof h[a] === 'string') { - h[a] = [h[a]]; - } - //add it - h[a].push(k); - } else { - h[a] = k; - } - }); - } else { - h[k] = obj[k]; - } - return h; - }, {}); -}; -module.exports = keyValue; - -},{}],225:[function(_dereq_,module,exports){ -'use strict'; -const unpackPlurals = function(str) { - return str.split(/,/g).reduce((h, s) => { - let arr = s.split(/\|/g); - if (arr.length === 3) { - h[arr[0] + arr[1]] = arr[0] + arr[2]; - } else if (arr.length === 2) { - h[arr[0]] = arr[0] + arr[1]; - } else { - h[arr[0]] = arr[0]; - } - return h; - }, {}); -}; -module.exports = unpackPlurals; - -},{}]},{},[4])(4) -}); diff --git a/builds/compromise.es6.min.js b/builds/compromise.es6.min.js deleted file mode 100644 index c56da4ab2..000000000 --- a/builds/compromise.es6.min.js +++ /dev/null @@ -1,2 +0,0 @@ -(function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,t.nlp=e()}})(function(){var e=Math.floor,t;return function(){function s(l,e,n){function t(o,i){if(!e[o]){if(!l[o]){var d="function"==typeof require&&require;if(!i&&d)return d(o,!0);if(r)return r(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var a=e[o]={exports:{}};l[o][0].call(a.exports,function(e){var a=l[o][1][e];return t(a||e)},a,a.exports,s,l,e,n)}return e[o].exports}for(var r="function"==typeof require&&require,a=0;a=s;r-=s,n++,s*=36);for(;n--;){const t=r%36;e=String.fromCharCode((10>t?48:55)+t)+e,r=(r-t)/36}return e},fromAlphaCode:function(a){if(void 0!==s[a])return s[a];let n=0,i=1,e=36,o=1;for(;i{let r=a.nodes[e];"!"===r[0]&&(n.push(t),r=r.slice(1));const m=r.split(/([A-Z0-9,]+)/g);for(let r=0;r{const a=n.split("\xA6");return t[a[0]]=a[1],t},{}),s={};return Object.keys(a).forEach(function(e){const n=u(a[e]);"true"===e&&(e=!0);for(let t=0;t (http://spencermounta.in)",name:"compromise",description:"natural language processing in the browser",version:"11.14.3",main:"./builds/compromise.js",unpkg:"./builds/compromise.min.js",types:"types",repository:{type:"git",url:"git://github.com/nlp-compromise/compromise.git"},scripts:{test:"tape \"./test/unit/**/*.test.js\" | tap-dancer","test:spec":"tape \"./test/unit/**/*.test.js\" | tap-spec",testb:"TESTENV=prod tape \"./test/unit/**/*.test.js\" | tap-dancer",buildTest:"TESTENV=prod node ./scripts/test.js","test:types":"dtslint types",browserTest:"node ./scripts/browserTest.js",benchmark:"node ./scripts/benchmark.js",build:"node ./scripts/build/index.js",pack:"node ./scripts/pack.js",prepublishOnly:"node ./scripts/prepublish && npm run test:types",postpublish:"node ./scripts/postpublish",watch:"amble ./scratch.js",filesize:"node ./scripts/lib/filesize.js",coverage:"node ./scripts/postpublish/coverage.js",lint:"node ./scripts/prepublish/linter.js"},files:["builds/","docs/","types/index.d.ts"],prettier:{trailingComma:"none",tabWidth:2,semi:!0,singleQuote:!0,printWidth:100},dependencies:{"efrt-unpack":"2.2.0"},devDependencies:{"@babel/core":"7.5.5","@babel/preset-env":"7.5.5",amble:"0.0.7",babelify:"10.0.0",babili:"0.1.4",browserify:"16.5.0",chalk:"2.4.2",codecov:"3.5.0","compromise-plugin":"0.0.9",derequire:"2.0.6",dtslint:"0.9.3",nyc:"14.1.1",shelljs:"0.8.3","tap-dancer":"0.2.0",tape:"4.11.0",terser:"4.2.1"},license:"MIT"}},{}],3:[function(e,t,n){"use strict";const a=e("./tags"),r={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",black:"\x1B[30m"};"undefined"==typeof t&&Object.keys(r).forEach((e)=>{r[e]=""}),n.ensureString=(e)=>{if("string"==typeof e)return e;return"number"==typeof e?e+"":""},n.ensureObject=(e)=>{return"object"==typeof e?null===e||e instanceof Array?{}:e:{}},n.titleCase=(e)=>{return e.charAt(0).toUpperCase()+e.substr(1)},n.copy=(e)=>{let t={};return e=n.ensureObject(e),Object.keys(e).forEach((n)=>{t[n]=e[n]}),t},n.extend=(e,t)=>{e=n.copy(e);const a=Object.keys(t);for(let n=0;n{t["add"+n]=function(t){e["add"+n](t)}}),t},"undefined"==typeof self?"undefined"==typeof window?"undefined"!=typeof a&&(a.nlp=u):window.nlp=u:self.nlp=u,"function"==typeof t&&t.amd&&t(u),"undefined"!=typeof n&&(n.exports=u)}).call(this,"undefined"==typeof global?"undefined"==typeof self?"undefined"==typeof window?{}:window:self:global)},{"../package.json":2,"./log":6,"./text/build":190,"./world":215,"./world/unpack":223}],5:[function(e,t){"use strict";const n=e("../fns");t.exports={tag:(e,t,a)=>{let r=e.normal||"["+e.silent_term+"]";r=n.leftPad("'"+r+"'",12),r+=" -> "+t,r+=n.leftPad(a||"",15),console.log("%c"+r," color: #a2c99c")},untag:(e,t,a)=>{let r=e.normal||"["+e.silent_term+"]";r=n.leftPad("'"+r+"'",12),r+=" ~* "+t,r+=" "+(a||""),console.log("%c"+r," color: #b66a6a")}}},{"../fns":3}],6:[function(e,t){"use strict";const n=e("./client"),a=e("./server");let r=!1;t.exports={enable:(e)=>{e===void 0&&(e=!0),r=e},tag:(e,t,s)=>{(!0===r||"tagger"===r)&&("undefined"==typeof window?a.tag(e,t,s):n.tag(e,t,s))},unTag:(e,t,s)=>{(!0===r||"tagger"===r)&&("undefined"==typeof window?a.untag(e,t,s):n.untag(e,t,s))}}},{"./client":5,"./server":7}],7:[function(e,t){"use strict";const n=e("../fns");t.exports={tag:(e,t,a)=>{let r=e.normal||"["+e.silent_term+"]";r=n.yellow(r),r=n.leftPad("'"+r+"'",20),r+=" -> "+n.printTag(t),r=n.leftPad(r,54),console.log(" "+r+"("+n.cyan(a||"")+")")},untag:function(e,t,a){let r="-"+e.normal+"-";r=n.red(r),r=n.leftPad(r,20),r+=" ~* "+n.red(t),r=n.leftPad(r,54),console.log(" "+r+"("+n.red(a||"")+")")}}},{"../fns":3}],8:[function(e,t){t.exports={fns:e("./fns"),Terms:e("./terms")}},{"./fns":3,"./terms":165}],9:[function(e,t){"use strict";const n=e("../../text");t.exports=n.makeSubset({stripPeriods:function(){return this.list.forEach((e)=>{e.terms.forEach((e)=>{let t=e._text.split(".");2{e.terms.forEach((e)=>{let t=e._text.split(".");if(2{let n=e.terms[0],t=n.text.toUpperCase().replace(/\./g,"").split("");return{periods:t.join("."),normal:t.join(""),text:n.text}})}},function(e,t){return e=e.match("#Acronym"),"number"==typeof t&&(e=e.get(t)),e})},{"../../text":192}],10:[function(e,t){"use strict";const n=e("../../text"),a=e("./methods"),r=function(e,t){return!e||3>=e.length?!1:!("Comparable"!==t[e])||"Adjective"!==t[e]&&!(-1!==e.indexOf(" "))};t.exports=n.makeSubset({data:function(){return this.list.map((e)=>{const t=e.out("normal");let n={normal:t,text:this.out("text"),comparative:"more "+t,superlative:"most "+t,adverbForm:null,nounForm:null};return!0===r(t,this.world().words)&&(n.comparative=a.toComparative(t)||n.comparative,n.superlative=a.toSuperlative(t)||n.superlative,n.adverbForm=a.toAdverb(t),n.nounForm=a.toNoun(t)),n})}},function(e,t){return e=e.match("#Adjective"),"number"==typeof t&&(e=e.get(t)),e})},{"../../text":192,"./methods":11}],11:[function(e,t){"use strict";t.exports={toNoun:e("./toNoun"),toSuperlative:e("./toSuperlative"),toComparative:e("./toComparative"),toAdverb:e("./toAdverb"),toVerb:e("./toVerb")}},{"./toAdverb":12,"./toComparative":13,"./toNoun":14,"./toSuperlative":15,"./toVerb":16}],12:[function(e,t){"use strict";const n=[/airs$/,/ll$/,/ee.$/,/ile$/,/y$/],a=e("../../../world/more-data/irregularAdjectives").toAdverb,r=[{reg:/al$/i,repl:"ally"},{reg:/ly$/i,repl:"ly"},{reg:/(.{3})y$/i,repl:"$1ily"},{reg:/que$/i,repl:"quely"},{reg:/ue$/i,repl:"uly"},{reg:/ic$/i,repl:"ically"},{reg:/ble$/i,repl:"bly"},{reg:/l$/i,repl:"ly"}];t.exports=function(e){if(!0===a.hasOwnProperty(e))return a[e];for(let t=0;t{return!0===n.hasOwnProperty(e)?n[e]:!0===/e$/.test(e)?e+"n":e+"en"}},{}],17:[function(e,t){"use strict";const n=e("../../text"),a=e("./toAdjective");t.exports=n.makeSubset({data:function(){return this.terms().list.map((e)=>{let n=e.terms[0];return{adjectiveForm:a(n.normal),normal:n.normal,text:n.text}})}},function(e,t){return e=e.splitAfter("#Comma"),e=e.match("#Adverb+"),"number"==typeof t&&(e=e.get(t)),e})},{"../../text":192,"./toAdjective":18}],18:[function(e,t){"use strict";const n={idly:"idle",sporadically:"sporadic",basically:"basic",grammatically:"grammatical",alphabetically:"alphabetical",economically:"economical",conically:"conical",politically:"political",vertically:"vertical",practically:"practical",theoretically:"theoretical",critically:"critical",fantastically:"fantastic",mystically:"mystical",pornographically:"pornographic",fully:"full",jolly:"jolly",wholly:"whole"},a=[{reg:/bly$/i,repl:"ble"},{reg:/gically$/i,repl:"gical"},{reg:/([rsdh])ically$/i,repl:"$1ical"},{reg:/ically$/i,repl:"ic"},{reg:/uly$/i,repl:"ue"},{reg:/ily$/i,repl:"y"},{reg:/(.{3})ly$/i,repl:"$1"}];t.exports=function(e){if(n.hasOwnProperty(e))return n[e];for(let t=0;t{t.whitespace.after=e.whitespace.after,e.whitespace.after="",t.whitespace.before="",e.silent_term=e.text,t.silent_term=t.text,t.text="",e.tag("Contraction","new-contraction"),t.tag("Contraction","new-contraction")},a={can:"can't",will:"won't"};t.exports=function(e){return!1===e.expanded||e.match("#Contraction").found?e:(e.match("(#Noun|#QuestionWord) is").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'s",e.contracted=!0}),e.match("#PronNoun did").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'d",e.contracted=!0}),e.match("#QuestionWord (did|do)").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'d",e.contracted=!0}),e.match("#Noun (could|would)").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'d",e.contracted=!0}),e.match("(they|we|you) are").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'re",e.contracted=!0}),e.match("i am").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'m",e.contracted=!0}),e.match("(#Noun|#QuestionWord) will").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'ll",e.contracted=!0}),e.match("(they|we|you|i) have").list.forEach((e)=>{n(e.terms[0],e.terms[1]),e.terms[0].text+="'ve",e.contracted=!0}),e.match("(#Copula|#Modal|do|does|have|has|can|will) not").list.forEach((e)=>{n(e.terms[0],e.terms[1]),!0===a.hasOwnProperty(e.terms[0].text)?e.terms[0].text=a[e.terms[0].text]:e.terms[0].text+="n't",e.contracted=!0}),e)}},{}],20:[function(e,t){"use strict";const n=e("../../paths").Terms,a=e("./contract"),r=e("./expand"),s=function(e,t,a){n.call(this,e,t,a)};s.prototype=Object.create(n.prototype),s.prototype.data=function(){let e=r(this.clone()),t=a(this.clone());return{text:this.out("text"),normal:this.out("normal"),expanded:{normal:e.out("normal"),text:e.out("text")},contracted:{normal:t.out("normal"),text:t.out("text")},isContracted:!!this.contracted}},s.prototype.expand=function(){return r(this)},s.prototype.contract=function(){return a(this)},t.exports=s},{"../../paths":8,"./contract":19,"./expand":21}],21:[function(e,t){"use strict";t.exports=function(e){return!1===e.contracted?e:(e.terms.forEach((e)=>{e.silent_term&&(!e.text&&(e.whitespace.before=" "),e._text=e.silent_term,e.tags.TitleCase&&e.toTitleCase(),e.normalize(),e.silent_term=null,e.unTag("Contraction","expanded"))}),e)}},{}],22:[function(e,t){"use strict";t.exports=(e)=>{let t=e.not("#Contraction"),n=t.match("(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)");return n.concat(t.match("(they|we|you|i) have")),n.concat(t.match("i am")),n.concat(t.match("(#Copula|#Modal|do|does|have|has|can|will) not")),n.list.forEach((e)=>{e.expanded=!0}),n}},{}],23:[function(e,t){"use strict";const n=e("../../text"),a=e("./contraction"),s=e("./findPossible");t.exports=n.makeSubset({contract:function(){return this.list.forEach((e)=>e.contract()),this},expand:function(){return this.list.forEach((e)=>e.expand()),this},contracted:function(){return this.list=this.list.filter((e)=>{return e.contracted}),this},expanded:function(){return this.list=this.list.filter((e)=>{return!e.contracted}),this}},function(e,t){let r=e.match("#Contraction #Contraction #Contraction?");r.list=r.list.map((e)=>{let t=new a(e.terms,e.world,e.refText,e.refTerms);return t.contracted=!0,t});let i=s(e);return i.list.forEach((e)=>{let t=new a(e.terms,e.world,e.refText,e.refTerms);t.contracted=!1,r.list.push(t)}),r.sort("chronological"),"number"==typeof t&&(r=r.get(t)),r})},{"../../text":192,"./contraction":20,"./findPossible":22}],24:[function(e,t){"use strict";const n=e("../../paths").Terms,a=e("./parseDate"),r=function(e,t,a){n.call(this,e,t,a),this.month=this.match("#Month")};r.prototype=Object.create(n.prototype),r.prototype.data=function(){return{text:this.out("text"),normal:this.out("normal"),date:a(this)}},t.exports=r},{"../../paths":8,"./parseDate":28}],25:[function(e,t){"use strict";const n=e("../../text"),a=e("./date"),r=e("./weekday"),s=e("./month");t.exports=n.makeSubset({toShortForm:function(){return this.match("#Month").terms().list.forEach((e)=>{let n=e.terms[0];s.toShortForm(n)}),this.match("#WeekDay").terms().list.forEach((e)=>{let n=e.terms[0];r.toShortForm(n)}),this},toLongForm:function(){return this.match("#Month").terms().list.forEach((e)=>{let n=e.terms[0];s.toLongForm(n)}),this.match("#WeekDay").terms().list.forEach((e)=>{let n=e.terms[0];r.toLongForm(n)}),this}},function(e,t){let r=e.match("#Date+");return"number"==typeof t&&(r=r.get(t)),r.list=r.list.map((e)=>{return new a(e.terms,e.world,e.refText,e.refTerms)}),r})},{"../../text":192,"./date":24,"./month":27,"./weekday":31}],26:[function(e,t,n){n.longMonths={january:0,february:1,march:2,april:3,may:4,june:5,july:6,august:7,september:8,october:9,november:10,december:11},n.shortMonths={jan:0,feb:1,mar:2,apr:3,may:4,jun:5,jul:6,aug:7,sep:8,oct:9,nov:10,dec:11,febr:1,sept:8}},{}],27:[function(e,t){"use strict";const n=e("./data"),a=n.shortMonths,r=n.longMonths,s=(e)=>{return e.charAt(0).toUpperCase()+e.substr(1)};t.exports={index:function(e){if(e.tags.Month){if(r[e.normal]!==void 0)return r[e.normal];if(void 0!==a[e.normal])return a[e.normal]}return null},toShortForm:function(e){if(void 0!==e.tags.Month&&void 0!==r[e.normal]){let t=Object.keys(a),n=e.getPunctuation()||"";e.text=t[r[e.normal]]+n,e.tags.TitleCase&&(e.text=s(e.text))}return e.dirty=!0,e},toLongForm:function(e){if(void 0!==e.tags.Month&&void 0!==a[e.normal]){let t=Object.keys(r),n=e.getPunctuation()||"";e.text=t[a[e.normal]]+n,e.tags.TitleCase&&(e.text=s(e.text))}return e.dirty=!0,e}}},{"./data":26}],28:[function(e,t){"use strict";const n=e("./parseTime"),a=e("./weekday"),s=e("./month"),i=(e)=>{return e&&31>e&&0{return e&&1e3e};t.exports=(e)=>{let t={month:null,date:null,weekday:null,year:null,named:null,time:null},r=e.match("(#Holiday|today|tomorrow|yesterday)");if(r.found&&(t.named=r.out("normal")),r=e.match("#Month"),r.found&&(t.month=s.index(r.list[0].terms[0])),r=e.match("#WeekDay"),r.found&&(t.weekday=a.index(r.list[0].terms[0])),r=e.match("#Time"),r.found&&(t.time=n(e),e.not("#Time")),r=e.match("#Month #Value #Year"),r.found){let n=r.values().numbers();i(n[0])&&(t.date=n[0]);let a=parseInt(e.match("#Year").out("normal"),10);o(a)&&(t.year=a)}if(!r.found){if(r=e.match("#Month #Value"),r.found){let e=r.values().numbers(),n=e[0];i(n)&&(t.date=n)}if(r=e.match("#Month #Year"),r.found){let n=parseInt(e.match("#Year").out("normal"),10);o(n)&&(t.year=n)}}if(r=e.match("#Value of #Month"),r.found){let e=r.values().numbers()[0];i(e)&&(t.date=e)}return t}},{"./month":27,"./parseTime":29,"./weekday":31}],29:[function(e,t){"use strict";const n=/([12]?[0-9]) ?(am|pm)/i,a=/([12]?[0-9]):([0-9][0-9]) ?(am|pm)?/i,r=(e)=>{return e&&0e},s=(e)=>{return e&&0e};t.exports=(e)=>{let i={logic:null,hour:null,minute:null,second:null,timezone:null},t=e.match("(by|before|for|during|at|until|after) #Time").firstTerm();t.found&&(i.logic=t.out("normal"));let o=e.match("#Time");return o.terms().list.forEach((e)=>{let o=e.terms[0],t=o.text.match(n);null!==t&&(i.hour=parseInt(t[1],10),"pm"===t[2]&&(i.hour+=12),!1===r(i.hour)&&(i.hour=null)),t=o.text.match(a),null!==t&&(i.hour=parseInt(t[1],10),i.minute=parseInt(t[2],10),!s(i.minute)&&(i.minute=null),"pm"===t[3]&&(i.hour+=12),!1===r(i.hour)&&(i.hour=null))}),i}},{}],30:[function(e,t,n){n.longDays={sunday:0,monday:1,tuesday:2,wednesday:3,thursday:4,friday:5,saturday:6},n.shortDays={sun:0,mon:1,tues:2,wed:3,weds:3,thurs:4,fri:5,sat:6}},{}],31:[function(e,t){"use strict";const n=e("./data"),a=n.shortDays,r=n.longDays;t.exports={index:function(e){if(e.tags.WeekDay){if(r[e.normal]!==void 0)return r[e.normal];if(void 0!==a[e.normal])return a[e.normal]}return null},toShortForm:function(e){if(e.tags.WeekDay&&void 0!==r[e.normal]){let t=Object.keys(a);e.text=t[r[e.normal]]}return e},toLongForm:function(e){if(e.tags.WeekDay&&void 0!==a[e.normal]){let t=Object.keys(r);e.text=t[a[e.normal]]}return e}}},{"./data":30}],32:[function(e,t){"use strict";const n=e("./index"),a=e("./getGrams"),s=function(e,t,a){n.call(this,e,t,a)};s.prototype=Object.create(n.prototype),s.find=function(e,t,r){let i={size:[1,2,3,4],edge:"end"};r&&(i.size=[r]);let o=a(e,i);return e=new s(o),e.sort(),"number"==typeof t&&(e=e.get(t)),e},t.exports=s},{"./getGrams":33,"./index":35}],33:[function(e,t){"use strict";const a=e("./gram"),r=function(e){return e=e.terms.filter((e)=>""!==e._text)},n=function(e,t){let n=r(e);if(n.length{e.list.forEach((e)=>{let o=[];o="start"===t.edge?s(e,r):"end"===t.edge?i(e,r):n(e,r),o.forEach((e)=>{a.hasOwnProperty(e.key)?a[e.key].inc():a[e.key]=e})})});let r=Object.keys(a).map((e)=>a[e]);return r}},{"./gram":34}],34:[function(e,t){"use strict";const n=e("../../paths").Terms,a=function(e,t,a){n.call(this,e,t,a),this.key=this.out("normal"),this.size=e.length,this.count=1};a.prototype=Object.create(n.prototype),a.prototype.inc=function(){this.count+=1},t.exports=a},{"../../paths":8}],35:[function(e,t){"use strict";const n=e("../../text"),a=e("./getGrams"),s=function(e){return e.list=e.list.sort((e,t)=>{return e.count>t.count?-1:e.count===t.count&&(e.size>t.size||e.key.length>t.key.length)?-1:1}),e};t.exports=n.makeSubset({data:function(){return this.list.map((e)=>{return{normal:e.out("normal"),count:e.count,size:e.size}})},unigrams:function(){return this.list=this.list.filter((e)=>1===e.size),this},bigrams:function(){return this.list=this.list.filter((e)=>2===e.size),this},trigrams:function(){return this.list=this.list.filter((e)=>3===e.size),this},sort:function(){return s(this)}},function(e,t){let r=[];"number"==typeof t&&(t={n:t}),t=t||{};let o=t.max||4;for(let n=1;n<=o;n++)r.push(n);t.size&&(r=[t.size]);let i={size:r},l=a(e,i);return e=new n(l),e=s(e),void 0!==t.n&&(e=e.get(t.n)),e})},{"../../text":192,"./getGrams":33}],36:[function(e,t){"use strict";const n=e("./index"),a=e("./getGrams"),s=function(e,t,a){n.call(this,e,t,a)};s.prototype=Object.create(n.prototype),s.find=function(e,t,r){let i={size:[1,2,3,4],edge:"start"};r&&(i.size=[r]);let o=a(e,i);return e=new s(o),e.sort(),"number"==typeof t&&(e=e.get(t)),e},t.exports=s},{"./getGrams":33,"./index":35}],37:[function(e,t){"use strict";t.exports=function(e){if(!e.tags.Noun)return!1;if(e.tags.Plural)return!0;const t=["Pronoun","Place","Value","Person","Month","WeekDay","RelativeDay","Holiday"];for(let n=0;ne.isPlural()),this},hasPlural:function(){return this.list.map((e)=>e.hasPlural())},toPlural:function(){return this.list.forEach((e)=>e.toPlural()),this},toSingular:function(e){return this.list.forEach((t)=>t.toSingular(e)),this},toPossessive:function(e){return this.list.forEach((t)=>t.toPossessive(e)),this},articles:function(){return this.list.map((e)=>{return{text:e.out("text"),normal:e.out("normal"),article:e.article()}})}},function(e,t){return e=e.clauses(),e=e.match("#Noun+ (of|by)? the? #Noun+?"),e=e.not("#Pronoun"),e=e.not("(there|these)"),e=e.not("(#Month|#WeekDay)"),e=e.not("(my|our|your|their|her|his)"),e=e.not("(of|for|by|the)$"),"number"==typeof t&&(e=e.get(t)),e.list=e.list.map((e)=>{return new a(e.terms,e.world,e.refText,e.refTerms)}),e})},{"../../text":192,"./noun":46}],39:[function(e,t){"use strict";const n=e("./methods/data/indicators"),a=/([a-z]*) (of|in|by|for) [a-z]/,r=e("./hasPlural"),s={i:!1,he:!1,she:!1,we:!0,they:!0},o=["Place","Value","Person","Month","WeekDay","RelativeDay","Holiday","Possessive"],i=function(e){if(!1===r(e))return!1;for(let t=0;t{u.prototype[e]=d[e]}),t.exports=u},{"../../paths":8,"./hasPlural":37,"./isPlural":39,"./makeArticle":40,"./methods/pluralize":44,"./methods/singularize":45,"./toPossessive":47}],47:[function(e,t){const n={he:"his",she:"hers",they:"theirs",we:"ours",i:"mine",you:"yours",her:"hers",their:"theirs",our:"ours",my:"mine",your:"yours"};t.exports=function(e){return(e.tag("Possessive","toPossessive"),n.hasOwnProperty(e.normal))?(e.text=n[e.normal],e):/s$/.test(e.normal)?(e.text+="'",e):(e.text+="'s",e)}},{}],48:[function(e,t){"use strict";t.exports=function(e){return e?!0===/.(i|ee|[a|e]y|a)$/.test(e)?"Female":!0===/[ou]$/.test(e)?"Male":!0===/(nn|ll|tt)/.test(e)?"Female":null:null}},{}],49:[function(e,t){"use strict";const n=e("../../text"),a=e("./person");t.exports=n.makeSubset({pronoun:function(){return this.list.map((e)=>e.pronoun())},firstNames:function(){return this.match("#FirstName")},lastNames:function(){return this.match("#LastName")}},function(e,t){let r=e.clauses();return r=r.match("#Person+"),"number"==typeof t&&(r=r.get(t)),r.list=r.list.map((e)=>{return new a(e.terms,e.world,e.refText,e.refTerms)}),r})},{"../../text":192,"./person":50}],50:[function(e,t){"use strict";const n=e("../../paths").Terms,a=e("./guessGender"),r=function(e,t,a,r){if(n.call(this,e,t,a,r),this.firstName=this.match("#FirstName+"),this.middleName=this.match("#Acronym+"),this.nickName=this.match("#NickName+"),this.honorifics=this.match("#Honorific"),this.lastName=this.match("#LastName+"),!this.firstName.found&&1{r.prototype[e]=s[e]}),t.exports=r},{"../../paths":8,"./guessGender":48}],51:[function(e,t){"use strict";const n=e("../../text"),a={strip(){return this.list.forEach((e)=>{let n=e.terms[e.terms.length-1];n.text=n.text.replace(/'s$/,""),n.unTag("Possessive",".strip()")}),this}};t.exports=n.makeSubset(a,function(e,t){return e=e.match("#Possessive+"),e=e.splitAfter("#Comma"),"number"==typeof t&&(e=e.get(t)),e})},{"../../text":192}],52:[function(e,t){"use strict";const n=e("../../text"),a=e("./sentence");t.exports=n.makeSubset({toPastTense:function(){return this.list=this.list.map((e)=>{return e=e.toPastTense(),new a(e.terms,e.world,e.refText,e.refTerms)}),this},toPresentTense:function(){return this.list=this.list.map((e)=>{return e=e.toPresentTense(),new a(e.terms,e.world,e.refText,e.refTerms)}),this},toFutureTense:function(){return this.list=this.list.map((e)=>{return e=e.toFutureTense(),new a(e.terms,e.world,e.refText,e.refTerms)}),this},toContinuous:function(){return this.list=this.list.map((e)=>{return e=e.toContinuous(),new a(e.terms,e.world,e.refText,e.refTerms)}),this},toNegative:function(){return this.list=this.list.map((e)=>{return e=e.toNegative(),new a(e.terms,e.world,e.refText,e.refTerms)}),this},toPositive:function(){return this.list=this.list.map((e)=>{return e=e.toPositive(),new a(e.terms,e.world,e.refText,e.refTerms)}),this},isPassive:function(){return this.list=this.list.filter((e)=>{return e.isPassive()}),this},isQuestion:function(){return this.questions()},prepend:function(e){return this.list=this.list.map((t)=>{return t.prepend(e)}),this},append:function(e){return this.list=this.list.map((t)=>{return t.append(e)}),this},toExclamation:function(){return this.list.forEach((e)=>{e.setPunctuation("!")}),this},toQuestion:function(){return this.list.forEach((e)=>{e.setPunctuation("?")}),this},toStatement:function(){return this.list.forEach((e)=>{e.setPunctuation(".")}),this}},function(e,t){return e=e.all(),"number"==typeof t&&(e=e.get(t)),e.list=e.list.map((e)=>{return new a(e.terms,e.world,e.refText,e.refTerms)}),e})},{"../../text":192,"./sentence":54}],53:[function(e,t){"use strict";t.exports=function(e){let t=e.getPunctuation(),n=e.match("*").splitAfter("#Comma");return!(!0!==/\?/.test(t))||!/\.\.$/.test(e.out("text"))&&(e.has("^#QuestionWord")&&e.has("#Comma")?!1:!!e.has("^#QuestionWord")||!!e.has("^(do|does|did|is|was|can|could|will|would|may) #Noun")||!!e.has("^(have|must) you")||!!n.has("^#QuestionWord")||!!n.has("(do|does|is|was) #Noun+ #Adverb? (#Adjective|#Infinitive)$"))}},{}],54:[function(e,t){"use strict";const n=e("../../paths").Terms,a=e("./toNegative"),r=e("./toPositive"),i=e("../verbs/verb"),s=e("./smartInsert"),o=function(e){let t=e.match("#Condition"),n=e.not("#Condition"),a=n.match("#VerbPhrase+").first(),r=a.out("normal"),s=n.match("#Determiner? #Adjective+? #Noun "+r).first().not("#VerbPhrase"),o=n.match(r+" #Preposition? #Determiner? #Noun").first().not("#VerbPhrase");return e.conditions=t,e.subject=s,e.verb=a,e.object=o,e.verb.found&&(e.verb=new i(e.verb.list[0].terms,e.world,e.refText,e.refTerms)),e},l=function(e){e.found&&e.contractions().expand()},d=function(e){e.terms=e.terms.filter((e)=>{if(e.silent_term){if("am"===e.silent_term||"will"===e.silent_term||"did"===e.silent_term)return!1;e.text=e.silent_term,e.silent_term=null,e.unTag("Contraction"),!0===e.tags.TitleCase&&e.toTitleCase()}return!0})},u=function(e){return e.subject.found&&e.subject.has("(i|we)")},m={toSingular:function(){let e=this.match("#Noun").match("!#Pronoun").firstTerm();return e.things().toSingular(),this},toPlural:function(){let e=this.match("#Noun").match("!#Pronoun").firstTerm();return e.things().toPlural(),this},mainVerb:function(){return o(this),this.verb.found?this.verb:null},toPastTense:function(){let e=this.mainVerb();if(e){let t=e.out("root");e.toPastTense();let n=this.match("#Contraction "+t);l(n);let a=e.out("root"),s=this.parentTerms.replace(t,a);return s}return this},toPresentTense:function(){let e=this.mainVerb();if(e){let t=e.out("normal");if(!0===u(this))this.has("(am|will|did) "+t)&&d(this),e.toInfinitive();else{e.toPresentTense();let n=this.match("#Contraction "+t);l(n)}let n=e.out("normal");return this.parentTerms.replace(t,n)}return this},toFutureTense:function(){let e=this.mainVerb();if(e){let t=e.clone();e.toFutureTense();let n=this.match("#Contraction "+t.out("normal"));l(n);let a=e.out("normal");return this.parentTerms.replace(t,a)}return this},toContinuous:function(){let e=this.mainVerb();if(e){let t=e.clone();e.toGerund();let n=this.match("#Contraction "+t.out("normal"));l(n);let a=e.out("normal");return this.parentTerms.replace(t,a)}return this},isNegative:function(){return 1===this.match("#Negative").list.length},toNegative:function(){return this.isNegative()?this:a(this)},toPositive:function(){return this.isNegative()?r(this):this},append:function(e){return s.append(this,e)},prepend:function(e){return s.prepend(this,e)},isPassive:function(){return this.match("was #Adverb? #PastTense #Adverb? by").found}},c=function(e,t,a,r){n.call(this,e,t,a,r),o(this)};c.prototype=Object.create(n.prototype),Object.keys(m).forEach((e)=>{c.prototype[e]=m[e]}),t.exports=c},{"../../paths":8,"../verbs/verb":94,"./smartInsert":55,"./toNegative":56,"./toPositive":57}],55:[function(e,t){"use strict";const n=/^[A-Z]/;t.exports={append:(e,t)=>{let n=e.terms[e.terms.length-1],a=e.getPunctuation();a&&n.killPunctuation(),e.insertAt(e.terms.length,t);let r=e.terms[e.terms.length-1];return a&&(r.text+=a),n.whitespace.after&&(r.whitespace.after=n.whitespace.after,n.whitespace.after=""),e},prepend:(e,t)=>{let a=e.terms[0];if(e.insertAt(0,t),n.test(a.text)){!1===a.needsTitleCase()&&a.toLowerCase();let t=e.terms[0];t.toTitleCase()}return e}}},{}],56:[function(e,t){"use strict";const n={everyone:"no one",everybody:"nobody",someone:"no one",somebody:"nobody",always:"never"};t.exports=(e)=>{let t=e.match("(everyone|everybody|someone|somebody|always)").first();if(t.found&&n[t.out("normal")]){let a=t.out("normal");return e=e.match(a).replaceWith(n[a]).list[0],e.parentTerms}let a=e.mainVerb();return a&&a.toNegative(),e}},{}],57:[function(e,t){"use strict";const n={never:"always",nothing:"everything"};t.exports=(e)=>{let t=e.match("(never|nothing)").first();if(t.found){let a=t.out("normal");if(n[a])return e=e.match(a).replaceWith(n[a],!0).list[0],e.parentTerms}return e.delete("#Negative"),e}},{}],58:[function(e,t){"use strict";const a=e("../../text"),n=e("../../paths").Terms;t.exports=a.makeSubset({data:function(){return this.list.map((e)=>{let n=e.terms[0];return{spaceBefore:n.whitespace.before,text:n.text,spaceAfter:n.whitespace.after,normal:n.normal,implicit:n.silent_term,bestTag:n.bestTag(),tags:Object.keys(n.tags)}})}},function(e,t){let r=[];return e.list.forEach((a)=>{a.terms.forEach((s)=>{r.push(new n([s],a.world,e))})}),e=new a(r,e.world,e.parent),"number"==typeof t&&(e=e.get(t)),e})},{"../../paths":8,"../../text":192}],59:[function(e,t){const n=e("./numOrdinal"),a=e("./textOrdinal"),r=e("./textCardinal"),s=e("./niceNumber");t.exports={nice:function(e){return s(e)},ordinal:function(e){return n(e)},cardinal:function(e){return e+""},niceOrdinal:function(e){return e=n(e),e=s(e),e},text:function(e){return r(e).join(" ")},textOrdinal:function(e){return a(e)}}},{"./niceNumber":60,"./numOrdinal":61,"./textCardinal":62,"./textOrdinal":63}],60:[function(e,t){"use strict";t.exports=function(e){if(!e&&0!==e)return null;e=e+"";let t=e.split("."),n=t[0],a=1t)return e+"th";const a={0:"th",1:"st",2:"nd",3:"rd"};let r=n(e),s=r.slice(r.length-1,r.length);return r+=a[s]?a[s]:"th",r}},{"./toString":64}],62:[function(t,n){"use strict";const a=t("./toString"),r=[["ninety",90],["eighty",80],["seventy",70],["sixty",60],["fifty",50],["forty",40],["thirty",30],["twenty",20]],s=["","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],i=[[1e+24,"septillion"],[1e+21,"sextillion"],[1000000000000000000,"quintillion"],[1000000000000000,"quadrillion"],[1000000000000,"trillion"],[1000000000,"billion"],[100000000,"hundred million"],[1000000,"million"],[100000,"hundred thousand"],[1000,"thousand"],[100,"hundred"],[1,"one"]],o=function(t){let n=t,r=[];return i.forEach((s)=>{if(t>=s[0]){let t=e(n/s[0]);n-=t*s[0],t&&r.push({unit:s[1],count:t})}}),r},l=function(e){let t=[];if(100=r[n][1]&&(e-=r[n][1],t.push(r[n][0]));return s[e]&&t.push(s[e]),t},d=(e)=>{const t=["zero","one","two","three","four","five","six","seven","eight","nine"];let n=[],r=a(e),s=r.match(/\.([0-9]+)/);if(!s||!s[0])return n;n.push("point");let o=s[0].split("");for(let a=0;ae&&(t.push("negative"),e=Math.abs(e));let n=o(e);for(let a=0,r;ae),0===t.length&&(t[0]=""),t}},{"./toString":64}],63:[function(e,t){"use strict";const n=e("./textCardinal"),a=e("../../../world/more-data/numbers").toOrdinal;t.exports=(e)=>{let t=n(e),r=t[t.length-1];return t[t.length-1]=a[r]||r,t.join(" ")}},{"../../../world/more-data/numbers":220,"./textCardinal":62}],64:[function(e,t){t.exports=function(e){if(1e6>e)return e+"";var t=e.toFixed(0);return-1===t.indexOf("e+")?t:t.replace(".","").split("e+").reduce(function(e,t){return e+Array(t-e.length+2).join(0)})}},{}],65:[function(e,t){"use strict";const n=e("../../text"),a=e("./value"),r=e("./parse");t.exports=n.makeSubset({noDates:function(){return this.not("#Date")},noUnits:function(){return this.not("#Unit")},units:function(){return this.match("#Unit+")},numbers:function(){return this.list.map((e)=>{return e.number()})},toNumber:function(){return this.list=this.list.map((e)=>{return e.toNumber()}),this},toText:function(){return this.list=this.list.map((e)=>{return e.toText()}),this},toCardinal:function(){return this.list=this.list.map((e)=>{return e.toCardinal()}),this},toOrdinal:function(){return this.list=this.list.map((e)=>{return e.toOrdinal()}),this},toNice:function(){return this.list=this.list.map((e)=>{return e.toNice()}),this},isEqual:function(e){return e=r(e),this.list=this.list.filter((t)=>{return null!==e&&t.number()===e}),this},greaterThan:function(e){return e=r(e),this.list=this.list.filter((t)=>{return null!==e&&t.number()>e}),this},lessThan:function(e){return e=r(e),this.list=this.list.filter((t)=>{return null!==e&&t.number(){let r=a.number();return r>e&&r{return t.add(e)}),this},subtract:function(e){return this.list=this.list.map((t)=>{return t.subtract(e)}),this},increment:function(){return this.list=this.list.map((e)=>{return e.add(1)}),this},decrement:function(){return this.list=this.list.map((e)=>{return e.subtract(1)}),this}},function(e,t){const r="twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty";if(e=e.match("#Value+ #Unit?"),e.has("#NumericValue #NumericValue")&&(e.has("#Value #Comma #Value")?e.splitAfter("#Comma"):e.splitAfter("#NumericValue")),e.has("#Value #Value #Value")&&!e.has("#Multiple")&&e.has("("+r+") #Cardinal #Cardinal")&&e.splitAfter("("+r+") #Cardinal"),e.has("#Value #Value")){e.has("#NumericValue #NumericValue")&&e.splitOn("#Year"),e.has("("+r+") ("+"eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen"+")")&&e.splitAfter("("+r+")");let t=e.match("#Cardinal #Cardinal");!t.found||e.has("(point|decimal)")||t.has("#Cardinal (#Multiple|point|decimal)")||t.has("("+r+") #Cardinal")||t.has("#Multiple #Value")||e.splitAfter(t.terms(0).out("normal")),!e.match("#Ordinal #Ordinal").match("#TextValue").found||e.has("#Multiple")||e.has("("+r+") #Ordinal")||e.splitAfter("#Ordinal"),e.has("#Ordinal #Cardinal")&&e.splitBefore("#Cardinal+"),e.has("#TextValue #NumericValue")&&!e.has("("+r+"|#Multiple)")&&e.splitBefore("#NumericValue+")}e.has("#NumberRange")&&e.splitAfter("#NumberRange"),"number"==typeof t&&(e=e.get(t));let s=e.world();return e.list=e.list.map((e)=>{return new a(e.terms,s,e.refText,e.refTerms)}),e})},{"../../text":192,"./parse":66,"./value":74}],66:[function(e,t){"use strict";const n=e("./parseText"),a=/^-?(\$|€|¥|£)?\.?[0-9]+[0-9,\.]*(st|nd|rd|th|rth|%)?$/,r=function(e){if(!0===a.test(e)){e=e.replace(/,/g,""),e=e.replace(/^[\$|€|¥|£]/g,""),e=e.replace(/%$/,""),e=e.replace(/(st|nd|rd|th|rth)$/g,"");let t=parseFloat(e);if(t||0===t)return t}return n(e)};t.exports=function(e){if(null===e||e===void 0||"number"==typeof e)return e;if("string"==typeof e)return r(e);if(1===e.terms.length&&!0!==e.terms[0].tags.TextValue){let t=e.terms[0].normal;return r(t)}return n(e.out("normal"))}},{"./parseText":69}],67:[function(e,t){const n=e("../../../world/more-data/numbers"),a=e("../paths").fns,r=a.extend(n.ordinal.ones,n.cardinal.ones),s=a.extend(n.ordinal.teens,n.cardinal.teens),i=a.extend(n.ordinal.tens,n.cardinal.tens),o=a.extend(n.ordinal.multiples,n.cardinal.multiples);o.grand=1e3,t.exports={ones:r,teens:s,tens:i,multiples:o}},{"../../../world/more-data/numbers":220,"../paths":73}],68:[function(e,t){"use strict";t.exports=(e)=>{const t=[{reg:/^(minus|negative)[\s\-]/i,mult:-1},{reg:/^(a\s)?half[\s\-](of\s)?/i,mult:0.5}];for(let n=0;n{return Object.keys(e).reduce((t,n)=>{return t+=e[n],t},0)};t.exports=function(e){if(!0===i.hasOwnProperty(e))return i[e];if("a"===e||"an"===e)return 1;const t=n(e);e=t.str;let u=null,m={},c=0,h=!1;const p=e.split(/[ -]/);for(let n=0,i;n{return e=e.replace(/1st$/,"1"),e=e.replace(/2nd$/,"2"),e=e.replace(/3rd$/,"3"),e=e.replace(/([4567890])r?th$/,"$1"),e=e.replace(/^[$€¥£¢]/,""),e=e.replace(/[%$€¥£¢]$/,""),e=e.replace(/,/g,""),e=e.replace(/([0-9])([a-z]{1,2})$/,"$1"),e}},{}],72:[function(e,t){"use strict";const n=e("./data");t.exports=(e,t)=>{if(n.ones.hasOwnProperty(e)){if(t.ones||t.teens)return!1;}else if(n.teens.hasOwnProperty(e)){if(t.ones||t.teens||t.tens)return!1;}else if(n.tens.hasOwnProperty(e)&&(t.ones||t.teens||t.tens))return!1;return!0}},{"./data":67}],73:[function(e,t){t.exports=e("../../paths")},{"../../paths":8}],74:[function(e,t){"use strict";const n=e("../../paths"),a=n.Terms,r=e("./parse"),s=e("./format"),i=function(e){return e.val=e.match("#Value+"),e.val=e.val.list[0],e.unit=e.match("#Unit+"),e.unit.found&&(e.unit=e.unit.list[0]),e},o=function(e,t){return e.has("#Percent")||t.has("#Percent")||!("percent"!==t.out("normal"))||null!==e.out("normal").match(/%$/)},l=function(e,t){let n=e.val.out();return n=e.has("#Ordinal")?e.has("#TextValue")?s.textOrdinal(t):s.ordinal(t):e.has("#TextValue")?s.text(t):e.has("#NiceNumber")?s.nice(t):s.cardinal(t),e.unit.found&&(n+=e.unit.out("text")),e=e.replaceWith(n,!0),i(e)},d=function(e,t,n,r){a.call(this,e,t,n,r),i(this)};d.prototype=Object.create(a.prototype);const u={data:function(){let e=r(this.val);return{number:e,nice:s.nice(e),ordinal:s.ordinal(e),niceOrdinal:s.niceOrdinal(e),text:s.text(e),textOrdinal:s.textOrdinal(e),unit:this.unit.out("normal")}},number:function(){return r(this.val)},toNumber:function(){let e=r(this.val);if(e||0===e){let t="";this.val.has("#Ordinal")?t=s.ordinal(e):(t=e+"",o(this.val,this.unit)&&(t+="%",this.unit.delete())),this.unit.found&&(t+=this.unit.out("text")),this.replaceWith(t,!0).tag("NumericValue"),this.unit.found&&this.match(this.unit.out("normal")).tag("Unit")}return this},toText:function(){let e=r(this.val);if(e||0===e){let t="";this.val.has("#Ordinal")?t=s.textOrdinal(e):(t=s.text(e),o(this.val,this.unit)&&(t+=" percent")),this.unit.found&&(t+=this.unit.out("text")),this.replaceWith(t,!0).tag("TextValue"),this.unit.found&&this.match(this.unit.out("normal")).tag("Unit")}return this},toCardinal:function(){let e=r(this.val);if(e||0===e){let t="";t=this.val.has("#TextValue")?s.text(e):e,this.unit.found&&(t+=this.unit.out("text")),this.replaceWith(t,!0).tag("Cardinal"),this.unit.found&&this.match(this.unit.out("normal")).tag("Unit")}return this},toOrdinal:function(){let e=r(this.val);if(e||0===e){let t="";t=this.val.has("#TextValue")?s.textOrdinal(e):s.ordinal(e),this.unit.found&&(t+=this.unit.out("text")),this.replaceWith(t,!0).tag("Ordinal"),this.unit.found&&this.match(this.unit.out("normal")).tag("Unit")}return this},toNice:function(){let e=r(this.val);if(e||0===e){let t="";t=this.val.has("#Ordinal")?s.niceOrdinal(e):s.nice(e),this.unit.found&&(t+=this.unit.out("text")),this.replaceWith(t,!0).tag("NumericValue"),this.unit.found&&this.match(this.unit.out("normal")).tag("Unit")}return this},add:function(e){if(!e)return this;let t=r(this.val)||0;return t+=e,l(this,t)},subtract:function(e){if(!e)return this;let t=r(this.val)||0;return t-=e,l(this,t)},increment:function(){return this.add(1)},decrement:function(){return this.subtract(1)}};Object.keys(u).forEach((e)=>{d.prototype[e]=u[e]}),t.exports=d},{"../../paths":8,"./format":59,"./parse":66}],75:[function(e,t){"use strict";const a=e("../../text"),n=e("./verb"),r={conjugation:function(e){return this.list.map((t)=>{return t.conjugation(e)})},conjugate:function(e,t){return null!==e&&"number"==typeof e&&this.list[e]?this.list[e].conjugate(t):this.list.map((e)=>{return e.conjugate(t)})},isPlural:function(){return this.list=this.list.filter((e)=>{return e.isPlural()}),this},isSingular:function(){return this.list=this.list.filter((e)=>{return!e.isPlural()}),this},isNegative:function(){return this.list=this.list.filter((e)=>{return e.isNegative()}),this},isPositive:function(){return this.list=this.list.filter((e)=>{return!e.isNegative()}),this},toNegative:function(){return this.list=this.list.map((e)=>{return e.toNegative()}),this},toPositive:function(){return this.list.forEach((e)=>{e.toPositive()}),this},toPastTense:function(){return this.list.forEach((e)=>{e.toPastTense()}),this},toPresentTense:function(){return this.list.forEach((e)=>{e.toPresentTense()}),this},toFutureTense:function(){return this.list.forEach((e)=>{e.toFutureTense()}),this},toInfinitive:function(){return this.list.forEach((e)=>{e.toInfinitive()}),this},toGerund:function(){return this.list.forEach((e)=>{e.toGerund()}),this},asAdjective:function(){return this.list.map((e)=>e.asAdjective())}};r.toContinuous=r.toGerund;t.exports=a.makeSubset(r,function(e,t){return e=e.match("(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+"),e=e.splitAfter("#Comma"),e.list.forEach((t)=>{t.terms.forEach((n)=>{n.whitespace.before.match("/")&&e.splitOn(n.normal)})}),e=e.if("#Verb"),"number"==typeof t&&(e=e.get(t)),e.list=e.list.map((e)=>{return new n(e.terms,e.world,e.refText,e.refTerms)}),new a(e.list,this.world,this.parent)})},{"../../text":192,"./verb":94}],76:[function(e,t){"use strict";const n=e("./methods/predict"),a=e("./methods/isPlural"),r=function(e){return e.match("#Gerund").found},s=function(e){let t=e.match("#Negative").list;return 2!==t.length&&!(1!==t.length)},i=function(e){return!!e.match("is being #PastTense").found||!!e.match("(had|has) been #PastTense").found||!!e.match("will have been #PastTense").found},o=function(e){return!!e.match("^(had|have) #PastTense")},l=function(e){let t=e.match("#Modal");return t.found?t.out("normal"):null},d=function(e){if(e.auxiliary.found){if(e.match("will have #PastTense").found)return"Past";if(e.auxiliary.match("will").found)return"Future";if(e.auxiliary.match("was").found)return"Past"}if(e.verb){let t=n(e.verb);return{PastTense:"Past",FutureTense:"Future",FuturePerfect:"Future"}[t]||"Present"}return"Present"};t.exports=(e)=>{let t=s(e),n={negative:t,continuous:r(e),passive:i(e),perfect:o(e),plural:a(e),modal:l(e),tense:d(e)};return n}},{"./methods/isPlural":86,"./methods/predict":87}],77:[function(e,t){"use strict";const n=e("./irregulars"),a=e("./suffixes"),r=e("./toActor"),s=e("./generic"),i=e("../predict"),o=e("../toInfinitive"),l=e("./toBe");t.exports=function(e,t){if("is"===e.normal||"was"===e.normal||"will"===e.normal)return l();e.tags.Contraction&&(e.text=e.silent_term);let d={PastTense:null,PresentTense:null,Infinitive:null,Gerund:null,Actor:null},u=i(e);u&&(d[u]=e.normal),"Infinitive"!==u&&(d.Infinitive=o(e,t)||"");const m=n(d.Infinitive,t)||{};Object.keys(m).forEach((e)=>{m[e]&&!d[e]&&(d[e]=m[e])});let c=d.Infinitive||e.normal;const h=a(c);return Object.keys(h).forEach((e)=>{h[e]&&!d[e]&&(d[e]=h[e])}),d.Actor||(d.Actor=r(c)),Object.keys(d).forEach((e)=>{!d[e]&&s[e]&&(d[e]=s[e](d))}),d}},{"../predict":87,"../toInfinitive":90,"./generic":80,"./irregulars":82,"./suffixes":83,"./toActor":84,"./toBe":85}],78:[function(e,t){t.exports=[{reg:/(eave)$/i,repl:{pr:"$1s",pa:"$1d",gr:"eaving",ar:"$1r"}},{reg:/(ink)$/i,repl:{pr:"$1s",pa:"unk",gr:"$1ing",ar:"$1er"}},{reg:/([aeiou]k)in$/i,repl:{pr:"$1s",pa:"$1ed",gr:"$1ing",ar:"$1er"}},{reg:/(end)$/i,repl:{pr:"$1s",pa:"ent",gr:"$1ing",ar:"$1er"}},{reg:/(ide)$/i,repl:{pr:"$1s",pa:"ode",gr:"iding",ar:"ider"}},{reg:/(ake)$/i,repl:{pr:"$1s",pa:"ook",gr:"aking",ar:"$1r"}},{reg:/(eed)$/i,repl:{pr:"$1s",pa:"$1ed",gr:"$1ing",ar:"$1er"}},{reg:/(e)(ep)$/i,repl:{pr:"$1$2s",pa:"$1pt",gr:"$1$2ing",ar:"$1$2er"}},{reg:/(a[tg]|i[zn]|ur|nc|gl|is)e$/i,repl:{pr:"$1es",pa:"$1ed",gr:"$1ing",prt:"$1en"}},{reg:/([i|f|rr])y$/i,repl:{pr:"$1ies",pa:"$1ied",gr:"$1ying"}},{reg:/([td]er)$/i,repl:{pr:"$1s",pa:"$1ed",gr:"$1ing"}},{reg:/([bd]l)e$/i,repl:{pr:"$1es",pa:"$1ed",gr:"$1ing"}},{reg:/(ish|tch|ess)$/i,repl:{pr:"$1es",pa:"$1ed",gr:"$1ing"}},{reg:/(ion|end|e[nc]t)$/i,repl:{pr:"$1s",pa:"$1ed",gr:"$1ing"}},{reg:/(om)e$/i,repl:{pr:"$1es",pa:"ame",gr:"$1ing"}},{reg:/(.eat)$/i,repl:{pr:"$1s",pa:"$1ed",gr:"$1ing"}},{reg:/([aeiu])([pt])$/i,repl:{pr:"$1$2s",pa:"$1$2",gr:"$1$2$2ing"}},{reg:/(er)$/i,repl:{pr:"$1s",pa:"$1ed",gr:"$1ing"}},{reg:/(en)$/i,repl:{pr:"$1s",pa:"$1ed",gr:"$1ing"}},{reg:/(ed)$/i,repl:{pr:"$1s",pa:"$1ded",ar:"$1der",gr:"$1ding"}},{reg:/(..)(ow)$/i,repl:{pr:"$1$2s",pa:"$1ew",gr:"$1$2ing",prt:"$1$2n"}},{reg:/(..)([cs]h)$/i,repl:{pr:"$1$2es",pa:"$1$2ed",gr:"$1$2ing"}},{reg:/([^aeiou][ou])(g|d)$/i,repl:{pr:"$1$2s",pa:"$1$2$2ed",gr:"$1$2$2ing"}},{reg:/([^aeiou][aeiou])(b|t|p|m)$/i,repl:{pr:"$1$2s",pa:"$1$2$2ed",gr:"$1$2$2ing"}},{reg:/([aeiou]zz)$/i,repl:{pr:"$1es",pa:"$1ed",gr:"$1ing"}}]},{}],79:[function(e,t){"use strict";const n=e("./irregulars"),a=e("./suffixes"),r=e("./generic"),s=["Gerund","PastTense","PresentTense"];t.exports=function(e,t){let o={Infinitive:e};if(t&&t.conjugations){const e=n(o.Infinitive,t);null!==e&&Object.keys(e).forEach((t)=>{e[t]&&!o[t]&&(o[t]=e[t])})}const i=a(e);Object.keys(i).forEach((e)=>{i[e]&&!o[e]&&(o[e]=i[e])});for(let n=0;n{const t=e.Infinitive;return"e"===t.charAt(t.length-1)?t.replace(/e$/,"ing"):t+"ing"},PresentTense:(e)=>{const t=e.Infinitive;return"s"===t.charAt(t.length-1)?t+"es":!0===n.test(t)?t.slice(0,-1)+"ies":t+"s"},PastTense:(e)=>{const t=e.Infinitive;return"e"===t.charAt(t.length-1)?t+"d":"ed"===t.substr(-2)?t:!0===n.test(t)?t.slice(0,-1)+"ied":t+"ed"}}},{}],81:[function(e,t){"use strict";const n=e("./conjugate"),a=e("./toBe"),r=function(e,t){if(t.adverbs.found){let n=t.first().match("#Adverb").found;Object.keys(e).forEach((a)=>{n?e[a]=t.adverbs.out()+" "+e[a]:e[a]+=t.adverbs.out()})}return e};t.exports=(e,t)=>{let s=e.negative.found,i=e.isPlural();if(e.verb.tags.Copula||"be"===e.verb.normal&&e.auxiliary.match("will").found){let t=!1;e.parent&&e.parent.has("i #Adverb? #Copula")&&(t=!0);let n=a(i,s,t);return r(n,e)}let o=n(e.verb,e.world,t);return e.particle.found&&Object.keys(o).forEach((t)=>{o[t]+=e.particle.out()}),s&&(o.PastTense="did not "+o.Infinitive,o.PresentTense="does not "+o.Infinitive,o.Gerund="not "+o.Gerund),o.FutureTense||(s?o.FutureTense="will not "+o.Infinitive:o.FutureTense="will "+o.Infinitive),o=r(o,e),o}},{"./conjugate":77,"./toBe":85}],82:[function(e,t){"use strict";const n=e("../../../../fns"),a=["Participle","Gerund","PastTense","PresentTense","FuturePerfect","PerfectTense","Actor"];t.exports=function(e,t){const r=t.conjugations,s=Object.keys(r);if(t&&t.conjugations&&!0===t.conjugations.hasOwnProperty(e))return t.conjugations[e];if(!0===r.hasOwnProperty(e)){let t=n.copy(r[e]);return t.Infinitive=e,t}for(let l=0;l{let a={PastTense:"was",PresentTense:"is",FutureTense:"will be",Infinitive:"is",Gerund:"being",Actor:"",PerfectTense:"been",Pluperfect:"been"};return!0===n&&(a.PresentTense="am",a.Infinitive="am"),e&&(a.PastTense="were",a.PresentTense="are",a.Infinitive="are"),t&&(a.PastTense+=" not",a.PresentTense+=" not",a.FutureTense="will not be",a.Infinitive+=" not",a.PerfectTense="not "+a.PerfectTense,a.Pluperfect="not "+a.Pluperfect,a.Gerund="not "+a.Gerund),a}},{}],86:[function(e,t){"use strict";t.exports=(e)=>{if(e.match("(are|were|does)").found)return!0;if(e.match("(is|am|do|was)").found)return!1;let t=e.getNoun();if(t&&t.found){if(t.match("#Plural").found)return!0;if(t.match("#Singular").found)return!1}return null}},{}],87:[function(e,t){"use strict";const n=e("./suffix_rules"),a={Infinitive:!0,Gerund:!0,PastTense:!0,PresentTense:!0,FutureTense:!0,PerfectTense:!0,Pluperfect:!0,FuturePerfect:!0,Participle:!0};t.exports=function(e){const t=Object.keys(a);for(let n=0;nr[t].length)return n[r[t]]}return null}},{"./suffix_rules":88}],88:[function(e,t){"use strict";const n={Gerund:["ing"],Actor:["erer"],Infinitive:["ate","ize","tion","rify","then","ress","ify","age","nce","ect","ise","ine","ish","ace","ash","ure","tch","end","ack","and","ute","ade","ock","ite","ase","ose","use","ive","int","nge","lay","est","ain","ant","ent","eed","er","le","own","unk","ung","en"],PastTense:["ed","lt","nt","pt","ew","ld"],PresentTense:["rks","cks","nks","ngs","mps","tes","zes","ers","les","acks","ends","ands","ocks","lays","eads","lls","els","ils","ows","nds","ays","ams","ars","ops","ffs","als","urs","lds","ews","ips","es","ts","ns","s"]},a={},r=Object.keys(n),s=r.length;for(let l=0,i;l{e.has("#Verb")&&e.terms.forEach((e)=>{e.silent_term&&(!e.text&&(e.whitespace.before=" "),e._text=e.silent_term,e.tags.TitleCase&&e.toTitleCase(),e.normalize(),e.silent_term=null,e.unTag("Contraction","expanded"))})}),e}},{}],93:[function(e,t){"use strict";const n=e("./methods/toInfinitive"),a=function(e){return e=e.match("(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+"),e=e.splitAfter("#Comma"),e.list[0]};t.exports=(e)=>{let t=e.match("#Auxiliary").first();if(t.found){let n=t.list[0].index(),r=e.parentTerms.insertAt(n+1,"not","Verb");return r.match("not").tag("Negative","tag-not"),a(r)}let r=e.match("(#Copula|will|has|had|do)").first();if(r.found){let t=r.list[0].index(),n=e.parentTerms.insertAt(t+1,"not","Verb");return n.match("not").tag("Negative","tag-not"),a(n)}let s=e.isPlural(),i=e.match("#PastTense").last();if(i.found){let t=i.list[0],r=t.index();t.terms[0].text=n(t.terms[0],e.world);let s=e.parentTerms.insertAt(r,"did not","Verb");return s.match("not").tag("Negative","tag-not"),a(s)}let o=e.match("#PresentTense").first();if(o.found){let t=o.list[0],r=t.index();t.terms[0].text=n(t.terms[0],e.world);let s=e.getNoun(),i=null;return i=s.match("(i|we|they|you)").found?e.parentTerms.insertAt(r,"do not","Verb"):e.parentTerms.insertAt(r,"does not","Verb"),i.match("not").tag("Negative","tag-not"),a(i)}let l=e.match("#Gerund").last();if(l.found){let t=l.list[0].index(),n=e.parentTerms.insertAt(t,"not","Verb");return n.match("not").tag("Negative","tag-not"),a(n)}let d=e.match("#Verb").last();if(d.found){let t=d.list[0],r=t.index();t.terms[0].text=n(t.terms[0],e.world);let i=e;return i=s?e.parentTerms.insertAt(r-1,"do not","Verb"):e.parentTerms.insertAt(r-1,"does not","Verb"),i.match("not").tag("Negative","tag-not"),a(i)}return e}},{"./methods/toInfinitive":90}],94:[function(e,t){"use strict";const n=e("../../paths").Terms,a=e("./methods/conjugate"),r=e("./methods/toAdjective"),s=e("./interpret"),i=e("./toNegative"),o=e("./methods/isPlural"),l=e("./methods/verbContraction"),d=function(e){let t=e;e.negative=e.match("#Negative"),e.adverbs=e.match("#Adverb");let n=e.clone().not("(#Adverb|#Negative)");if(e.verb=n.match("#Verb").not("#Particle").last(),e.particle=n.match("#Particle").last(),e.verb.found){let n=e.verb.out("normal");e.auxiliary=t.not(n).not("(#Adverb|#Negative)"),e.verb=e.verb.list[0].terms[0]}else e.verb=t.terms[0],e.auxiliary=n.not(".");return e},u={parse:function(){return d(this)},data:function(e){return{text:this.out("text"),normal:this.out("normal"),parts:{negative:this.negative.out("normal"),auxiliary:this.auxiliary.out("normal"),verb:this.verb.out("normal"),particle:this.particle.out("normal"),adverbs:this.adverbs.out("normal")},interpret:s(this,e),conjugations:this.conjugate()}},getNoun:function(){if(!this.refTerms)return null;let e="#Adjective? #Noun+ "+this.out("normal");return this.refTerms.match(e).match("#Noun+")},conjugation:function(){return s(this,!1).tense},conjugate:function(e){return a(this,e)},isPlural:function(){return o(this)},isNegative:function(){return 1===this.match("#Negative").list.length},isPerfect:function(){return this.auxiliary.match("(have|had)").found},toNegative:function(){return this.isNegative()?this:i(this)},toPositive:function(){return this.match("#Negative").delete()},toPastTense:function(){this.has("#Contraction")&&(this.list=l(this.parentTerms).list);let e=this.conjugate(),t=e.PastTense,n=this.replaceWith(t,!1);return n.verb.tag("#PastTense"),n},toPresentTense:function(){this.has("#Contraction")&&l(this.parentTerms);let e=this.conjugate(),t=this.replaceWith(e.PresentTense,!1);return t.verb.tag("#PresentTense"),t},toFutureTense:function(){this.has("#Contraction")&&l(this.parentTerms);let e=this.conjugate(),t=this.replaceWith(e.FutureTense,!1);return t.verb.tag("#FutureTense"),t},toInfinitive:function(){this.has("#Contraction")&&l(this.parentTerms);let e=this.conjugate(),t=this.replaceWith(e.Infinitive,!1);return t.verb.tag("#Infinitive"),t},toGerund:function(){this.has("#Contraction")&&l(this.parentTerms);let e=this.conjugate(),t="is",n=this.getNoun().out("normal");if(n){let e={i:"am",we:"are",they:"are"};e.hasOwnProperty(n)&&(t=e[n])}let a=t+" "+e.Gerund,s=this.replaceWith(a,!1);return s.verb.tag("#Gerund"),s},asAdjective:function(){return r(this.verb.out("normal"))}},m=function(e,t,a,r){return n.call(this,e,t,a,r),d(this)};m.prototype=Object.create(n.prototype),Object.keys(u).forEach((e)=>{m.prototype[e]=u[e]}),t.exports=m},{"../../paths":8,"./interpret":76,"./methods/conjugate":81,"./methods/isPlural":86,"./methods/toAdjective":89,"./methods/verbContraction":92,"./toNegative":93}],95:[function(e,t){"use strict";const n={punctuation_step:e("./steps/01-punctuation_step"),emoji_step:e("./steps/02-emoji_step"),lexicon_step:e("./steps/03-lexicon_step"),lexicon_multi:e("./steps/04-lexicon_multi"),web_step:e("./steps/05-web_step"),suffix_step:e("./steps/06-suffix_step"),neighbour_step:e("./steps/07-neighbour_step"),capital_step:e("./steps/08-capital_step"),noun_fallback:e("./steps/09-noun_fallback"),contraction:e("./steps/10-contraction_step"),date_step:e("./steps/11-date_step"),auxiliary_step:e("./steps/12-auxiliary_step"),negation_step:e("./steps/13-negation_step"),comma_step:e("./steps/14-comma_step"),quotation_step:e("./steps/15-quotation_step"),possessive_step:e("./steps/16-possessive_step"),acronym_step:e("./steps/17-acronym_step"),person_step:e("./steps/18-person_step"),organization_step:e("./steps/19-organization_step"),parentheses_step:e("./steps/20-parentheses_step"),plural_step:e("./steps/21-plural_step"),value_step:e("./steps/22-value_step"),corrections:e("./steps/23-corrections"),properNoun:e("./steps/24-proper_noun"),custom:e("./steps/25-custom")},a=e("./phrase");t.exports=function(e){return e=n.punctuation_step(e),e=n.emoji_step(e),e=n.lexicon_step(e),e=n.lexicon_multi(e),e=n.web_step(e),e=n.suffix_step(e),e=n.comma_step(e),e=n.neighbour_step(e),e=n.capital_step(e),e=n.noun_fallback(e),e=n.contraction(e),e=n.date_step(e),e=n.auxiliary_step(e),e=n.negation_step(e),e=n.quotation_step(e),e=n.possessive_step(e),e=n.acronym_step(e),e=n.person_step(e),e=n.organization_step(e),e=n.parentheses_step(e),e=n.plural_step(e),e=n.value_step(e),e=n.corrections(e),e=n.properNoun(e),e=a(e),e=n.custom(e),e}},{"./phrase":98,"./steps/01-punctuation_step":99,"./steps/02-emoji_step":100,"./steps/03-lexicon_step":101,"./steps/04-lexicon_multi":102,"./steps/05-web_step":103,"./steps/06-suffix_step":104,"./steps/07-neighbour_step":105,"./steps/08-capital_step":106,"./steps/09-noun_fallback":107,"./steps/10-contraction_step":108,"./steps/11-date_step":109,"./steps/12-auxiliary_step":110,"./steps/13-negation_step":111,"./steps/14-comma_step":112,"./steps/15-quotation_step":113,"./steps/16-possessive_step":114,"./steps/17-acronym_step":115,"./steps/18-person_step":116,"./steps/19-organization_step":117,"./steps/20-parentheses_step":118,"./steps/21-plural_step":119,"./steps/22-value_step":120,"./steps/23-corrections":121,"./steps/24-proper_noun":122,"./steps/25-custom":123}],96:[function(e,t){"use strict";t.exports=function(e){let t=e.match("#Condition .{1,7} #ClauseEnd");return t.found&&t.match("#Comma$")&&t.tag("Condition"),t=e.match("#Condition .{1,13} #ClauseEnd #Pronoun"),t.found&&t.match("#Comma$")&&t.not("#Pronoun$").tag("Condition","end-pronoun"),t=e.match("#Condition .{1,7} then"),t.found&&t.not("then$").tag("Condition","cond-then"),t=e.match("as long as .{1,7} (then|#ClauseEnd)"),t.found&&t.not("then$").tag("Condition","as-long-then"),t=e.match("#Comma #Condition .{1,7} .$"),t.found&&t.not("^#Comma").tag("Condition","comma-7-end"),t=e.match("#Condition .{1,4}$"),t.found&&t.tag("Condition","cond-4-end"),e}},{}],97:[function(e,t){"use strict";t.exports=function(e){return e.has("(#Verb|#Auxiliary)")&&(e.match("#Verb").tag("VerbPhrase","verbphrase-verb"),e.match("#Adverb #Verb").tag("VerbPhrase","adverb-verb"),e.match("#Verb #Adverb").tag("VerbPhrase","verb-adverb"),e.match("#Verb #Negative").tag("VerbPhrase","verb-not"),e.match("never #Verb").tag("VerbPhrase","not-verb"),e.match("#Auxiliary+").tag("VerbPhrase","2"),e.match("#Copula").tag("VerbPhrase","#3"),e.match("#Adverb #Auxiliary").tag("VerbPhrase","#4")),e}},{}],98:[function(e,t){"use strict";const n=e("./00-conditionPass"),a=e("./01-verbPhrase");t.exports=function(e){return e=n(e),e=a(e),e}},{"./00-conditionPass":96,"./01-verbPhrase":97}],99:[function(e,t){"use strict";const n=/^[A-Z][a-z']/,a=/^[IVXCM]+$/,r=function(e){return 1{let o=l.text;!0===n.test(o)&&l.tag("TitleCase","punct-rule"),"-"===l.whitespace.after&&e.terms[t+1]&&""===e.terms[t+1].whitespace.before&&(l.tag("Hyphenated","has-hyphen"),e.terms[t+1].tag("Hyphenated","has-hyphen")),"("===l.text[0]&&l.tag("StartBracket"),!0===/\)[,.?!;:]?$/.test(l.text)&&l.tag("EndBracket"),o=o.replace(/[,\.\?]$/,"");for(let e=0,n;e{return!(":"!==e.text.charAt(0))&&null!==e.text.match(/:.?$/)&&!e.text.match(" ")&&!(35{let t=e.text.replace(/^[:;]/,":");return!0===a.hasOwnProperty(t)};t.exports=(e)=>{for(let a=0,i;ae.root),o=n;i.length{e.world.cache=e.world.cache||{};let n=e.world.cache.firstWords||{};for(let r=0,s;r{let n=Object.keys(l.tags);if(n=n.filter((e)=>!1===i.hasOwnProperty(e)),0===n.length){let n=e.terms[t-1],i=e.terms[t+1];if(n&&a.hasOwnProperty(n.normal)&&!n.tags.ClauseEnd)return void l.tag(a[n.normal],"neighbour-after-\""+n.normal+"\"");if(!l.tags.ClauseEnd&&i&&r.hasOwnProperty(i.normal))return void l.tag(r[i.normal],"neighbour-before-\""+i.normal+"\"");let d=[];if(n){d=Object.keys(n.tags);for(let e=0;e!n[e]).length)},r=function(e){if(!0===/^(re|un)-?[^aeiou]./.test(e.normal)){let t=e.normal.replace(/^(re|un)-?/,"");if(!0===e.world.words.hasOwnProperty(t)){let n=e.world.words[t];if("Infinitive"===n||"PresentTense"===n||"PastTense"===n||"Gerund"===n)return n}}return null};t.exports=function(e){for(let n=0,s;n{!0!==e.found||e.list.forEach((e)=>{let n=parseInt(e.terms[0].normal,10);n&&1e3n&&e.terms[0].tag("Year",t)})},o=(e,t)=>{!0!==e.found||e.list.forEach((e)=>{let n=parseInt(e.terms[0].normal,10);n&&1900n&&e.terms[0].tag("Year",t)})};t.exports=function(e){let t="(january|april|may|june|summer|autumn|jan|sep)";e.has(t)&&(e.match(`#Infinitive #Determiner? #Adjective? #Noun? (to|for) ${t}`).lastTerm().tag("Person","ambig-person"),e.match(`#Infinitive ${t}`).lastTerm().tag("Person","infinitive-person"),e.match(`${t} #PresentTense (to|for)`).firstTerm().tag("Person","ambig-active"),e.match(`${t} #Modal`).firstTerm().tag("Person","ambig-modal"),e.match(`#Modal ${t}`).lastTerm().tag("Person","modal-ambig"),e.match(`(that|with|for) ${t}`).term(1).tag("Person","that-month"),e.match(`#Copula ${t}`).term(1).tag("Person","is-may"),e.match(`${t} #Copula`).term(0).tag("Person","may-is"),e.match(`${t} the? #Value`).term(0).tag("Month","person-value"),e.match(`#Date ${t}`).term(1).tag("Month","correction-may"),e.match(`${t} the? #Value`).firstTerm().tag("Month","may-5th"),e.match(`#Value of ${t}`).lastTerm().tag("Month","5th-of-may"),e.match(`${n} ${t}`).ifNo("#Holiday").term(1).tag("Month","preps-month"),e.match(`(next|this|last) ${t}`).term(1).tag("Month","correction-may"));let l="(may|march)";if(e.has(l)&&(e.match(`#Adverb ${l}`).lastTerm().tag("Infinitive","ambig-verb"),e.match(`${l} #Adverb`).lastTerm().tag("Infinitive","ambig-verb"),e.match(`${n} ${l}`).lastTerm().tag("Month","in-month"),e.match(`(next|this|last) ${l}`).lastTerm().tag("Month","this-month"),e.match(`${l} the? #Value`).firstTerm().tag("Month","march-5th"),e.match(`#Value of? ${l}`).lastTerm().tag("Month","5th-of-march"),e.match(`[${l}] .? #Date`).lastTerm().tag("Month","march-and-feb"),e.match(`#Date .? [${l}]`).lastTerm().tag("Month","feb-and-march"),e.has("march")&&(e.match("march (up|down|back|to|toward)").term(0).tag("Infinitive","march-to"),e.match("#Modal march").term(1).tag("Infinitive","must-march"))),e.has("sun")&&(e.match("sun #Date").firstTerm().tag("WeekDay","sun-feb"),e.match("sun the #Ordinal").tag("Date").firstTerm().tag("WeekDay","sun-the-5th"),e.match("#Determiner sun").lastTerm().tag("Singular","the-sun")),e.has("sat")&&(e.match("sat #Date").firstTerm().tag("WeekDay","sat-feb"),e.match(`${n} sat`).lastTerm().tag("WeekDay","sat")),e.has("#Month")&&(e.match(`#Month #DateRange+`).tag("Date","correction-numberRange"),e.match("#Value of #Month").tag("Date","value-of-month"),e.match("#Cardinal #Month").tag("Date","cardinal-month"),e.match("#Month #Value to #Value").tag("Date","value-to-value"),e.match("#Month the #Value").tag("Date","month-the-value")),e.match("in the (night|evening|morning|afternoon|day|daytime)").tag("Time","in-the-night"),e.match("(#Value|#Time) (am|pm)").tag("Time","value-ampm"),e.has("#Value")){e.match("for #Value #Duration").tag("Date","for-x-duration"),e.match("#Value #Abbreviation").tag("Value","value-abbr"),e.match("a #Value").if("(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)").tag("Value","a-value"),e.match("(minus|negative) #Value").tag("Value","minus-value"),e.match("#Value grand").tag("Value","value-grand"),e.match("(half|quarter) #Ordinal").tag("Value","half-ordinal"),e.match("(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion) and #Value").tag("Value","magnitude-and-value"),e.match("#Value (point|decimal) #Value").tag("Value","value-point-value"),e.match(`${n}? #Value #Duration`).tag("Date","value-duration"),e.match("(#WeekDay|#Month) #Value").ifNo("#Money").tag("Date","date-value"),e.match("#Value (#WeekDay|#Month)").ifNo("#Money").tag("Date","value-date");let t=e.match("#TextValue #TextValue");t.found&&t.has("#Date")&&t.tag("#Date","textvalue-date"),e.match("#Value #Duration #Conjunction").tag("Date","val-duration-conjunction"),e.match("#Value #Duration old").unTag("Date","val-years-old")}if(e.has(s)&&(e.match(`${n}? ${a} ${s}`).tag("Date","thisNext-season"),e.match(`the? ${r} of ${s}`).tag("Date","section-season")),e.has("#Date")&&(e.match("#Date the? #Ordinal").tag("Date","correction-date"),e.match(`${a} #Date`).tag("Date","thisNext-date"),e.match("due? (by|before|after|until) #Date").tag("Date","by-date"),e.match("#Date (by|before|after|at|@|about) #Cardinal").not("^#Date").tag("Time","date-before-Cardinal"),e.match("#Date (am|pm)").term(1).unTag("Verb").unTag("Copula").tag("Time","date-am"),e.match("(last|next|this|previous|current|upcoming|coming|the) #Date").tag("Date","next-feb"),e.match("#Date (#Preposition|to) #Date").tag("Date","date-prep-date"),e.match(`the? ${r} of #Date`).tag("Date","section-of-date"),e.match("#Ordinal #Duration in #Date").tag("Date","duration-in-date"),e.match("(early|late) (at|in)? the? #Date").tag("Time","early-evening")),e.has("#Cardinal")){let t=e.match(`#Date #Value #Cardinal`).lastTerm();i(t,"date-value-year"),t=e.match(`#Date+ #Cardinal`).lastTerm(),i(t,"date-year"),t=e.match(`#Month #Value #Cardinal`).lastTerm(),i(t,"month-value-year"),t=e.match(`#Month #Value to #Value #Cardinal`).lastTerm(),i(t,"month-range-year"),t=e.match(`(in|of|by|during|before|starting|ending|for|year) #Cardinal`).lastTerm(),i(t,"in-year"),t=e.match("(q1|q2|q3|q4) [#Cardinal]"),i(t,"in-year"),t=e.match("#Ordinal quarter [#Cardinal]"),i(t,"in-year"),t=e.match("the year [#Cardinal]"),i(t,"in-year"),t=e.match("it (is|was) [#Cardinal]"),o(t,"in-year"),t=e.match(`#Cardinal !#Plural`).firstTerm(),o(t,"year-unsafe")}if(e.has("#Date")){e.has("#Time")&&(e.match("#Cardinal #Time").not("#Year").tag("Time","value-time"),e.match("(by|before|after|at|@|about) #Time").tag("Time","preposition-time"),e.match("#Time (eastern|pacific|central|mountain)").term(1).tag("Time","timezone"),e.match("#Time (est|pst|gmt)").term(1).tag("Time","timezone abbr"));let t=e.match("#Date+").splitOn("Clause");!1===t.has("(#Year|#Time)")&&t.match("#Value (#Month|#Weekday) #Value").lastTerm().unTag("Date")}return e}},{}],110:[function(e,t){"use strict";const n={do:!0,"don't":!0,does:!0,"doesn't":!0,will:!0,wont:!0,"won't":!0,have:!0,"haven't":!0,had:!0,"hadn't":!0,not:!0};t.exports=function(e){for(let a=0,r;a{let a=e.terms[n],t=e.terms[n+1];return t&&a.tags.Place&&!a.tags.Country&&t.tags.Country},a=(e)=>{return e.tags.Adjective?"Adjective":e.tags.Noun?"Noun":e.tags.Verb?"Verb":e.tags.Value?"Value":null},r=(e,n)=>{let r=n,s=a(e.terms[n]),i=0,o=0,l=!1;for(++n;n{n[e].regex=new RegExp(n[e].close+"[;:,.]*"),n[e].open=e});const a=new RegExp("["+Object.keys(n).join("")+"]");t.exports=(e)=>{const r=e.terms.slice(0);for(let s=0,i;sn[e]);for(let n=0,a;n{o[e[0]]=new RegExp(e[1]+"[^"+e[1]+"\\w]*$")}),n.map((e)=>new RegExp(e.replace("'","["+"'\u2018\u2019\u201B\u201A\u2035\u2032`\xB4"+"]")));const l=function(e,t,s){const i=e.get(s),o=e.get(s+1),l=e.get(s+2),d=n.map((e)=>t.match(e)).find((e)=>e),u=r.test(i.whitespace.after),m=i.tags.Pronoun;return d||m||!u?!1:a.test(t)||void 0===o||!0===o.tags.Noun||!0===i.tags.ClauseEnd||void 0!==l&&o.tags.Adjective&&l.tags.Noun};t.exports=function(e){let t=[];for(let n=0;n{e.isAcronym()&&e.tag("Acronym","acronym-step")}),e}},{}],116:[function(e,t){"use strict";t.exports=function(e){e.match("(mr|mrs|ms|dr) (#TitleCase|#Possessive)+").tag("#Person","mr-putin");let t="(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)";e.has(t)&&(e.match("(#Determiner|#Adverb|#Pronoun|#Possessive) ["+t+"]").tag("Noun","the-ray"),e.match(t+" (#Person|#Acronym|#TitleCase)").canBe("#Person").tag("Person","ray-smith"));let n="(pat|wade|ollie|will|rob|buck|bob|mark|jack)";e.has(n)&&(e.match("(#Modal|#Adverb) ["+n+"]").tag("Verb","would-mark"),e.match(n+" (#Person|#TitleCase)").tag("Person","rob-smith"));let a="(misty|rusty|dusty|rich|randy)";e.has(a)&&(e.match("#Adverb ["+a+"]").tag("Adjective","really-rich"),e.match(a+" (#Person|#TitleCase)").tag("Person","randy-smith"));let r="(april|june|may|jan|august|eve)";e.has(r)&&(e.match(r+" (#Person|#TitleCase)").canBe("#Person").tag("Person","june-smith"),e.match("(in|during|on|by|before|#Date) ["+r+"]").canBe("#Date").tag("Date","in-june"),e.match(r+" (#Date|#Value)").canBe("#Date").tag("Date","june-5th"));let s="(paris|alexandria|houston|kobe|salvador|sydney)";if(e.has(s)&&(e.match("(in|near|at|from|to|#Place) ["+s+"]").canBe("#Place").tag("Place","in-paris"),e.match("["+s+"] #Place").canBe("#Place").tag("Place","paris-france"),e.match("["+s+"] #Person").canBe("#Person").tag("Person","paris-hilton")),e.match("al")&&(e.match("al (#Person|#TitleCase)").canBe("#Person").tag("#Person","al-borlen"),e.match("#TitleCase al #TitleCase").canBe("#Person").tag("#Person","arabic-al-arabic")),e.match("(private|general|major|corporal|lord|lady|secretary|premier) #Honorific? #Person").terms(0).tag("Honorific","ambg-honorifics"),e.match("(1st|2nd|first|second) #Honorific").terms(0).tag("Honorific","ordinal-honorific"),e.has("#FirstName")){let t=e.match("#FirstName #Noun").ifNo("^#Possessive").ifNo("#ClauseEnd .");t.lastTerm().canBe("#LastName").tag("#LastName","firstname-noun"),e.match("#FirstName de #Noun").canBe("#Person").tag("#Person","firstname-de-noun"),e.match("#FirstName (bin|al) #Noun").canBe("#Person").tag("#Person","firstname-al-noun"),e.match("#FirstName #Acronym #TitleCase").tag("Person","firstname-acronym-titlecase"),e.match("#FirstName #FirstName #TitleCase").tag("Person","firstname-firstname-titlecase"),e.match("#Honorific #FirstName? #TitleCase").tag("Person","Honorific-TitleCase"),e.match("#FirstName #TitleCase #TitleCase?").match("#Noun+").tag("Person","firstname-titlecase"),e.match("#FirstName the #Adjective").tag("Person","correction-determiner5"),e.match("#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)").tag("#Person","firstname-maybe"),e.match("#FirstName #Acronym #Noun").ifNo("#Date").tag("#Person","n-acro-noun").lastTerm().tag("#LastName","n-acro-noun"),e.match("#FirstName [#Determiner? #Noun] #LastName").tag("#NickName","first-noun-last").tag("#Person","first-noun-last"),e.match("#FirstName (#Singular|#Possessive)").ifNo("#Date").ifNo("#NickName").tag("#Person","first-possessive").lastTerm().tag("#LastName","first-possessive")}return e.has("#LastName")&&(e.match("#Noun #LastName").firstTerm().canBe("#FirstName").tag("#FirstName","noun-lastname"),e.match("(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill) #LastName").firstTerm().tag("#FirstName","maybe-lastname"),e.match("#TitleCase #Acronym? #LastName").ifNo("#Date").tag("#Person","title-acro-noun").lastTerm().tag("#LastName","title-acro-noun"),e.match("#Copula (#Noun|#PresentTense) #LastName").term(1).tag("#FirstName","copula-noun-lastname")),e.has("#TitleCase")&&(e.match("#Acronym #TitleCase").canBe("#Person").tag("#Person","acronym-titlecase"),e.match("#TitleCase (van|al|bin) #TitleCase").canBe("#Person").tag("Person","correction-titlecase-van-titlecase"),e.match("#TitleCase (de|du) la? #TitleCase").canBe("#Person").tag("Person","correction-titlecase-van-titlecase"),e.match("#Person #TitleCase").match("#TitleCase #Noun").canBe("#Person").tag("Person","correction-person-titlecase"),e.match("(lady|queen|sister) #TitleCase").ifNo("#Date").ifNo("#Honorific").tag("#FemaleName","lady-titlecase"),e.match("(king|pope|father) #TitleCase").ifNo("#Date").tag("#MaleName","correction-poe")),e.match("#Noun van der? #Noun").canBe("#Person").tag("#Person","von der noun"),e.match("(king|queen|prince|saint|lady) of? #Noun").canBe("#Person").tag("#Person","king-of-noun"),e.match("#Honorific #Acronym").tag("Person","Honorific-TitleCase"),e.match("#Person #Person the? #RomanNumeral").tag("Person","correction-roman-numeral"),e.match("#Honorific #Person").tag("Person","Honorific-Person"),e.match("^#Honorific$").unTag("Person","single-honorific"),e}},{}],117:[function(e,t){"use strict";let n=e("../../world/more-data/orgWords");const a=function(e){return!!e.tags.Noun&&(e.tags.Pronoun||e.tags.Comma||e.tags.Possessive||e.tags.Place?!1:e.tags.TitleCase||e.tags.Organization||e.tags.Acronym)};t.exports=(e)=>{for(let r=0,s;r{if(n.tags.StartBracket)for(let n=t;n{e.match(n).tag(t[n],"post-hoc: "+n)}),e}},{}],124:[function(e,t){"use strict";const n=e("./fix"),a={wanna:["want","to"],gonna:["going","to"],im:["i","am"],alot:["a","lot"],dont:["do","not"],dun:["do","not"],ive:["i","have"],"won't":["will","not"],wont:["will","not"],"can't":["can","not"],cant:["can","not"],cannot:["can","not"],"shan't":["should","not"],imma:["I","will"],"where'd":["where","did"],whered:["where","did"],"when'd":["when","did"],whend:["when","did"],"how'd":["how","did"],howd:["how","did"],"what'd":["what","did"],whatd:["what","did"],"let's":["let","us"],dunno:["do","not","know"],brb:["be","right","back"],gtg:["got","to","go"],irl:["in","real","life"],tbh:["to","be","honest"],imo:["in","my","opinion"],til:["today","i","learned"],rn:["right","now"],twas:["it","was"],"@":["at"]};t.exports=(e)=>{for(let r=0,s;r{let a=e.terms[n],t=e.terms[n+1];return a.tags.Pronoun||a.tags.QuestionWord?!1:!r[a.normal]&&(!t||!!t.tags.Infinitive||!t.tags.VerbPhrase&&(!!t.tags.Noun||t.tags.Adjective&&e.terms[n+2]&&e.terms[n+2].tags.Noun||(t.tags.Adjective||t.tags.Adverb||t.tags.Verb)&&!1))},l=function(e,t){let n=["is","not"];if(e.terms[t-1]){let a=e.terms[t-1];a.tags.Adverb&&e.terms[t-2]&&(a=e.terms[t-2]),(a.tags.Plural||!0===s[a.normal])&&(n[0]="are")}return n};t.exports=(e)=>{for(let t=0;t{for(let t=0;t{e.match("#Hyphenated #Hyphenated").match("#NumericValue #NumericValue").tag("NumberRange");for(let s=0,i;s{a[e.silent_term]&&e.tag(a[e.silent_term])};t.exports=(e,t,a)=>{let s=e.terms[a];if(s.silent_term=t[0],s.tag("Contraction","tagger-contraction"),t[1]){let s=new n("",e.world);s.silent_term=t[1],s.tag("Contraction","tagger-contraction"),e.insertAt(a+1,s),s.whitespace.before="",s.whitespace.after="",r(s)}if(t[2]){let s=new n("",e.world);s.silent_term=t[2],e.insertAt(a+2,s),s.tag("Contraction","tagger-contraction"),r(s)}return e}},{"../../../term":143}],129:[function(e,t){"use strict";const n=/^([a-z]+)'([a-z][a-z]?)$/i,a=/[a-z]s'$/i,r={re:1,ve:1,ll:1,t:1,s:1,d:1,m:1};t.exports=(e)=>{if("can't"===e.normal)return{start:"can",end:"n't"};let t=e.normal.match(n);return t&&t[1]&&1===r[t[2]]?("t"===t[2]&&t[1].match(/[a-z]n$/)&&(t[1]=t[1].replace(/n$/,""),t[2]="n't"),!0===e.tags.TitleCase&&(t[1]=t[1].replace(/^[a-z]/,(e)=>e.toUpperCase())),{start:t[1],end:t[2]}):!0===a.test(e.text)?{start:e.normal.replace(/s'?$/,""),end:""}:null}},{}],130:[function(e,t){t.exports=/(?:0\u20E3\n1\u20E3|2\u20E3|3\u20E3|4\u20E3|5\u20E3|6\u20E3|7\u20E3|8\u20E3|9\u20E3|#\u20E3|\*\u20E3|\uD83C(?:\uDDE6\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF2|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFD|\uDDFF)|\uDDE7\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFC|\uDDFE|\uDDFF)|\uDDE8\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDE9\uD83C(?:\uDDEA|\uDDEC|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDFF)|\uDDEA\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDED|\uDDF7|\uDDF8|\uDDF9|\uDDFA)|\uDDEB\uD83C(?:\uDDEE|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDF7)|\uDDEC\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF1|\uDDF2|\uDDF3|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFE)|\uDDED\uD83C(?:\uDDF0|\uDDF2|\uDDF3|\uDDF7|\uDDF9|\uDDFA)|\uDDEE\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9)|\uDDEF\uD83C(?:\uDDEA|\uDDF2|\uDDF4|\uDDF5)|\uDDF0\uD83C(?:\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDF2|\uDDF3|\uDDF5|\uDDF7|\uDDFC|\uDDFE|\uDDFF)|\uDDF1\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDEE|\uDDF0|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFE)|\uDDF2\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDF3\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFF)|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C(?:\uDDE6|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF7|\uDDF8|\uDDF9|\uDDFC|\uDDFE)|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C(?:\uDDEA|\uDDF4|\uDDF8|\uDDFA|\uDDFC)|\uDDF8\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDE9|\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFD|\uDDFE|\uDDFF)|\uDDF9\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF9|\uDDFB|\uDDFC|\uDDFF)|\uDDFA\uD83C(?:\uDDE6|\uDDEC|\uDDF2|\uDDF8|\uDDFE|\uDDFF)|\uDDFB\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDEE|\uDDF3|\uDDFA)|\uDDFC\uD83C(?:\uDDEB|\uDDF8)|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C(?:\uDDEA|\uDDF9)|\uDDFF\uD83C(?:\uDDE6|\uDDF2|\uDDFC)))|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD79\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED0\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3]|\uD83E[\uDD10-\uDD18\uDD80-\uDD84\uDDC0]/g},{}],131:[function(e,t){t.exports={":(":!0,":)":!0,":P":!0,":p":!0,":O":!0,":3":!0,":|":!0,":/":!0,":\\":!0,":$":!0,":*":!0,":@":!0,":-(":!0,":-)":!0,":-P":!0,":-p":!0,":-O":!0,":-3":!0,":-|":!0,":-/":!0,":-\\":!0,":-$":!0,":-*":!0,":-@":!0,":^(":!0,":^)":!0,":^P":!0,":^p":!0,":^O":!0,":^3":!0,":^|":!0,":^/":!0,":^\\":!0,":^$":!0,":^*":!0,":^@":!0,"):":!0,"(:":!0,"$:":!0,"*:":!0,")-:":!0,"(-:":!0,"$-:":!0,"*-:":!0,")^:":!0,"(^:":!0,"$^:":!0,"*^:":!0,"<3":!0,"{e[n].downward=[];for(let a=0;a{t[n]=e[n]})},m=function(t){Object.keys(t).forEach((r)=>{t[r].notA={};for(let e=0,a;ee!==r),a.forEach((n)=>{t[r].notA[n]=!0}));t[r].notA=Object.keys(t[r].notA)})},c=function(e){Object.keys(e).forEach((t)=>{return d[t]?void(e[t].color=d[t]):e[t].isA&&d[e[t].isA]?void(e[t].color=d[e[t].isA]):void(e[t].isA&&e[e[t].isA].color&&(e[t].color=e[e[t].isA].color))})};t.exports=(()=>{let e={};return u(a,e),u(r,e),u(s,e),u(i,e),u(o,e),l(e),m(e),c(e),e})()},{"./addDownward":135,"./conflicts":136,"./tags/dates":138,"./tags/misc":139,"./tags/nouns":140,"./tags/values":141,"./tags/verbs":142}],138:[function(e,t){t.exports={Date:{},Month:{isA:"Date",also:"Singular"},WeekDay:{isA:"Date",also:"Noun"},RelativeDay:{isA:"Date"},Year:{isA:"Date"},Duration:{isA:"Date",also:"Noun"},Time:{isA:"Date",also:"Noun"},Holiday:{isA:"Date",also:"Noun"}}},{}],139:[function(e,t){t.exports={Adjective:{},Comparable:{isA:"Adjective"},Comparative:{isA:"Adjective"},Superlative:{isA:"Adjective"},NumberRange:{isA:"Contraction"},Adverb:{},Currency:{},Determiner:{},Conjunction:{},Preposition:{},QuestionWord:{},RelativeProunoun:{isA:"Pronoun"},Expression:{},Abbreviation:{},Url:{},PhoneNumber:{},HashTag:{},AtMention:{is:"Noun"},Emoji:{},Email:{},Condition:{},VerbPhrase:{},Auxiliary:{},Negative:{},Contraction:{},TitleCase:{},CamelCase:{},UpperCase:{},Hyphenated:{},Acronym:{},ClauseEnd:{},Quotation:{},StartQuotation:{isA:"Quotation"},EndQuotation:{isA:"Quotation"},Parentheses:{},EndBracket:{isA:"Parentheses"},StartBracket:{isA:"Parentheses"}}},{}],140:[function(e,t){t.exports={Noun:{},Singular:{isA:"Noun"},ProperNoun:{isA:"Noun"},Person:{isA:"Singular"},FirstName:{isA:"Person"},MaleName:{isA:"FirstName"},FemaleName:{isA:"FirstName"},LastName:{isA:"Person"},Honorific:{isA:"Noun"},Place:{isA:"Singular"},Country:{isA:"Place"},City:{isA:"Place"},Region:{isA:"Place"},Address:{isA:"Place"},Organization:{isA:"Singular"},SportsTeam:{isA:"Organization"},Company:{isA:"Organization"},School:{isA:"Organization"},Plural:{isA:"Noun"},Uncountable:{isA:"Noun"},Pronoun:{isA:"Noun"},Actor:{isA:"Noun"},Activity:{isA:"Noun"},Unit:{isA:"Noun"},Demonym:{isA:"Noun"},Possessive:{isA:"Noun"}}},{}],141:[function(e,t){t.exports={Value:{},Ordinal:{isA:"Value"},Cardinal:{isA:"Value"},Multiple:{isA:"Value"},RomanNumeral:{isA:"Cardinal"},Fraction:{isA:"Value"},TextValue:{isA:"Value"},NumericValue:{isA:"Value"},NiceNumber:{isA:"Value"},Money:{},Percent:{isA:"Value"}}},{}],142:[function(e,t){t.exports={Verb:{isA:"VerbPhrase"},PresentTense:{isA:"Verb"},Infinitive:{isA:"PresentTense"},Gerund:{isA:"PresentTense"},PastTense:{isA:"Verb"},PerfectTense:{isA:"Verb"},FuturePerfect:{isA:"Verb"},Pluperfect:{isA:"Verb"},Copula:{isA:"Verb"},Modal:{isA:"Verb"},Participle:{isA:"Verb"},Particle:{isA:"Verb"},PhrasalVerb:{isA:"Verb"}}},{}],143:[function(e,t){"use strict";const n=e("./paths").fns,a=e("./whitespace"),r=e("./makeUID"),s=e("./methods/normalize/normalize").addNormal,i=e("./methods/normalize/root"),o=function(e,t){this.tags={},this._text=n.ensureString(e),Object.defineProperty(this,"world",{enumerable:!1,value:t});let o=a(this._text);this.whitespace=o.whitespace,this._text=o.text,this.parent=null,this.silent_term="",this.lumped=!1,s(this),i(this),this.dirty=!1,this.uid=r(this.normal),Object.defineProperty(this,"text",{get:function(){return this._text},set:function(e){e=e||"",this._text=e.trim(),this.dirty=!0,this.normalize()}}),Object.defineProperty(this,"isA",{get:function(){return"Term"}})};o.prototype.normalize=function(){return s(this),i(this),this},o.prototype.index=function(){let e=this.parentTerms;return e?e.terms.indexOf(this):null},o.prototype.clone=function(){let e=new o(this._text,this.world);return e.tags=n.copy(this.tags),e.whitespace=n.copy(this.whitespace),e.silent_term=this.silent_term,e},e("./methods/misc")(o),e("./methods/out")(o),e("./methods/tag")(o),e("./methods/case")(o),e("./methods/punctuation")(o),t.exports=o},{"./makeUID":144,"./methods/case":146,"./methods/misc":147,"./methods/normalize/normalize":149,"./methods/normalize/root":150,"./methods/out":153,"./methods/punctuation":156,"./methods/tag":158,"./paths":161,"./whitespace":162}],144:[function(e,t){"use strict";t.exports=(e)=>{let t="";for(let n=0;5>n;n++)t+=parseInt(9*Math.random(),10);return e+"-"+t}},{}],145:[function(e,t){"use strict";const n={Auxiliary:1,Possessive:1,TitleCase:1,ClauseEnd:1,Comma:1,CamelCase:1,UpperCase:1,Hyphenated:1,VerbPhrase:1,EndBracket:1,StartBracket:1,Parentheses:1,Quotation:1};t.exports=function(e){const t=e.world.tags;let a=Object.keys(e.tags);return a=a.sort(),a=a.sort((e,a)=>{return t[e]?n[a]||!t[a]?-1:t[e].downward.length>t[a].downward.length?1:1:1}),a[0]}},{}],146:[function(e,t){"use strict";t.exports=(e)=>{const t={toUpperCase:function(){return this.text=this._text.toUpperCase(),this.tag("#UpperCase","toUpperCase"),this},toLowerCase:function(){return this.text=this._text.toLowerCase(),this.unTag("#TitleCase"),this.unTag("#UpperCase"),this},toTitleCase:function(){return this.text=this._text.replace(/^ *[a-z]/,(e)=>e.toUpperCase()),this.tag("#TitleCase","toTitleCase"),this},needsTitleCase:function(){const e=["Person","Place","Organization","Acronym","UpperCase","Currency","RomanNumeral","Month","WeekDay","Holiday","Demonym"];for(let t=0;t{e.prototype[n]=t[n]}),e}},{}],147:[function(e,t){"use strict";const n=e("./normalize/isAcronym"),a=e("./bestTag"),r=/[aeiouy]/i,s=/[a-z]/,i=/[0-9]/;t.exports=(e)=>{const t={bestTag:function(){return a(this)},isAcronym:function(){return n(this._text)},isWord:function(){let e=this;return!!e.silent_term||!1!==/[a-z|A-Z|0-9]/.test(e.text)&&(3{e.prototype[n]=t[n]}),e}},{"./bestTag":145,"./normalize/isAcronym":148}],148:[function(e,t){"use strict";const n=/([A-Z]\.)+[A-Z]?,?$/,a=/^[A-Z]\.,?$/,r=/[A-Z]{2}('s|,)?$/;t.exports=function(e){return!(!0!==n.test(e))||!(!0!==a.test(e))||!(!0!==r.test(e))}},{}],149:[function(e,t,n){"use strict";const a=e("./unicode"),r=e("./isAcronym");n.normalize=function(e){e=e||"",e=e.toLowerCase(),e=e.trim();let t=e;return e=a(e),e=e.replace(/^[#@]/,""),e=e.replace(/[,;.!?]+$/,""),e=e.replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g,"'"),e=e.replace(/[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g,"\""),e=e.replace(/\u2026/g,"..."),e=e.replace(/\u2013/g,"-"),!0===/[a-z][^aeiou]in['’]$/.test(e)&&(e=e.replace(/in['’]$/,"ing")),!0===/^(re|un)-?[^aeiou]./.test(e)&&(e=e.replace("-","")),!1===/^[:;]/.test(e)&&(e=e.replace(/\.{3,}$/g,""),e=e.replace(/['",\.!:;\?\)]+$/g,""),e=e.replace(/^['"\(]+/g,"")),e=e.trim(),""===e&&(e=t),e},n.addNormal=function(e){let t=e._text||"";t=n.normalize(t),r(e._text)&&(t=t.replace(/\./g,"")),t=t.replace(/([0-9]),([0-9])/g,"$1$2"),e.normal=t}},{"./isAcronym":148,"./unicode":151}],150:[function(e,t){"use strict";t.exports=function(e){let t=e.normal||e.silent_term||"";t=t.replace(/'s\b/,""),t=t.replace(/'$/,""),e.root=t}},{}],151:[function(e,t){"use strict";let n={"!":"\xA1","?":"\xBF\u0241",'"':"\u201C\u201D\"\u275D\u275E","'":"\u2018\u201B\u275B\u275C","-":"\u2014\u2013",a:"\xAA\xC0\xC1\xC2\xC3\xC4\xC5\xE0\xE1\xE2\xE3\xE4\xE5\u0100\u0101\u0102\u0103\u0104\u0105\u01CD\u01CE\u01DE\u01DF\u01E0\u01E1\u01FA\u01FB\u0200\u0201\u0202\u0203\u0226\u0227\u023A\u0386\u0391\u0394\u039B\u03AC\u03B1\u03BB\u0410\u0414\u0430\u0434\u0466\u0467\u04D0\u04D1\u04D2\u04D3\u019B\u0245\xE6",b:"\xDF\xFE\u0180\u0181\u0182\u0183\u0184\u0185\u0243\u0392\u03B2\u03D0\u03E6\u0411\u0412\u042A\u042C\u0431\u0432\u044A\u044C\u0462\u0463\u048C\u048D\u0494\u0495\u01A5\u01BE",c:"\xA2\xA9\xC7\xE7\u0106\u0107\u0108\u0109\u010A\u010B\u010C\u010D\u0186\u0187\u0188\u023B\u023C\u037B\u037C\u037D\u03F2\u03F9\u03FD\u03FE\u03FF\u0404\u0421\u0441\u0454\u0480\u0481\u04AA\u04AB",d:"\xD0\u010E\u010F\u0110\u0111\u0189\u018A\u0221\u018B\u018C\u01F7",e:"\xC8\xC9\xCA\xCB\xE8\xE9\xEA\xEB\u0112\u0113\u0114\u0115\u0116\u0117\u0118\u0119\u011A\u011B\u018E\u018F\u0190\u01DD\u0204\u0205\u0206\u0207\u0228\u0229\u0246\u0247\u0388\u0395\u039E\u03A3\u03AD\u03B5\u03BE\u03F1\u03F5\u03F6\u0400\u0401\u0415\u042D\u0435\u0450\u0451\u04BC\u04BD\u04BE\u04BF\u04D6\u04D7\u04D8\u04D9\u04DA\u04DB\u04EC\u04ED",f:"\u0191\u0192\u03DC\u03DD\u04FA\u04FB\u0492\u0493\u04F6\u04F7\u017F",g:"\u011C\u011D\u011E\u011F\u0120\u0121\u0122\u0123\u0193\u01E4\u01E5\u01E6\u01E7\u01F4\u01F5",h:"\u0124\u0125\u0126\u0127\u0195\u01F6\u021E\u021F\u0389\u0397\u0402\u040A\u040B\u041D\u043D\u0452\u045B\u04A2\u04A3\u04A4\u04A5\u04BA\u04BB\u04C9\u04CA",I:"\xCC\xCD\xCE\xCF",i:"\xEC\xED\xEE\xEF\u0128\u0129\u012A\u012B\u012C\u012D\u012E\u012F\u0130\u0131\u0196\u0197\u0208\u0209\u020A\u020B\u038A\u0390\u03AA\u03AF\u03B9\u03CA\u0406\u0407\u0456\u0457",j:"\u0134\u0135\u01F0\u0237\u0248\u0249\u03F3\u0408\u0458",k:"\u0136\u0137\u0138\u0198\u0199\u01E8\u01E9\u039A\u03BA\u040C\u0416\u041A\u0436\u043A\u045C\u049A\u049B\u049C\u049D\u049E\u049F\u04A0\u04A1",l:"\u0139\u013A\u013B\u013C\u013D\u013E\u013F\u0140\u0141\u0142\u019A\u01AA\u01C0\u01CF\u01D0\u0234\u023D\u0399\u04C0\u04CF",m:"\u039C\u03FA\u03FB\u041C\u043C\u04CD\u04CE",n:"\xD1\xF1\u0143\u0144\u0145\u0146\u0147\u0148\u0149\u014A\u014B\u019D\u019E\u01F8\u01F9\u0220\u0235\u039D\u03A0\u03AE\u03B7\u03DE\u040D\u0418\u0419\u041B\u041F\u0438\u0439\u043B\u043F\u045D\u048A\u048B\u04C5\u04C6\u04E2\u04E3\u04E4\u04E5\u03C0",o:"\xD2\xD3\xD4\xD5\xD6\xD8\xF0\xF2\xF3\xF4\xF5\xF6\xF8\u014C\u014D\u014E\u014F\u0150\u0151\u019F\u01A0\u01A1\u01D1\u01D2\u01EA\u01EB\u01EC\u01ED\u01FE\u01FF\u020C\u020D\u020E\u020F\u022A\u022B\u022C\u022D\u022E\u022F\u0230\u0231\u038C\u0398\u039F\u03B8\u03BF\u03C3\u03CC\u03D5\u03D8\u03D9\u03EC\u03ED\u03F4\u041E\u0424\u043E\u0472\u0473\u04E6\u04E7\u04E8\u04E9\u04EA\u04EB\xA4\u018D\u038F",p:"\u01A4\u01BF\u03A1\u03C1\u03F7\u03F8\u03FC\u0420\u0440\u048E\u048F\xDE",q:"\u024A\u024B",r:"\u0154\u0155\u0156\u0157\u0158\u0159\u01A6\u0210\u0211\u0212\u0213\u024C\u024D\u0403\u0413\u042F\u0433\u044F\u0453\u0490\u0491",s:"\u015A\u015B\u015C\u015D\u015E\u015F\u0160\u0161\u01A7\u01A8\u0218\u0219\u023F\u03C2\u03DA\u03DB\u03DF\u03E8\u03E9\u0405\u0455",t:"\u0162\u0163\u0164\u0165\u0166\u0167\u01AB\u01AC\u01AD\u01AE\u021A\u021B\u0236\u023E\u0393\u03A4\u03C4\u03EE\u03EF\u0422\u0442\u0482\u04AC\u04AD",u:"\xB5\xD9\xDA\xDB\xDC\xF9\xFA\xFB\xFC\u0168\u0169\u016A\u016B\u016C\u016D\u016E\u016F\u0170\u0171\u0172\u0173\u01AF\u01B0\u01B1\u01B2\u01D3\u01D4\u01D5\u01D6\u01D7\u01D8\u01D9\u01DA\u01DB\u01DC\u0214\u0215\u0216\u0217\u0244\u03B0\u03BC\u03C5\u03CB\u03CD\u03D1\u040F\u0426\u0427\u0446\u045F\u04B4\u04B5\u04B6\u04B7\u04CB\u04CC\u04C7\u04C8",v:"\u03BD\u0474\u0475\u0476\u0477",w:"\u0174\u0175\u019C\u03C9\u03CE\u03D6\u03E2\u03E3\u0428\u0429\u0448\u0449\u0461\u047F",x:"\xD7\u03A7\u03C7\u03D7\u03F0\u0425\u0445\u04B2\u04B3\u04FC\u04FD\u04FE\u04FF",y:"\xDD\xFD\xFF\u0176\u0177\u0178\u01B3\u01B4\u0232\u0233\u024E\u024F\u038E\u03A5\u03AB\u03B3\u03C8\u03D2\u03D3\u03D4\u040E\u0423\u0443\u0447\u045E\u0470\u0471\u04AE\u04AF\u04B0\u04B1\u04EE\u04EF\u04F0\u04F1\u04F2\u04F3",z:"\u0179\u017A\u017B\u017C\u017D\u017E\u01A9\u01B5\u01B6\u0224\u0225\u0240\u0396\u03B6"},a={};Object.keys(n).forEach(function(e){n[e].split("").forEach(function(t){a[t]=e})});t.exports=(e)=>{let t=e.split("");return t.forEach((e,n)=>{a[e]&&(t[n]=a[e])}),t.join("")}},{}],152:[function(e,t){"use strict";const n=e("../../paths"),a=n.fns,r=n.tags;t.exports=(e)=>{let t="silver",n=Object.keys(e.tags);for(let a=0;a{return e.prototype.out=function(e){return s[e]||(e="text"),s[e](this)},e}},{"./client":152,"./renderHtml":154,"./server":155}],154:[function(e,t){"use strict";const n=(e)=>{const t={"<":"<",">":">","&":"&",'"':""","'":"'"," ":" "};return e.replace(/[<>&"' ]/g,function(e){return t[e]})},a=(e)=>{const t=/<(?:!--(?:(?:-*[^->])*--+|-?)|script\b(?:[^"'>]|"[^"]*"|'[^']*')*>[\s\S]*?<\/script\s*|style\b(?:[^"'>]|"[^"]*"|'[^']*')*>[\s\S]*?<\/style\s*|\/?[a-z](?:[^"'>]|"[^"]*"|'[^']*')*)>/gi;let n;do n=e,e=e.replace(t,"");while(e!==n);return e.replace(/"Term"!==e);t=t.map((e)=>"nl-"+e),t=t.join(" ");let r=a(e.text);r=n(r);let s=""+r+"";return n(e.whitespace.before)+s+n(e.whitespace.after)}},{}],155:[function(e,t){"use strict";const n=e("../../paths").fns;t.exports=function(e){let t=Object.keys(e.tags).map((e)=>{return n.printTag(e)}).join(", "),a=e.text;a="'"+n.yellow(a||"-")+"'";let r="";e.silent_term&&(r="["+e.silent_term+"]"),a=n.leftPad(a,20),a+=n.leftPad(r,8),console.log(" "+a+" - "+t)}},{"../../paths":161}],156:[function(e,t){"use strict";const n=/([a-z0-9 ])([,:;.!?]+)$/i;t.exports=(e)=>{const t={getPunctuation:function(){let e=this.text.match(n);return e?e[2]:(e=this.whitespace.after.match(n),e?e[2]:null)},setPunctuation:function(e){return this.killPunctuation(),this.text+=e,","===e&&(this.tags.Comma=!0),this},hasComma:function(){return","===this.getPunctuation()},killPunctuation:function(){return this.text=this._text.replace(n,"$1"),delete this.tags.Comma,delete this.tags.ClauseEnd,this}};return Object.keys(t).forEach((n)=>{e.prototype[n]=t[n]}),e}},{}],157:[function(e,t){"use strict";const n=function(e,t){const a=e.world.tags;if(a[t]===void 0)return!0;let r=a[t].notA||[];for(let n=0;n{const t={tag:function(e,t){!0!==s[e]&&n(this,e,t)},unTag:function(e,t){!0!==s[e]&&a(this,e,t)},canBe:function(e){if(e=e||"","string"==typeof e){if(!0===s[e])return!0;e=e.replace(/^#/,"")}return r(this,e)}};return Object.keys(t).forEach((n)=>{e.prototype[n]=t[n]}),e}},{"./canBe":157,"./setTag":159,"./unTag":160}],159:[function(e,t){"use strict";const n=e("../../paths"),a=n.log,r=n.fns,s=e("./unTag"),i=(e,t,n)=>{const r=e.world.tags;if((t=t.replace(/^#/,""),!0!==e.tags[t])&&(e.tags[t]=!0,a.tag(e,t,n),r[t])){let a=r[t].notA||[];for(let t=0;t "+t)}}};t.exports=function(e,t,n){if(e&&t){const a=e.world.tags;return r.isArray(t)?void t.forEach((a)=>i(e,a,n)):void(i(e,t,n),a[t]&&void 0!==a[t].also&&i(e,a[t].also,n))}}},{"../../paths":161,"./unTag":160}],160:[function(e,t){"use strict";const n=e("../../paths"),a=n.log,r=(e,t,n)=>{const s=e.world.tags;if(e.tags[t]&&(a.unTag(e,t,n),delete e.tags[t],s[t])){let n=s[t].downward;for(let t=0;t{if(e&&t){if("*"===t)return void(e.tags={});r(e,t,n)}}},{"../../paths":161}],161:[function(e,t){t.exports={fns:e("../fns"),log:e("../log"),tags:e("../tags")}},{"../fns":3,"../log":6,"../tags":137}],162:[function(e,t){"use strict";const n=/^(\s|-+|\.\.+|\/|"|\u0022|\uFF02|\u0027|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\u00AB|\u2039|\u2035|\u2036|\u2037|\u301D|\u0060|\u301F)+/u,a=/(\s+|-+|\.\.+|"|\u0022|\uFF02|\u0027|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4)+[,;.!? ]*$/u,r=/^( *)-(\$|€|¥|£)?([0-9])/;t.exports=(e)=>{let t={before:"",after:""},s=e.match(r);return null===s?(s=e.match(n),null!==s&&(t.before=s[0],e=e.replace(n,""))):(t.before=s[1],e=e.replace(/^ */,"")),s=e.match(a),null!==s&&(e=e.replace(a,""),t.after=s[0]),{whitespace:t,text:e}}},{}],163:[function(e,t){"use strict";const n=e("../term"),a=/\S/,r=/^[!?.]+$/,s={".":!0,"-":!0,"–":!0,"—":!0,"--":!0,"...":!0},o=function(e){if(!0===/^(re|un)-?[^aeiou]./.test(e))return!1;let t=/^([a-z`"'/]+)(-|–|—)([a-z0-9].*)/i;if(!0===t.test(e))return!0;let n=/^([0-9]+)(–|—)([0-9].*)/i;return!!n.test(e)},l=function(e){const t=/[a-z]\/[a-z]/;return t.test(e)&&2===e.split(/\//g).length};t.exports=function(e,i){let t=[],d=[];e=e||"","number"==typeof e&&(e+="");const u=e.split(/(\S+)/);for(let t=0;tnew n(e,i))}},{"../term":143}],164:[function(e,t){"use strict";t.exports={parent:{get:function(){return this.refText||this},set:function(e){return this.refText=e,this}},parentTerms:{get:function(){return this.refTerms||this},set:function(e){return this.refTerms=e,this}},dirty:{get:function(){for(let e=0;e{n.dirty=e})}},refTerms:{get:function(){return this._refTerms||this},set:function(e){return this._refTerms=e,this}},found:{get:function(){return 0{return this.firstTerm().whitespace.before=e,this},after:(e)=>{return this.lastTerm().whitespace.after=e,this}}}}}},{}],165:[function(e,t){"use strict";const n=e("./build"),a=e("./getters");let r=e("../world");const s=function(e,t,n,s){this.terms=e,this.world=t||r,this.refText=n,this._refTerms=s,this.get=(e)=>{return this.terms[e]};let o=Object.keys(a);for(let r=0;r{e.parentTerms=r}),r},e("./match")(s),e("./methods/tag")(s),e("./methods/loops")(s),e("./match/not")(s),e("./methods/delete")(s),e("./methods/insert")(s),e("./methods/misc")(s),e("./methods/out")(s),e("./methods/replace")(s),e("./methods/split")(s),e("./methods/transform")(s),e("./methods/lump")(s),t.exports=s},{"../world":215,"./build":163,"./getters":164,"./match":166,"./match/not":176,"./methods/delete":177,"./methods/insert":178,"./methods/loops":179,"./methods/lump":181,"./methods/misc":182,"./methods/out":183,"./methods/replace":184,"./methods/split":185,"./methods/tag":186,"./methods/transform":187}],166:[function(e,t){"use strict";const n=e("./lib/syntax"),a=e("./lib/startHere"),r=e("../../text"),s=e("./lib");t.exports=(e)=>{const t={match:function(t,n){if(0===this.terms.length)return new r([],this.world,this.parent);if(!t)return new r([],this.world,this.parent);let a=s(this,t,n);return a=a.map((t)=>{return new e(t,this.world,this.refText,this.refTerms)}),new r(a,this.world,this.parent)},matchOne:function(e){if(0===this.terms.length)return null;let r=n(e);for(let n=0,t;n{e.prototype[n]=t[n]}),e}},{"../../text":192,"./lib":170,"./lib/startHere":174,"./lib/syntax":175}],167:[function(e,t){"use strict";t.exports=(e,t)=>{e.captureGroup=!!t.capture||void 0}},{}],168:[function(e,t){"use strict";t.exports=function(e){let t=[];return e.forEach((e)=>{if(0===e.filter((e)=>!0===e.captureGroup).length)return void t.push(e);let n=[];for(let a=0;a{for(let n=0;n{return{id:e.uid}});return t};t.exports=(e,o,l)=>{if("string"==typeof o?o=n(o):o&&"Text"===o.isA?o=i(o.list[0]):o&&"Terms"===o.isA&&(o=i(o)),!o||0===o.length)return[];if(!0===r(e,o,l))return[];let d=[];for(let n=0,t;n{if(!e||!t)return!1;if(!0===t.anyOne)return!0;if(void 0!==t.tag)return e.tags[t.tag];if(void 0!==t.id)return t.id===e.uid;if(void 0!==t.normal)return t.normal===e.normal||t.normal===e.silent_term;if(!0===t.suffix&&void 0!==t.partial){const n=e.normal.length;return e.normal.substr(n-t.partial.length,n)===t.partial}if(!0===t.prefix&&void 0!==t.partial)return e.normal.substr(0,t.partial.length)===t.partial;if(!0===t.infix&&t.partial)return-1!==e.normal.indexOf(t.partial);if(void 0!==t.regex)return t.regex.test(e.normal)||t.regex.test(e.text);if(void 0!==t.oneOf){for(let n=0;n{if(!e||!t)return!1;let s=a(e,t,r);return t.negative&&(s=!!!s),s&&n(e,t),s}},{"./applyCaptureGroup":167}],172:[function(e,t){"use strict";const n=(e,t)=>{let n=t.normal.substr(0,e.length);return n===e};t.exports=function(e,t,a){let r=t[a].normal;if(r!==void 0&&n(r,e))for(++a,a;a{for(;t{for(;n{let d=t;for(let u=0;u=n&&a(i,s))break;let l=e.terms[d+o+1];if(l&&a(l,s)){d+=o+2,u+=1;break}else if(o===r-1)return null}continue}if(!0===c.optional){let t=o[u+1];d=i(e,d,c,t);continue}if(a(m,c,l)){if(d+=1,!0===c.consecutive){let t=o[u+1];d=i(e,d,c,t)}continue}if(m.silent_term&&!m.normal){if(0===u)return null;d+=1,u-=1;continue}let p=n(m,o,u,l);if(null!==p){u=p,d+=1;continue}if(!0!==c.optional)return null}return e.terms.slice(t,d)}},{"./applyCaptureGroup":167,"./isMatch":171,"./lumpMatch":172}],175:[function(e,t){"use strict";const n=e("./paths").fns,a=/\{[0-9,]+\}$/,r=function(e){return e.substr(1,e.length)},s=function(e){return e.substring(0,e.length-1)},i=function(e){e=e||"",e=e.trim();let t={};if(1===e.length&&"."!==e&&"*"!==e)return t.normal=e.toLowerCase(),t;if("!"===e.charAt(0)&&(e=r(e),t.negative=!0),"^"===e.charAt(0)&&(e=r(e),t.starting=!0),"$"===e.charAt(e.length-1)&&(e=s(e),t.ending=!0),"?"===e.charAt(e.length-1)&&(e=s(e),t.optional=!0),"+"===e.charAt(e.length-1)&&(e=s(e),t.consecutive=!0),"_"===e.charAt(e.length-1)?(e=s(e),t.prefix=!0,"_"===e.charAt(0)&&(e=r(e),t.prefix=void 0,t.infix=!0),t.partial=e,e=""):"_"===e.charAt(0)&&(e=r(e),t.suffix=!0,t.partial=e,e=""),"}"===e.charAt(e.length-1)&&!0===a.test(e)){let n=e.match(/\{([0-9])*,? ?([0-9]+)\}/);t.minMax={min:parseInt(n[1],10)||0,max:parseInt(n[2],10)},e=e.replace(a,"")}if("#"===e.charAt(0)&&(e=r(e),t.tag=n.titleCase(e),e=""),"/"===e.charAt(0)&&"/"===e.charAt(e.length-1)&&(e=s(e),e=r(e),t.regex=new RegExp(e,"i"),e=""),"("===e.charAt(0)&&")"===e.charAt(e.length-1)){e=s(e),e=r(e);let a=e.split(/\|/g);t.oneOf={terms:{},tagArr:[]},a.forEach((e)=>{if("#"===e.charAt(0)){let a=e.substr(1,e.length);a=n.titleCase(a),t.oneOf.tagArr.push(a)}else t.oneOf.terms[e]=!0}),e=""}return"."===e&&(t.anyOne=!0,e=""),"*"===e&&(t.astrix=!0,e=""),""!==e&&(e=e.replace(/\\([\\#\*\.\[\]\(\)\+\?\^])/g,""),t.normal=e.toLowerCase()),t};t.exports=function(e){e=e||"";let t=e.split(/ +/);for(let n=0;ne);let n=!1;return t=t.map((e)=>{let t=!1;return"["===e.charAt(0)&&(e=r(e),n=!0),"]"===e.charAt(e.length-1)&&(e=s(e),n=!1,t=!0),e=i(e),(!0==n||!0==t)&&(e.capture=!0),e}),t}},{"./paths":173}],176:[function(e,t){"use strict";const n=e("./lib/syntax"),a=e("./lib/startHere"),s=e("../../text");t.exports=(e)=>{const t={notObj:function(t,n){let a=[],r=[];return t.terms.forEach((e)=>{n.hasOwnProperty(e.normal)?(r.length&&a.push(r),r=[]):r.push(e)}),r.length&&a.push(r),a=a.map((n)=>{return new e(n,t.world,t.refText,t.refTerms)}),new s(a,t.world,t.parent)},notString:function(t,r,o){let l=[],d=n(r),u=[];for(let e=0,n;e{return new e(n,t.world,t.refText,t.refTerms)}),new s(l,t.world,t.parent)}};return t.notArray=function(e,n){let a=n.reduce((e,t)=>{return e[t]=!0,e},{});return t.notObj(e,a)},t.notText=function(e,n){let a=n.out("array");return t.notArray(e,a)},e.prototype.not=function(e,n){if("object"==typeof e){let a=Object.prototype.toString.call(e);if("[object Array]"===a)return t.notArray(this,e,n);if("[object Object]"===a)return"Text"===e.isA?t.notText(this,e,n):t.notObj(this,e,n)}return"string"==typeof e?t.notString(this,e,n):this},e}},{"../../text":192,"./lib/startHere":174,"./lib/syntax":175}],177:[function(e,t){"use strict";const n=e("../mutate");t.exports=(e)=>{return e.prototype.delete=function(e){if(!this.found)return this;if(!e)return this.parentTerms=n.deleteThese(this.parentTerms,this),this;let t=this.match(e);if(t.found){let e=n.deleteThese(this,t);return e}return this.parentTerms},e}},{"../mutate":188}],178:[function(e,t){"use strict";const n=e("../mutate"),a=(e,t)=>{return e.terms.length&&e.terms[t]?(e.terms[t].whitespace.before=" ",e):e};t.exports=(e)=>{const t=function(t,n){if("Terms"===t.isA)return t;if("Term"===t.isA)return new e([t],n);let a=e.fromString(t,n);return a.tagger(),a},r={insertBefore:function(e,r){let s=this.terms.length,i=t(e,this.world);r&&i.tag(r);let o=this.index();return a(this.parentTerms,o),0e&&(e=0);let i=this.terms.length,o=t(r,this.world);return s&&o.tag(s),0{e.prototype[t]=r[t]}),e}},{"../mutate":188}],179:[function(e,t){"use strict";t.exports=(e)=>{return[["toUpperCase","UpperCase"],["toLowerCase"],["toTitleCase","TitleCase"]].forEach((t)=>{let n=t[0],a=t[1];e.prototype[n]=function(){let e=arguments;return this.terms.forEach((a)=>{a[n].apply(a,e)}),a&&this.tag(a,n),this}}),e}},{}],180:[function(e,t){"use strict";const n=e("../../../term"),r=(e,t)=>{let n=e.whitespace.before+e.text+e.whitespace.after;return n+=t.whitespace.before+t.text+t.whitespace.after,n};t.exports=function(e,t){let s=e.terms[t],a=e.terms[t+1];if(a){let i=r(s,a);return e.terms[t]=new n(i,s.context),e.terms[t].normal=s.normal+" "+a.normal,e.terms[t].lumped=!0,e.terms[t].parentTerms=e.terms[t+1].parentTerms,e.terms[t+1]=null,void(e.terms=e.terms.filter((e)=>null!==e))}}},{"../../../term":143}],181:[function(e,t){"use strict";const n=e("./combine"),a=e("../../mutate"),r=function(e,t){let a=e.terms.length;for(let r=0;r{return e.prototype.lump=function(){let e=this.index(),t={};if(this.terms.forEach((e)=>{Object.keys(e.tags).forEach((e)=>t[e]=!0)}),this.parentTerms===this){let e=r(this,t);return this.terms=[e],this}this.parentTerms=a.deleteThese(this.parentTerms,this);let n=r(this,t);return this.parentTerms.terms=a.insertAt(this.parentTerms.terms,e,n),this},e}},{"../../mutate":188,"./combine":180}],182:[function(e,t){"use strict";const n=e("../../tagger");t.exports=(e)=>{const t={tagger:function(){return n(this),this},firstTerm:function(){return this.terms[0]},lastTerm:function(){return this.terms[this.terms.length-1]},all:function(){return this.parent},data:function(){return{text:this.out("text"),normal:this.out("normal")}},term:function(e){return this.terms[e]},first:function(){let n=this.terms[0];return new e([n],this.world,this.refText,this.refTerms)},last:function(){let n=this.terms[this.terms.length-1];return new e([n],this.world,this.refText,this.refTerms)},slice:function(t,n){let a=this.terms.slice(t,n);return new e(a,this.world,this.refText,this.refTerms)},index:function(){let e=this.parentTerms,t=this.terms[0];if(!e||!t)return null;for(let n=0;n{return e+=n.whitespace.before.length,e+=n.text.length,e+=n.whitespace.after.length,e},0)},wordCount:function(){return this.terms.length},setPunctuation:function(e){let t=this.terms[this.terms.length-1];t.setPunctuation(e)},getPunctuation:function(){let e=this.last().terms[0];return e?e.getPunctuation()||"":""},toCamelCase:function(){return this.toTitleCase(),this.terms.forEach((e,t)=>{0!==t&&(e.whitespace.before=""),e.whitespace.after=""}),this.tag("#CamelCase","toCamelCase"),this}};return Object.keys(t).forEach((n)=>{e.prototype[n]=t[n]}),e}},{"../../tagger":95}],183:[function(e,t){"use strict";const n=e("../paths").fns,a={text:function(e){return e.terms.reduce((e,n)=>{return e+=n.out("text"),e},"")},match:function(e){let t="",n=e.terms.length;for(let a=0;a{return e.text});return t=t.map((e)=>{return e.normal}),t.join(" ")},grid:function(e){let t=" ";return t+=e.terms.reduce((e,a)=>{return e+=n.leftPad(a.text,11),e},""),t+"\n\n"},color:function(e){return e.terms.reduce((e,a)=>{return e+=n.printTerm(a),e},"")},csv:function(e){return e.terms.map((e)=>e.normal.replace(/,/g,"")).join(",")},newlines:function(e){return e.terms.reduce((e,n)=>{return e+=n.out("text").replace(/\n/g," "),e},"").replace(/^\s/,"")},root:function(e){return e.terms.map((e)=>e.silent_term||e.root).join(" ").toLowerCase()},html:function(e){return e.terms.map((e)=>e.render.html()).join(" ")},debug:function(e){e.terms.forEach((e)=>{e.out("debug")})},custom:function(e,n){return e.terms.map((e)=>{return Object.keys(n).reduce((t,a)=>{return n[a]&&e[a]&&("function"==typeof e[a]?t[a]=e[a]():t[a]=e[a]),t},{})})}};a.plaintext=a.text,a.normalize=a.normal,a.normalized=a.normal,a.colors=a.color,a.tags=a.terms;t.exports=(e)=>{return e.prototype.out=function(e){if("string"==typeof e){if(a[e])return a[e](this);}else if(!0===n.isObject(e))return a.custom(this,e);return a.text(this)},e.prototype.debug=function(){return a.debug(this)},e}},{"../paths":189}],184:[function(e,t){"use strict";const n=e("../mutate");t.exports=(e)=>{const t={replace:function(e,t,n){return void 0===t?this.replaceWith(e,n):(this.match(e).replaceWith(t,n),this)},replaceWith:function(t,a){let r=e.fromString(t,this.world);r.tagger(),a&&this.terms.forEach((e,t)=>{let n=Object.keys(e.tags);void 0!==r.terms[t]&&n.forEach((e)=>r.terms[t].tag(e,"from-memory"))});let s=this.getPunctuation(),i=this.index();return this.parentTerms=n.deleteThese(this.parentTerms,this),this.parentTerms.terms=n.insertAt(this.parentTerms.terms,i,r),this.terms=r.terms,0{e.prototype[n]=t[n]}),e}},{"../mutate":188}],185:[function(e,t,n){"use strict";const a=(e,t)=>{let n=t.terms[0],a=t.terms.length;for(let r=0;r{const t={splitAfter:function(t,n){let r=this.match(t,n),s=this.terms,i=[];return r.list.forEach((e)=>{let t=a(s,e);t.before&&t.match&&i.push(t.before.concat(t.match)),s=t.after}),s.length&&i.push(s),i=i.map((t)=>{let n=this.refText;return new e(t,this.world,n,this.refTerms)}),i},splitOn:function(t,n){let r=this.match(t,n),s=this.terms,i=[];return r.list.forEach((e)=>{let t=a(s,e);t.before&&i.push(t.before),t.match&&i.push(t.match),s=t.after}),s.length&&i.push(s),i=i.filter((e)=>e&&e.length),i=i.map((t)=>new e(t,this.world,t.refText,this.refTerms)),i},splitBefore:function(t,n){let r=this.match(t,n),s=this.terms,l=[];r.list.forEach((e)=>{let t=a(s,e);t.before&&l.push(t.before),t.match&&l.push(t.match),s=t.after}),s.length&&l.push(s);for(let e=0;ee&&e.length),l=l.map((t)=>new e(t,t.world,t.refText,this.refTerms)),l}};return Object.keys(t).forEach((n)=>{e.prototype[n]=t[n]}),e};t.exports=r,n=r},{}],186:[function(e,t){"use strict";t.exports=(e)=>{const t={tag:function(e,n){let a=[];return("string"==typeof e&&(a=e.split(" ")),1{e.tag(a[t],n)}),this):(this.terms.forEach((a)=>{a.tag(e,n)}),this)},unTag:function(e,n){let a=[];return("string"==typeof e&&(a=e.split(" ")),1{e.unTag(a[t],n)}),this):(this.terms.forEach((a)=>{a.unTag(e,n)}),this)},canBe:function(n){let t=this.terms.filter((e)=>e.canBe(n));return new e(t,this.world,this.refText,this.refTerms)}};return Object.keys(t).forEach((n)=>{e.prototype[n]=t[n]}),e}},{}],187:[function(e,t){"use strict";t.exports=(e)=>{const t={clone:function(){let t=this.terms.map((e)=>{return e.clone()});return new e(t,this.world,this.refText,null)},hyphenate:function(){return this.terms.forEach((e,t)=>{t!==this.terms.length-1&&(e.whitespace.after="-"),0!==t&&(e.whitespace.before="")}),this},dehyphenate:function(){return this.terms.forEach((e)=>{"-"===e.whitespace.after&&(e.whitespace.after=" ")}),this},trim:function(){return 0>=this.length?this:(this.terms[0].whitespace.before="",this.terms[this.terms.length-1].whitespace.after="",this)}};return Object.keys(t).forEach((n)=>{e.prototype[n]=t[n]}),e}},{}],188:[function(e,t,n){"use strict";const a=(e)=>{let t=[];return"Terms"===e.isA?t=e.terms:"Text"===e.isA?t=e.flatten().list[0].terms:"Term"===e.isA&&(t=[e]),t};n.deleteThese=(e,t)=>{let n=a(t);return e.terms=e.terms.filter((e)=>{for(let t=0;t{n.dirty=!0;let r=a(n);return 0{let r=[];s.isArray(e)?r=e:(e=s.ensureString(e),r=a(e));let o=r.map((e)=>i.fromString(e,t)),l=new n(o,t);return l.list.forEach((e)=>{e.refText=l}),l}},{"./index":192,"./paths":205,"./tokenize":207}],191:[function(e,t){t.exports={found:function(){return 0{return this.list.forEach((t)=>{t.whitespace.before(e)}),this},after:(e)=>{return this.list.forEach((t)=>{t.whitespace.after(e)}),this}}}}},{}],192:[function(e,t){"use strict";function n(e,t,n){this.list=e||[],"function"==typeof t&&(t=t()),this.world=()=>{return t},this.original=n;let r=Object.keys(a);for(let s=0;s{n.prototype[e]=function(t,n){let a=r[e],s=a.find(this,t,n);return new r[e](s.list,this.world,this.parent)}}),n.prototype.words=n.prototype.terms},{"../subset/acronyms":9,"../subset/adjectives":10,"../subset/adverbs":17,"../subset/contractions":23,"../subset/dates":25,"../subset/ngrams":35,"../subset/ngrams/endGrams":32,"../subset/ngrams/startGrams":36,"../subset/nouns":38,"../subset/people":49,"../subset/possessives":51,"../subset/sentences":52,"../subset/terms":58,"../subset/values":65,"../subset/verbs":75,"./getters":191,"./methods/loops":193,"./methods/match":194,"./methods/misc":195,"./methods/normalize":196,"./methods/out":197,"./methods/sort":202,"./methods/split":204,"./subsets":206}],193:[function(e,t){"use strict";const n=["toTitleCase","toUpperCase","toLowerCase","toCamelCase","hyphenate","dehyphenate","trim","insertBefore","insertAfter","insertAt","replace","replaceWith","delete","lump","tagger","unTag"];t.exports=(e)=>{n.forEach((t)=>{e.prototype[t]=function(){for(let e=0;e{const t=function(t,a,r){let s=[];a=n(a),t.list.forEach((e)=>{let t=e.match(a,r);t.list.forEach((e)=>{s.push(e)})});let i=t.parent||t;return new e(s,t.world(),i)},s=function(n,r){let s=[];return n.list.forEach((e)=>{e.terms.forEach((e)=>{!0===r.hasOwnProperty(e.normal)&&s.push(e)})}),s=s.map((e)=>{return new a([e],n.world(),n,e.parentTerms)}),new e(s,n.world(),n.parent)},i=function(e,t){let n=t.reduce((e,t)=>{return e[t]=!0,e},{});return s(e,n)},r=function(e,t){let n=t.out("array");return i(e,n)},o={match:function(n,a){if(0===this.list.length||void 0===n||null===n){let t=this.parent||this;return new e([],this.world(),t)}if("string"==typeof n||"number"==typeof n)return t(this,n,a);let o=Object.prototype.toString.call(n);return"[object Array]"===o?i(this,n):"[object Object]"===o?"Text"===n.isA?r(this,n):s(this,n):this},not:function(t,n){let a=[];this.list.forEach((e)=>{let r=e.not(t,n);a=a.concat(r.list)});let r=this.parent||this;return new e(a,this.world(),r)},if:function(t){let n=[];for(let e=0;e{const n={all:function(){return this.parent},index:function(){return this.list.map((e)=>e.index())},wordCount:function(){return this.terms().length},data:function(){return this.list.map((e)=>e.data())},map:function(e){return this.list.map((n,a)=>{let r=new t([n],this.world);return e(r,a)})},forEach:function(e){return this.list.forEach((n,a)=>{let r=new t([n],this.world);e(r,a)}),this},filter:function(e){let n=this.list.filter((n,a)=>{let r=new t([n],this.world);return e(r,a)});return new t(n,this.world)},reduce:function(e,n){return this.list.reduce((n,a)=>{let r=new t([a],this.world);return e(n,r)},n)},find:function(e){for(let n=0;n{return e.clone()});return new t(e,this.world)},term:function(e){let n=this.list.map((t)=>{let n=[],r=t.terms[e];return r&&(n=[r]),new a(n,this.world,this.refText,this.refTerms)});return new t(n,this.world,this.parent)},firstTerm:function(){return this.match("^.")},lastTerm:function(){return this.match(".$")},slice:function(e,t){return this.list=this.list.slice(e,t),this},get:function(e){if(!e&&0!==e||!this.list[e])return new t([],this.world,this.parent);let a=this.list[e];return new t([a],this.world,this.parent)},first:function(e){return e||0===e?new t(this.list.slice(0,e),this.world,this.parent):this.get(0)},last:function(e){if(!e&&0!==e)return this.get(this.list.length-1);let a=this.list.length;return new t(this.list.slice(a-e,a),this.world,this.parent)},concat:function(){for(let e=0,t;e{e=e.concat(t.terms)}),!e.length)return new t(null,this.world,this.parent);let n=new a(e,this.world,this,null);return new t([n],this.world,this.parent)},canBe:function(e){return this.list.forEach((t)=>{t.terms=t.terms.filter((n)=>{return n.canBe(e)})}),this},random:function(a){a=a||1;let n=e(Math.random()*this.list.length),r=this.list.slice(n,n+a);if(r.lengthn&&(e=n),r=r.concat(this.list.slice(0,e))}return new t(r,this.world,this.parent)},setPunctuation:function(e){return this.list.forEach((t)=>t.setPunctuation(e)),this},getPunctuation:function(e){return e||0===e?this.list[e]?this.list[e].getPunctuation():"":this.list.map((e)=>e.getPunctuation())},offset:function(){return this.out("offset")},text:function(){return this.out("text")}};n.eq=n.get,n.join=n.flatten,t.addMethods(t,n)}},{"../../terms":165}],196:[function(e,t){"use strict";const n=e("../../term/methods/normalize/unicode"),a={whitespace:!0,case:!0,numbers:!0,punctuation:!0,unicode:!0,contractions:!0,acronyms:!0,parentheses:!1,possessives:!1,plurals:!1,verbs:!1,honorifics:!1},r={whitespace:(e)=>{return e.terms().list.forEach((e,n)=>{let a=e.terms[0];0{return e.list.forEach((e)=>{e.terms.forEach((n,t)=>{0===t||n.tags.Person||n.tags.Place||n.tags.Organization||e.toLowerCase()})}),e},numbers:(e)=>{return e.values().toNumber(),e},punctuation:(e)=>{return e.list.forEach((e)=>{if(e.terms.length){e.terms[0]._text=e.terms[0]._text.replace(/^¿/,"");for(let n=0,a;n{return e.list.forEach((e)=>{e.terms.forEach((e)=>{e.text=n(e.text)})}),e},contractions:(e)=>{return e.contractions().expand(),e},acronyms:(e)=>{return e.acronyms().stripPeriods(),e},possessives:(e)=>{return e.possessives().strip(),e},parentheses:(e)=>{return e.parentheses().delete(),e},plurals:(e)=>{return e.nouns().toSingular(),e},verbs:(e)=>{return e.verbs().toInfinitive(),e},honorifics:(e)=>{return e=e.delete("#Honorific"),e}};t.exports=(e)=>{e.prototype.normalize=function(e){let t=this;e=e||{};let n=Object.assign({},a),s=Object.keys(e);return s.forEach((t)=>{n[t]=e[t]}),Object.keys(n).forEach((e)=>{n[e]&&void 0!==r[e]&&(t=r[e](t))}),t}}},{"../../term/methods/normalize/unicode":151}],197:[function(e,t){"use strict";const n=e("./topk"),a=e("./offset"),s=e("./indexes"),r=e("../paths").fns,i={text:(e)=>{return e.list.reduce((e,t)=>{return e+=t.out("text"),e},"")},match:(e)=>{return e.list.reduce((e,t)=>{return e+=t.out("match"),e},"")},normal:(e)=>{return e.list.map((e)=>{let t=e.out("normal"),n=e.last();if(n){let n=e.getPunctuation();("."===n||"!"===n||"?"===n)&&(t+=n)}return t}).join(" ")},root:(e)=>{return e.list.map((e)=>{return e.out("root")}).join(" ")},offsets:(e)=>{return a(e)},index:(e)=>{return s(e)},grid:(e)=>{return e.list.reduce((e,t)=>{return e+=t.out("grid"),e},"")},color:(e)=>{return e.list.reduce((e,t)=>{return e+=t.out("color"),e},"")},array:(e)=>{return e.list.map((e)=>{return e.out("normal")})},csv:(e)=>{return e.list.map((e)=>{return e.out("csv")}).join("\n")},newlines:(e)=>{return e.list.map((e)=>{return e.out("newlines")}).join("\n")},json:(e)=>{return e.list.reduce((e,t)=>{let n=t.terms.map((e)=>{return{text:e.text,normal:e.normal,tags:e.tag}});return e.push(n),e},[])},html:(e)=>{let t=e.list.reduce((e,t)=>{let n=t.terms.reduce((e,n)=>{return e+="\n "+n.out("html"),e},"");return e+="\n "+n+"\n "},"");return" "+t+"\n"},terms:(e)=>{let n=[];return e.list.forEach((e)=>{e.terms.forEach((e)=>{n.push({text:e.text,normal:e.normal,tags:Object.keys(e.tags)})})}),n},debug:(e)=>{return console.log("===="),e.list.forEach((e)=>{console.log(" --"),e.debug()}),e},topk:(e)=>{return n(e)},custom:(e,t)=>{return e.list.map((e)=>e.out(t))}};i.plaintext=i.text,i.normalized=i.normal,i.colors=i.color,i.tags=i.terms,i.offset=i.offsets,i.idexes=i.index,i.frequency=i.topk,i.freq=i.topk,i.arr=i.array;t.exports=(e)=>{return e.prototype.out=function(e){if("string"==typeof e){if(i[e])return i[e](this);}else if(!0===r.isObject(e))return i.custom(this,e);return i.text(this)},e.prototype.debug=function(){return i.debug(this)},e}},{"../paths":201,"./indexes":198,"./offset":199,"./topk":200}],198:[function(e,t){"use strict";t.exports=(e)=>{let n=[],a={};e.terms().list.forEach((e)=>{a[e.terms[0].uid]=!0});let r=0,t=e.all();return t.list.forEach((e,o)=>{e.terms.forEach((e,t)=>{void 0!==a[e.uid]&&n.push({text:e.text,normal:e.normal,term:r,sentence:o,sentenceTerm:t}),r+=1})}),n}},{}],199:[function(e,t){"use strict";const n=(e,n)=>{let a=0;for(let r=0;r=n.length)return e.out("normal");let a=n[0].normal;for(let r=1,s;r{let t=e.all();return e.list.map((e)=>{let r=[];for(let t=0;t{let t=e.out("root");n[t]=n[t]||0,n[t]+=1});let a=[];return Object.keys(n).forEach((e)=>{a.push({normal:e,count:n[e]})}),a.forEach((t)=>{t.percent=parseFloat((100*(t.count/e.list.length)).toFixed(2))}),a=a.sort((e,t)=>{return e.count>t.count?-1:1}),t&&(a=a.splice(0,t)),a}},{}],201:[function(e,t){t.exports=e("../paths")},{"../paths":205}],202:[function(e,t){"use strict";const n=e("./methods");t.exports=(e)=>{return e.addMethods(e,{sort:function(t){return t=t||"alphabetical",t=t.toLowerCase(),t&&"alpha"!==t&&"alphabetical"!==t?"chron"===t||"chronological"===t?n.chron(this,e):"length"===t?n.lengthFn(this,e):"freq"===t||"frequency"===t?n.freq(this,e):"wordcount"===t?n.wordCount(this,e):this:n.alpha(this,e)},reverse:function(){return this.list=this.list.reverse(),this},unique:function(){let e={};return this.list=this.list.filter((t)=>{let n=t.out("root");return!e.hasOwnProperty(n)&&(e[n]=!0,!0)}),this}}),e}},{"./methods":203}],203:[function(e,t,n){"use strict";const a=function(e){return e=e.sort((e,t)=>{return e.index>t.index?1:e.index===t.index?0:-1}),e.map((e)=>e.ts)};n.alpha=function(e){return e.list.sort((e,t)=>{if(e===t)return 0;if(e.terms[0]&&t.terms[0]){if(e.terms[0].root>t.terms[0].root)return 1;if(e.terms[0].roott.out("root")?1:-1}),e},n.chron=function(e){let t=e.list.map((e)=>{return{ts:e,index:e.termIndex()}});return e.list=a(t),e},n.lengthFn=function(e){let t=e.list.map((e)=>{return{ts:e,index:e.chars()}});return e.list=a(t).reverse(),e},n.wordCount=function(e){let t=e.list.map((e)=>{return{ts:e,index:e.length}});return e.list=a(t),e},n.freq=function(e){let t={};e.list.forEach((e)=>{let n=e.out("root");t[n]=t[n]||0,t[n]+=1});let n=e.list.map((e)=>{let n=t[e.out("root")]||0;return{ts:e,index:-1*n}});return e.list=a(n),e}},{}],204:[function(e,t){"use strict";t.exports=(e)=>{return e.addMethods(e,{splitAfter:function(e,t){let n=[];return this.list.forEach((a)=>{a.splitAfter(e,t).forEach((e)=>{n.push(e)})}),this.list=n,this},splitBefore:function(e,t){let n=[];return this.list.forEach((a)=>{a.splitBefore(e,t).forEach((e)=>{n.push(e)})}),this.list=n,this},splitOn:function(e,t){let n=[];return this.list.forEach((a)=>{a.splitOn(e,t).forEach((e)=>{n.push(e)})}),this.list=n,this}}),e}},{}],205:[function(e,t,n){arguments[4][201][0].apply(n,arguments)},{"../paths":8,dup:201}],206:[function(e,t){"use strict";const n=e("../subset/sentences/isQuestion");t.exports=(e)=>{const t={clauses:function(e){let t=this.splitAfter("#ClauseEnd");return"number"==typeof e&&(t=t.get(e)),t},hashTags:function(e){let t=this.match("#HashTag").terms();return"number"==typeof e&&(t=t.get(e)),t},organizations:function(e){let t=this.splitAfter("#Comma");return t=t.match("#Organization+"),"number"==typeof e&&(t=t.get(e)),t},phoneNumbers:function(e){let t=this.splitAfter("#Comma");return t=t.match("#PhoneNumber+"),"number"==typeof e&&(t=t.get(e)),t},places:function(e){let t=this.splitAfter("#Comma");return t=t.match("#Place+"),"number"==typeof e&&(t=t.get(e)),t},quotations:function(e){let t=this.match("#Quotation+"),a=[];return t.list.forEach((e)=>{let n=0,r=null;e.terms.forEach((s,t)=>{!0===s.tags.StartQuotation&&(0==n&&(r=t),n+=1),0n(e));return new e(r,this.world,this.parent)},statements:function(t){let a=this.all();"number"==typeof t&&(a=a.get(t));let r=a.list.filter((e)=>!1===n(e));return new e(r,this.world,this.parent)},parentheses:function(e){let t=this.match("#Parentheses+");return t=t.splitAfter("#EndBracket"),"number"==typeof e&&(t=t.get(e)),t}};return Object.keys(t).forEach((n)=>{e.prototype[n]=t[n]}),e}},{"../subset/sentences/isQuestion":53}],207:[function(e,t){"use strict";const n=Object.keys(e("../world/more-data/abbreviations")),a=new RegExp("\\b("+n.join("|")+")[.!?\u203D\u2E18\u203C\u2047-\u2049] *$","i"),r=/[ .][A-Z]\.? *$/i,s=/(?:\u2026|\.{2,}) *$/,i=/((?:\r?\n|\r)+)/,o=/(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g,l=/[a-z0-9\u0000-\u007F]/i,d=/\S/,u=function(e){let t=[],n=e.split(i);for(let a=0,r;a{this.conjugations[t]=this.conjugations[t]||{},this.words[t]=this.words[t]||"Infinitive",Object.keys(e[t]).forEach((n)=>{let a=e[t][n];this.conjugations[t][n]=a,this.words[a]=this.words[a]||n,this.cache.toInfinitive[e[t][n]]=t});let a=n(t,this);Object.keys(a).forEach((e)=>{let t=a[e];!1===this.words.hasOwnProperty(t)&&(this.words[t]=e)})}),e}},{"../subset/verbs/methods/conjugate/faster.js":79}],210:[function(e,t){t.exports=function(e){return Object.keys(e).forEach((t)=>{this.patterns[t]=e[t]}),e}},{}],211:[function(e,t){"use strict";t.exports=function(e){return Object.keys(e).forEach((t)=>{let n=e[t];this.plurals[t]=n,this.words[n]=this.words[n]||"Plural",this.words[t]=this.words[t]||"Singular",this.cache.toSingular[n]=t}),e}},{}],212:[function(e,t){t.exports=function(e){Object.keys(e).forEach((t)=>{this.regex.push({reg:new RegExp(t,"i"),tag:e[t]})})}},{}],213:[function(e,t){"use strict";const n=e("../tags/addDownward");t.exports=function(e){return Object.keys(e).forEach((t)=>{let n=e[t];n.notA=n.notA||[],n.downward=n.downward||[],this.tags[t]=n}),n(this.tags),e}},{"../tags/addDownward":135}],214:[function(e,t){"use strict";const n=e("../term/methods/normalize/normalize").normalize,a=e("../subset/nouns/methods/pluralize"),r=e("../subset/verbs/methods/conjugate/faster.js"),s=e("../subset/adjectives/methods"),i=/ /,o=function(e){return e=n(e),e=e.replace(/\s+/," "),e=e.replace(/[.\?,;\!]/g,""),e};t.exports=function(e){return Object.keys(e).forEach((t)=>{let n=e[t];if(t=o(t),this.words[t]=n,!0===i.test(t)){let e=t.split(i);this.cache.firstWords[e[0]]=!0}if("Singular"===n){let e=a(t,{});return void(e&&e!==t&&(this.words[e]="Plural"))}if("Infinitive"===n){let e=r(t,this);return void Object.keys(e).forEach((t)=>{this.words[e[t]]=t})}if("PhrasalVerb"===n){let e=t.split(/ /),n=r(e[0],this);return void Object.keys(n).forEach((t)=>{let a=n[t]+" "+e[1];this.words[a]="PhrasalVerb",this.cache.firstWords[n[t]]=!0})}if("Comparable"===n){let e=s.toComparative(t);e&&t!==e&&(this.words[e]="Comparative");let n=s.toSuperlative(t);n&&t!==n&&(this.words[n]="Superlative")}}),e}},{"../subset/adjectives/methods":11,"../subset/nouns/methods/pluralize":44,"../subset/verbs/methods/conjugate/faster.js":79,"../term/methods/normalize/normalize":149}],215:[function(e,t){"use strict";const n=e("../fns");let a=e("./_data"),r=e("./more-data"),s=e("../tags"),i=e("./unpack"),o=e("./addTags"),l=e("./addWords"),d=e("./addRegex"),u=e("./addConjugations"),m=e("./addPatterns"),c=e("./addPlurals"),h=e("./more-data/misc");const p=(e,t)=>{let n=Object.keys(t);for(let a=0;a{this[t]&&(e[t]=n.copy(this[t]))}),e},g.prototype.plugin=function(e){e=i(e),e.tags&&this.addTags(e.tags),e.regex&&this.addRegex(e.regex),e.patterns&&this.addPatterns(e.patterns),e.conjugations&&this.addConjugations(e.conjugations),e.plurals&&this.addPlurals(e.plurals),e.words&&this.addWords(e.words)};let f=new g;f.plugin(a),f.addWords(h),r.forEach((e)=>{p(f.words,e)}),t.exports={w:f,reBuild:function(){let e=new g;return e.plugin(a),e.addWords(h),r.forEach((t)=>{p(e.words,t)}),e}}},{"../fns":3,"../tags":137,"./_data":208,"./addConjugations":209,"./addPatterns":210,"./addPlurals":211,"./addRegex":212,"./addTags":213,"./addWords":214,"./more-data":217,"./more-data/misc":219,"./unpack":223}],216:[function(e,t){"use strict";let n={Noun:["arc","al","exp","fy","pd","pl","plz","tce","bl","ma","ba","lit","ex","eg","ie","ca","cca","vs","etc","esp","ft","bc","ad","md","corp","col"],Organization:["dept","univ","assn","bros","inc","ltd","co","yahoo","joomla","jeopardy"],Place:["rd","st","dist","mt","ave","blvd","cl","ct","cres","hwy","ariz","cal","calif","colo","conn","fla","fl","ga","ida","ia","kan","kans","minn","neb","nebr","okla","penna","penn","pa","dak","tenn","tex","ut","vt","va","wis","wisc","wy","wyo","usafa","alta","ont","que","sask"],Month:["jan","feb","mar","apr","jun","jul","aug","sep","sept","oct","nov","dec"],Date:["circa"],Honorific:["adj","adm","adv","asst","atty","bldg","brig","capt","cmdr","comdr","cpl","det","dr","esq","gen","gov","hon","jr","llb","lt","maj","messrs","mister","mlle","mme","mr","mrs","ms","mstr","op","ord","phd","prof","pvt","rep","reps","res","rev","sen","sens","sfc","sgt","sir","sr","supt","surg"],Value:["no"]},a={};const r=Object.keys(n);for(let s=0;s{let t=Object.keys(a[e]),l=Object.keys(n[e]);for(let n=0;n{let a=t.split(":"),r=a[0],s=a[1].split(","),o=r+s[0];"_"===s[0]&&(o=r),e[o]={};for(let r=1,i;r{if(!0==n){let n=e[r];n.forEach((e)=>{t[e]?("string"==typeof t[e]&&(t[e]=[t[e]]),t[e].push(r)):t[e]=r})}else t[r]=e[r];return t},{})}},{}],225:[function(e,t){"use strict";t.exports=function(e){return e.split(/,/g).reduce((e,t)=>{let n=t.split(/\|/g);return 3===n.length?e[n[0]+n[1]]=n[0]+n[2]:2===n.length?e[n[0]]=n[0]+n[1]:e[n[0]]=n[0],e},{})}},{}]},{},[4])(4)}); - diff --git a/builds/compromise.js b/builds/compromise.js index 7069398b3..f634c6d49 100644 --- a/builds/compromise.js +++ b/builds/compromise.js @@ -1,14773 +1,12423 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.nlp = f()}})(function(){var define,module,exports;return (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=e;n-=e,o++,e*=36);for(;o--;){const o=n%36;t=String.fromCharCode((o<10?48:55)+o)+t,n=(n-o)/36}return t},fromAlphaCode=function(n){if(void 0!==cache[n])return cache[n];let o=0,e=1,t=36,r=1;for(;e=0;e--,r*=36){let t=n.charCodeAt(e)-48;t>10&&(t-=7),o+=t*r}return o};var encoding={toAlphaCode:toAlphaCode,fromAlphaCode:fromAlphaCode},symbols=function(n){const o=new RegExp("([0-9A-Z]+):([0-9A-Z]+)");for(let e=0;e{let s=n.nodes[t];"!"===s[0]&&(o.push(r),s=s.slice(1));const c=s.split(/([A-Z0-9,]+)/g);for(let s=0;s{const e=o.split("¦");return n[e[0]]=e[1],n},{}),e={};return Object.keys(o).forEach(function(n){const t=unpack_1(o[n]);"true"===n&&(n=!0);for(let o=0;o (http://spencermounta.in)", - "name": "compromise", - "description": "natural language processing in the browser", - "version": "11.14.3", - "main": "./builds/compromise.js", - "unpkg": "./builds/compromise.min.js", - "types": "types", - "repository": { - "type": "git", - "url": "git://github.com/nlp-compromise/compromise.git" - }, - "scripts": { - "test": "tape \"./test/unit/**/*.test.js\" | tap-dancer", - "test:spec": "tape \"./test/unit/**/*.test.js\" | tap-spec", - "testb": "TESTENV=prod tape \"./test/unit/**/*.test.js\" | tap-dancer", - "buildTest": "TESTENV=prod node ./scripts/test.js", - "test:types": "dtslint types", - "browserTest": "node ./scripts/browserTest.js", - "benchmark": "node ./scripts/benchmark.js", - "build": "node ./scripts/build/index.js", - "pack": "node ./scripts/pack.js", - "prepublishOnly": "node ./scripts/prepublish && npm run test:types", - "postpublish": "node ./scripts/postpublish", - "watch": "amble ./scratch.js", - "filesize": "node ./scripts/lib/filesize.js", - "coverage": "node ./scripts/postpublish/coverage.js", - "lint": "node ./scripts/prepublish/linter.js" - }, - "files": [ - "builds/", - "docs/", - "types/index.d.ts" - ], - "prettier": { - "trailingComma": "none", - "tabWidth": 2, - "semi": true, - "singleQuote": true, - "printWidth": 100 - }, - "dependencies": { - "efrt-unpack": "2.2.0" - }, - "devDependencies": { - "@babel/core": "7.5.5", - "@babel/preset-env": "7.5.5", - "amble": "0.0.7", - "babelify": "10.0.0", - "babili": "0.1.4", - "browserify": "16.5.0", - "chalk": "2.4.2", - "codecov": "3.5.0", - "compromise-plugin": "0.0.9", - "derequire": "2.0.6", - "dtslint": "0.9.3", - "nyc": "14.1.1", - "shelljs": "0.8.3", - "tap-dancer": "0.2.0", - "tape": "4.11.0", - "terser": "4.2.1" - }, - "license": "MIT" -} - -},{}],3:[function(_dereq_,module,exports){ -'use strict'; - -function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.nlp = factory()); +}(this, (function () { 'use strict'; + + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } -var tagset = _dereq_('./tags'); // https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color + return _typeof(obj); + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } -var c = { - reset: '\x1b[0m', - red: '\x1b[31m', - green: '\x1b[32m', - yellow: '\x1b[33m', - blue: '\x1b[34m', - magenta: '\x1b[35m', - cyan: '\x1b[36m', - black: '\x1b[30m' -}; //dont use colors on client-side + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } -if (typeof module === 'undefined') { - Object.keys(c).forEach(function (k) { - c[k] = ''; - }); -} //coerce any input into a string + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } -exports.ensureString = function (input) { - if (typeof input === 'string') { - return input; - } else if (typeof input === 'number') { - return String(input); + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); } - return ''; -}; //coerce any input into a string + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; -exports.ensureObject = function (input) { - if (_typeof(input) !== 'object') { - return {}; + return _setPrototypeOf(o, p); } - if (input === null || input instanceof Array) { - return {}; + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; } - return input; -}; + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } -exports.titleCase = function (str) { - return str.charAt(0).toUpperCase() + str.substr(1); -}; //shallow-clone an object + return _assertThisInitialized(self); + } + //this is a not-well-thought-out way to reduce our dependence on `object===object` stuff + var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split(''); //generates a unique id for this term -exports.copy = function (o) { - var o2 = {}; - o = exports.ensureObject(o); - Object.keys(o).forEach(function (k) { - o2[k] = o[k]; - }); - return o2; -}; + function makeId(str) { + str = str || '_'; + var text = str + '-'; -exports.extend = function (obj, a) { - obj = exports.copy(obj); - var keys = Object.keys(a); + for (var i = 0; i < 7; i++) { + text += chars[Math.floor(Math.random() * chars.length)]; + } - for (var i = 0; i < keys.length; i++) { - obj[keys[i]] = a[keys[i]]; + return text; } - return obj; -}; //colorization + var _id = makeId; + //a hugely-ignorant, and widely subjective transliteration of latin, cryllic, greek unicode characters to english ascii. + //approximate visual (not semantic or phonetic) relationship between unicode and ascii characters + //http://en.wikipedia.org/wiki/List_of_Unicode_characters + //https://docs.google.com/spreadsheet/ccc?key=0Ah46z755j7cVdFRDM1A2YVpwa1ZYWlpJM2pQZ003M0E + var compact = { + '!': '¡', + '?': '¿Ɂ', + '"': '“”"❝❞', + "'": '‘‛❛❜', + '-': '—–', + a: 'ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАадѦѧӐӑӒӓƛɅæ', + b: 'ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬвъьѢѣҌҍ', + c: '¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾСсєҀҁҪҫ', + d: 'ÐĎďĐđƉƊȡƋƌǷ', + e: 'ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ', + f: 'ƑƒϜϝӺӻҒғſ', + g: 'ĜĝĞğĠġĢģƓǤǥǦǧǴǵ', + h: 'ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ', + I: 'ÌÍÎÏ', + i: 'ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії', + j: 'ĴĵǰȷɈɉϳЈј', + k: 'ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ', + l: 'ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ', + m: 'ΜϺϻМмӍӎ', + n: 'ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ', + o: 'ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ', + p: 'ƤƿΡρϷϸϼРрҎҏÞ', + q: 'Ɋɋ', + r: 'ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ', + s: 'ŚśŜŝŞşŠšƧƨȘșȿЅѕ', + t: 'ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮТт', + u: 'µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύ', + v: 'νѴѵѶѷ', + w: 'ŴŵƜωώϖϢϣШЩшщѡѿ', + x: '×ΧχϗϰХхҲҳӼӽӾӿ', + y: 'ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ', + z: 'ŹźŻżŽžƩƵƶȤȥɀΖζ' + }; //decompress data into two hashes -exports.green = function (str) { - return c.green + str + c.reset; -}; + var unicode = {}; + Object.keys(compact).forEach(function (k) { + compact[k].split('').forEach(function (s) { + unicode[s] = k; + }); + }); -exports.red = function (str) { - return c.red + str + c.reset; -}; + var killUnicode = function killUnicode(str) { + var chars = str.split(''); + chars.forEach(function (s, i) { + if (unicode[s]) { + chars[i] = unicode[s]; + } + }); + return chars.join(''); + }; -exports.blue = function (str) { - return c.blue + str + c.reset; -}; + var unicode_1 = killUnicode; // console.log(killUnicode('bjŏȒk—Ɏó')); -exports.magenta = function (str) { - return c.magenta + str + c.reset; -}; + var periodAcronym = /([A-Z]\.)+[A-Z]?,?$/; + var oneLetterAcronym = /^[A-Z]\.,?$/; + var noPeriodAcronym = /[A-Z]{2,}('s|,)?$/; + var lowerCaseAcronym = /([a-z]\.){2,}[a-z]\.?$/; -exports.cyan = function (str) { - return c.cyan + str + c.reset; -}; + var isAcronym = function isAcronym(str) { + //like N.D.A + if (periodAcronym.test(str) === true) { + return true; + } //like c.e.o -exports.yellow = function (str) { - return c.yellow + str + c.reset; -}; -exports.black = function (str) { - return c.black + str + c.reset; -}; + if (lowerCaseAcronym.test(str) === true) { + return true; + } //like 'F.' -exports.printTag = function (tag) { - if (tagset[tag]) { - var color = tagset[tag].color || 'blue'; - return exports[color](tag); - } - return tag; -}; + if (oneLetterAcronym.test(str) === true) { + return true; + } //like NDA -exports.printTerm = function (t) { - var tags = Object.keys(t.tags); - for (var i = 0; i < tags.length; i++) { - if (tagset[tags[i]]) { - var color = tagset[tags[i]].color || 'black'; - return exports[color](t.out('text')); + if (noPeriodAcronym.test(str) === true) { + return true; } - } - return c.reset + t.plaintext + c.reset; -}; + return false; + }; -exports.leftPad = function (str, width, _char) { - _char = _char || ' '; - str = str.toString(); + var isAcronym_1 = isAcronym; - while (str.length < width) { - str += _char; - } + var hasSlash = /[a-z\u00C0-\u00FF] ?\/ ?[a-z\u00C0-\u00FF]/; + /** some basic operations on a string to reduce noise */ - return str; -}; + var clean = function clean(str) { + str = str || ''; + str = str.toLowerCase(); + str = str.trim(); + var original = str; //(very) rough ASCII transliteration - bjŏrk -> bjork -exports.isArray = function (arr) { - return Object.prototype.toString.call(arr) === '[object Array]'; -}; + str = unicode_1(str); //rough handling of slashes - 'see/saw' -exports.isObject = function (obj) { - return obj === Object(obj); -}; + if (hasSlash.test(str) === true) { + str = str.replace(/\/.*/, ''); + } //#tags, @mentions -},{"./tags":137}],4:[function(_dereq_,module,exports){ -(function (global){ -'use strict'; -var buildText = _dereq_('./text/build'); + str = str.replace(/^[#@]/, ''); //punctuation -var pkg = _dereq_('../package.json'); + str = str.replace(/[,;.!?]+$/, ''); // coerce single curly quotes -var log = _dereq_('./log'); + str = str.replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g, "'"); // coerce double curly quotes -var unpack = _dereq_('./world/unpack'); + str = str.replace(/[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g, '"'); //coerce Unicode ellipses -var world = _dereq_('./world'); + str = str.replace(/\u2026/g, '...'); //en-dash -var w = world.w; //the main function + str = str.replace(/\u2013/g, '-'); //lookin'->looking (make it easier for conjugation) -var nlp = function nlp(str, lex) { - if (lex) { - w.plugin({ - words: lex - }); - } + if (/[a-z][^aeiou]in['’]$/.test(str) === true) { + str = str.replace(/in['’]$/, 'ing'); + } //turn re-enactment to reenactment - var doc = buildText(str, w); - doc.tagger(); - return doc; -}; //this is used, atleast, for testing the packing + if (/^(re|un)-?[^aeiou]./.test(str) === true) { + str = str.replace('-', ''); + } //strip leading & trailing grammatical punctuation -nlp.unpack = function (plugin) { - return unpack(plugin); -}; //this is handy + if (/^[:;]/.test(str) === false) { + str = str.replace(/\.{3,}$/g, ''); + str = str.replace(/[",\.!:;\?\)]+$/g, ''); + str = str.replace(/^['"\(]+/g, ''); + } //do this again.. -nlp.version = pkg.version; //turn-on some debugging -nlp.verbose = function (str) { - log.enable(str); -}; //same as main method, except with no POS-tagging. + str = str.trim(); //oh shucks, + if (str === '') { + str = original; + } //compact acronyms -nlp.tokenize = function (str) { - return buildText(str); -}; //uncompress user-submitted lexicon + if (isAcronym_1(str)) { + str = str.replace(/\./g, ''); + } //nice-numbers -nlp.plugin = function (plugin) { - w.plugin(plugin); -}; //contribute words to the lexicon + str = str.replace(/([0-9]),([0-9])/g, '$1$2'); + return str; + }; -nlp.addWords = function (lex) { - w.plugin({ - words: lex - }); -}; + var clean_1 = clean; // console.log(normalize('Dr. V Cooper')); -nlp.addTags = function (tags) { - w.plugin({ - tags: tags - }); -}; + /** reduced is one step further than clean */ + var reduced = function reduced(str) { + // remove apostrophes + str = str.replace(/['’]s$/, ''); + str = str.replace(/s['’]$/, 's'); + return str; + }; -nlp.addRegex = function (regex) { - w.plugin({ - regex: regex - }); -}; + var reduce = reduced; -nlp.addPatterns = function (patterns) { - w.plugin({ - patterns: patterns - }); -}; + //all punctuation marks, from https://en.wikipedia.org/wiki/Punctuation + //we have slightly different rules for start/end - like #hashtags. -nlp.addPlurals = function (plurals) { - w.plugin({ - plurals: plurals - }); -}; + var startings = /^[ \n\t\.’'\[\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\-?‘’;\/⁄·\&*\•^†‡°¡¿※№÷׺ª%‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\u0022|\uFF02|\u0027|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\u00AB|\u2039|\u2035|\u2036|\u2037|\u301D|\u0060|\u301F]+/; + var endings = /[ \n\t\.’'\[\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\-?‘’;\/⁄·\&*@\•^†‡°¡¿※#№÷׺ª‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\u0022|\uFF02|\u0027|\u201D|\u2019|\u201D|\u2019|\u201D|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4|\u301E]+$/; //money = ₵¢₡₢$₫₯֏₠€ƒ₣₲₴₭₺₾ℳ₥₦₧₱₰£៛₽₹₨₪৳₸₮₩¥ -nlp.addConjugations = function (conj) { - w.plugin({ - conjugations: conj - }); -}; //make a weird, half-copy of this method + var hasSlash$1 = /\//; + var hasApostrophe = /['’]/; + var minusNumber = /^[-+\.][0-9]/; + /** turn given text into a parsed-up object + * seperate the 'meat' of the word from the whitespace+punctuation + */ + + var parseTerm = function parseTerm(str) { + var original = str; + var pre = ''; + var post = ''; + str = str.replace(startings, function (found) { + pre = found; // support '-40' + + if ((pre === '-' || pre === '+' || pre === '.') && minusNumber.test(str)) { + pre = ''; + return found; + } + + return ''; + }); + str = str.replace(endings, function (found) { + post = found; // keep s-apostrophe - "flanders'" or "chillin'" + if (hasApostrophe.test(found) && /[sn]['’]$/.test(original) && hasApostrophe.test(pre) === false) { + post = post.replace(hasApostrophe, ''); + return "'"; + } -nlp.clone = function () { - var w2 = world.reBuild(); //this is weird, but it's okay + return ''; + }); //we went too far.. - var nlp2 = function nlp2(str, lex) { - if (lex) { - w2.plugin({ - words: lex + if (str === '') { + // do a very mild parse, and hope for the best. + original = original.replace(/ *$/, function (after) { + post = after || ''; + return ''; + }); + str = original; + pre = ''; + post = post; + } // create the various forms of our text, + + + var clean = clean_1(str); + var parsed = { + text: str, + clean: clean, + reduced: reduce(clean), + pre: pre, + post: post + }; // support aliases for slashes + + if (hasSlash$1.test(str)) { + str.split(hasSlash$1).forEach(function (word) { + parsed.alias = parsed.alias || {}; + parsed.alias[word.trim()] = true; }); } - var doc = buildText(str, w2); - doc.tagger(); - return doc; + return parsed; }; - nlp2.tokenize = nlp.tokenize; - nlp2.verbose = nlp.verbose; - nlp2.version = nlp.version; - ['Words', 'Tags', 'Regex', 'Patterns', 'Plurals', 'Conjugations'].forEach(function (fn) { - nlp2['add' + fn] = function (obj) { - w2['add' + fn](obj); - }; - }); - return nlp2; -}; //and then all-the-exports... - - -if (typeof self !== 'undefined') { - self.nlp = nlp; // Web Worker -} else if (typeof window !== 'undefined') { - window.nlp = nlp; // Browser -} else if (typeof global !== 'undefined') { - global.nlp = nlp; // NodeJS -} //don't forget amd! - - -if (typeof define === 'function' && define.amd) { - define(nlp); -} //then for some reason, do this too! - - -if (typeof module !== 'undefined') { - module.exports = nlp; -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../package.json":2,"./log":6,"./text/build":190,"./world":215,"./world/unpack":223}],5:[function(_dereq_,module,exports){ -'use strict'; - -var fns = _dereq_('../fns'); // const colors = { -// 'Person': '#6393b9', -// 'Pronoun': '#81acce', -// 'Noun': 'steelblue', -// 'Verb': 'palevioletred', -// 'Adverb': '#f39c73', -// 'Adjective': '#b3d3c6', -// 'Determiner': '#d3c0b3', -// 'Preposition': '#9794a8', -// 'Conjunction': '#c8c9cf', -// 'Value': 'palegoldenrod', -// 'Expression': '#b3d3c6' -// }; - - -var tag = function tag(t, pos, reason) { - var title = t.normal || '[' + t.silent_term + ']'; - title = fns.leftPad('\'' + title + '\'', 12); - title += ' -> ' + pos; - title += fns.leftPad(reason || '', 15); - console.log('%c' + title, ' color: #a2c99c'); -}; - -var untag = function untag(t, pos, reason) { - var title = t.normal || '[' + t.silent_term + ']'; - title = fns.leftPad('\'' + title + '\'', 12); - title += ' ~* ' + pos; - title += ' ' + (reason || ''); - console.log('%c' + title, ' color: #b66a6a'); -}; - -module.exports = { - tag: tag, - untag: untag -}; - -},{"../fns":3}],6:[function(_dereq_,module,exports){ -'use strict'; - -var client = _dereq_('./client'); - -var server = _dereq_('./server'); - -var _enable = false; -module.exports = { - enable: function enable(str) { - if (str === undefined) { - str = true; - } - - _enable = str; - }, - tag: function tag(t, pos, reason) { - if (_enable === true || _enable === 'tagger') { - if (typeof window !== 'undefined') { - client.tag(t, pos, reason); - } else { - server.tag(t, pos, reason); - } - } - }, - unTag: function unTag(t, pos, reason) { - if (_enable === true || _enable === 'tagger') { - if (typeof window !== 'undefined') { - client.untag(t, pos, reason); - } else { - server.untag(t, pos, reason); - } - } + var parse = parseTerm; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; } -}; -},{"./client":5,"./server":7}],7:[function(_dereq_,module,exports){ -'use strict'; + var _01Case = createCommonjsModule(function (module, exports) { + var titleCase = /^[A-Z][a-z'\u00C0-\u00FF]/; + var upperCase = /^[A-Z]+s?$/; + /** convert all text to uppercase */ -var fns = _dereq_('../fns'); //use weird bash escape things for some colors + exports.toUpperCase = function () { + this.text = this.text.toUpperCase(); + return this; + }; + /** convert all text to lowercase */ -var tag = function tag(t, pos, reason) { - var title = t.normal || '[' + t.silent_term + ']'; - title = fns.yellow(title); - title = fns.leftPad('\'' + title + '\'', 20); - title += ' -> ' + fns.printTag(pos); - title = fns.leftPad(title, 54); - console.log(' ' + title + '(' + fns.cyan(reason || '') + ')'); -}; + exports.toLowerCase = function () { + this.text = this.text.toLowerCase(); + return this; + }; + /** only set the first letter to uppercase + * leave any existing uppercase alone + */ -var untag = function untag(t, pos, reason) { - var title = '-' + t.normal + '-'; - title = fns.red(title); - title = fns.leftPad(title, 20); - title += ' ~* ' + fns.red(pos); - title = fns.leftPad(title, 54); - console.log(' ' + title + '(' + fns.red(reason || '') + ')'); -}; -module.exports = { - tag: tag, - untag: untag -}; + exports.toTitleCase = function () { + this.text = this.text.replace(/^ *[a-z\u00C0-\u00FF]/, function (x) { + return x.toUpperCase(); + }); //support unicode? -},{"../fns":3}],8:[function(_dereq_,module,exports){ -"use strict"; + return this; + }; + /** if all letters are uppercase */ -module.exports = { - fns: _dereq_('./fns'), - Terms: _dereq_('./terms') -}; -},{"./fns":3,"./terms":165}],9:[function(_dereq_,module,exports){ -'use strict'; + exports.isUpperCase = function () { + return upperCase.test(this.text); + }; + /** if the first letter is uppercase, and the rest are lowercase */ -var Text = _dereq_('../../text'); //the Acronym() subset class + exports.isTitleCase = function () { + return titleCase.test(this.text); + }; -var methods = { - stripPeriods: function stripPeriods() { - this.list.forEach(function (ts) { - ts.terms.forEach(function (t) { - var chars = t._text.split('.'); + exports.titleCase = exports.isTitleCase; + }); + var _01Case_1 = _01Case.toUpperCase; + var _01Case_2 = _01Case.toLowerCase; + var _01Case_3 = _01Case.toTitleCase; + var _01Case_4 = _01Case.isUpperCase; + var _01Case_5 = _01Case.isTitleCase; + var _01Case_6 = _01Case.titleCase; + + // these methods are called with '@hasComma' in the match syntax + // various unicode quotation-mark formats + var startQuote = "(\"|\uFF02|'|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\xAB|\u2039|\u2035|\u2036|\u2037|\u301D|`|\u301F)"; + var endQuote = "(\"|\uFF02|'|\u201D|\u2019|\u201D|\u2019|\u201D|\u201D|\u2019|\xBB|\u203A|\u2032|\u2033|\u2034|\u301E|\xB4|\u301E)"; + /** search the term's 'post' punctuation */ + + var hasPost = function hasPost(punct) { + return this.post.indexOf(punct) !== -1; + }; + /** search the term's 'pre' punctuation */ - if (chars.length > 2) { - t.text = chars.join(''); - } - }); - }); - return this; - }, - addPeriods: function addPeriods() { - this.list.forEach(function (ts) { - ts.terms.forEach(function (t) { - var chars = t._text.split('.'); - if (chars.length > 2) { - var str = t._text.replace(/\./g, ''); + var hasPre = function hasPre(punct) { + return this.pre.indexOf(punct) !== -1; + }; + /** does it have a quotation symbol? */ - t.text = str.split('').join('.') + '.'; - } - }); - }); - return this; - }, - data: function data() { - return this.terms().list.map(function (ts) { - var t = ts.terms[0]; - var parsed = t.text.toUpperCase().replace(/\./g, '').split(''); - return { - periods: parsed.join('.'), - normal: parsed.join(''), - text: t.text - }; - }); - } -}; -var find = function find(r, n) { - r = r.match('#Acronym'); + var hasQuote = function hasQuote() { + return startQuote.test(this.pre) || endQuote.test(this.post); + }; + /** does it have a comma? */ - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; + var hasComma = function hasComma() { + return this.hasPost(','); + }; + /** does it end in a period? */ -module.exports = Text.makeSubset(methods, find); -},{"../../text":192}],10:[function(_dereq_,module,exports){ -'use strict'; + var hasPeriod = function hasPeriod() { + return this.hasPost('.') === true && this.hasPost('...') === false; + }; + /** does it end in an exclamation */ -var Text = _dereq_('../../text'); -var fns = _dereq_('./methods'); //the Adjectives() subset class -//is this an adjective we want to goof-around with? + var hasExclamation = function hasExclamation() { + return this.hasPost('!'); + }; + /** does it end with a question mark? */ -var shouldConvert = function shouldConvert(str, words) { - if (!str || str.length <= 3) { - return false; - } + var hasQuestionMark = function hasQuestionMark() { + return this.hasPost('?') || this.hasPost('¿'); + }; + /** is there a ... at the end? */ - if (words[str] === 'Comparable') { - return true; - } - if (words[str] === 'Adjective') { - return false; - } //has space + var hasEllipses = function hasEllipses() { + return this.hasPost('..') || this.hasPost('…'); + }; + /** is there a semicolon after this word? */ - if (str.indexOf(' ') !== -1) { - return false; - } + var hasSemicolon = function hasSemicolon() { + return this.hasPost(';'); + }; + /** is there a slash '/' in this word? */ - return true; -}; -var methods = { - data: function data() { - var _this = this; + var hasSlash$2 = function hasSlash() { + return /\//.test(this.text); + }; + /** a hyphen connects two words like-this */ - return this.list.map(function (ts) { - var str = ts.out('normal'); - var obj = { - normal: str, - text: _this.out('text'), - comparative: 'more ' + str, - superlative: 'most ' + str, - adverbForm: null, - nounForm: null // verbForm: null - }; + var hasHyphen = function hasHyphen() { + var hyphen = /(-|–|—)/; + return hyphen.test(this.post) || hyphen.test(this.pre); + }; + /** a dash separates words - like that */ - if (shouldConvert(str, _this.world().words) === true) { - obj.comparative = fns.toComparative(str) || obj.comparative; - obj.superlative = fns.toSuperlative(str) || obj.superlative; - obj.adverbForm = fns.toAdverb(str); - obj.nounForm = fns.toNoun(str); // obj.verbForm = fns.toVerb(str); - } - return obj; - }); - } -}; + var hasDash = function hasDash() { + var hyphen = / (-|–|—) /; + return hyphen.test(this.post) || hyphen.test(this.pre); + }; + /** is it multiple words combinded */ -var find = function find(r, n) { - r = r.match('#Adjective'); - if (typeof n === 'number') { - r = r.get(n); - } + var hasContraction = function hasContraction() { + return Boolean(this.implicit); + }; + /** try to sensibly put this punctuation mark into the term */ - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./methods":11}],11:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = { - toNoun: _dereq_('./toNoun'), - toSuperlative: _dereq_('./toSuperlative'), - toComparative: _dereq_('./toComparative'), - toAdverb: _dereq_('./toAdverb'), - toVerb: _dereq_('./toVerb') -}; - -},{"./toAdverb":12,"./toComparative":13,"./toNoun":14,"./toSuperlative":15,"./toVerb":16}],12:[function(_dereq_,module,exports){ -//turn 'quick' into 'quickly' -'use strict'; - -var not_matches = [/airs$/, /ll$/, /ee.$/, /ile$/, /y$/]; - -var irregulars = _dereq_('../../../world/more-data/irregularAdjectives').toAdverb; - -var transforms = [{ - reg: /al$/i, - repl: 'ally' -}, { - reg: /ly$/i, - repl: 'ly' -}, { - reg: /(.{3})y$/i, - repl: '$1ily' -}, { - reg: /que$/i, - repl: 'quely' -}, { - reg: /ue$/i, - repl: 'uly' -}, { - reg: /ic$/i, - repl: 'ically' -}, { - reg: /ble$/i, - repl: 'bly' -}, { - reg: /l$/i, - repl: 'ly' -}]; - -var adj_to_adv = function adj_to_adv(str) { - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - for (var i = 0; i < not_matches.length; i++) { - if (not_matches[i].test(str) === true) { - return null; + var addPunctuation = function addPunctuation(punct) { + // dont add doubles + if (punct === ',' || punct === ';') { + this.post = this.post.replace(punct, ''); } - } - for (var _i = 0; _i < transforms.length; _i++) { - if (transforms[_i].reg.test(str) === true) { - return str.replace(transforms[_i].reg, transforms[_i].repl); - } - } + this.post = punct + this.post; + return this; + }; - return str + 'ly'; -}; // console.log(adj_to_adv('good')); + var _02Punctuation = { + hasPost: hasPost, + hasPre: hasPre, + hasQuote: hasQuote, + hasComma: hasComma, + hasPeriod: hasPeriod, + hasExclamation: hasExclamation, + hasQuestionMark: hasQuestionMark, + hasEllipses: hasEllipses, + hasSemicolon: hasSemicolon, + hasSlash: hasSlash$2, + hasHyphen: hasHyphen, + hasDash: hasDash, + hasContraction: hasContraction, + addPunctuation: addPunctuation + }; + //declare it up here + var wrapMatch = function wrapMatch() {}; + /** ignore optional/greedy logic, straight-up term match*/ -module.exports = adj_to_adv; -},{"../../../world/more-data/irregularAdjectives":218}],13:[function(_dereq_,module,exports){ -//turn 'quick' into 'quickly' -'use strict'; + var doesMatch = function doesMatch(t, reg, index, length) { + // support id matches + if (reg.id === t.id) { + return true; + } // support '.' -var do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /old$/, /oud$/, /e[ae]p$/]; -var dont_rules = [/ary$/, /ous$/]; -var irregulars = _dereq_('../../../world/more-data/irregularAdjectives').toComparative; + if (reg.anything === true) { + return true; + } // support '^' (in parentheses) -var transforms = [{ - reg: /y$/i, - repl: 'ier' -}, { - reg: /([aeiou])t$/i, - repl: '$1tter' -}, { - reg: /([aeou])de$/i, - repl: '$1der' -}, { - reg: /nge$/i, - repl: 'nger' -}]; -var to_comparative = function to_comparative(str) { - //known-irregulars - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } //known-transforms + if (reg.start === true && index !== 0) { + return false; + } // support '$' (in parentheses) - for (var i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } //dont-patterns + if (reg.end === true && index !== length - 1) { + return false; + } //support a text match - for (var _i = 0; _i < dont_rules.length; _i++) { - if (dont_rules[_i].test(str) === true) { - return null; - } - } //do-patterns + if (reg.word !== undefined) { + //match contractions + if (t.implicit !== null && t.implicit === reg.word) { + return true; + } // term aliases for slashes and things - for (var _i2 = 0; _i2 < do_rules.length; _i2++) { - if (do_rules[_i2].test(str) === true) { - return str + 'er'; - } - } //easy-one + if (t.alias !== undefined && t.alias.hasOwnProperty(reg.word)) { + return true; + } // support ~ match - if (/e$/.test(str) === true) { - return str + 'r'; - } + if (reg.soft === true && reg.word === t.root) { + return true; + } //match either .clean or .text - return str + 'er'; // return null; -}; // console.log(to_comparative('big')); - - -module.exports = to_comparative; - -},{"../../../world/more-data/irregularAdjectives":218}],14:[function(_dereq_,module,exports){ -'use strict'; //convert 'cute' to 'cuteness' - -var irregulars = { - clean: 'cleanliness', - naivety: 'naivety', - hurt: 'hurt' -}; -var transforms = [{ - reg: /y$/, - repl: 'iness' -}, { - reg: /le$/, - repl: 'ility' -}, { - reg: /ial$/, - repl: 'y' -}, { - reg: /al$/, - repl: 'ality' -}, { - reg: /ting$/, - repl: 'ting' -}, { - reg: /ring$/, - repl: 'ring' -}, { - reg: /bing$/, - repl: 'bingness' -}, { - reg: /sing$/, - repl: 'se' -}, { - reg: /ing$/, - repl: 'ment' -}, { - reg: /ess$/, - repl: 'essness' -}, { - reg: /ous$/, - repl: 'ousness' -}]; - -var to_noun = function to_noun(w) { - if (irregulars.hasOwnProperty(w)) { - return irregulars[w]; - } - var lastChar = w.charAt(w.length - 1); + return reg.word === t.clean || reg.word === t.text || reg.word === t.reduced; + } //support #Tag - if (lastChar === 'w' || lastChar === 's') { - return null; - } - for (var i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(w) === true) { - return w.replace(transforms[i].reg, transforms[i].repl); - } - } + if (reg.tag !== undefined) { + return t.tags[reg.tag] === true; + } //support @method - return w + 'ness'; -}; -module.exports = to_noun; // console.log(to_noun("great")) + if (reg.method !== undefined) { + if (typeof t[reg.method] === 'function' && t[reg.method]() === true) { + return true; + } -},{}],15:[function(_dereq_,module,exports){ -//turn 'quick' into 'quickest' -'use strict'; + return false; + } //support /reg/ -var do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /oud$/, /...p$/]; -var dont_rules = [/ary$/]; -var irregulars = _dereq_('../../../world/more-data/irregularAdjectives').toSuperlative; + if (reg.regex !== undefined) { + return reg.regex.test(t.clean); + } //support (one|two) -var transforms = [{ - reg: /y$/i, - repl: 'iest' -}, { - reg: /([aeiou])t$/i, - repl: '$1ttest' -}, { - reg: /([aeou])de$/i, - repl: '$1dest' -}, { - reg: /nge$/i, - repl: 'ngest' -}, { - reg: /([aeiou])te$/i, - repl: '$1test' -}]; -var to_superlative = function to_superlative(str) { - //irregulars - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } //known transforms + if (reg.choices !== undefined) { + // try to support && operator + if (reg.operator === 'and') { + // must match them all + return reg.choices.every(function (r) { + return wrapMatch(t, r, index, length); + }); + } // or must match one - for (var i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str)) { - return str.replace(transforms[i].reg, transforms[i].repl); + return reg.choices.some(function (r) { + return wrapMatch(t, r, index, length); + }); } - } //dont-rules - - for (var _i = 0; _i < dont_rules.length; _i++) { - if (dont_rules[_i].test(str) === true) { - return null; - } - } //do-rules + return false; + }; // wrap result for !negative match logic - for (var _i2 = 0; _i2 < do_rules.length; _i2++) { - if (do_rules[_i2].test(str) === true) { - if (str.charAt(str.length - 1) === 'e') { - return str + 'st'; - } + wrapMatch = function wrapMatch(t, reg, index, length) { + var result = doesMatch(t, reg, index, length); - return str + 'est'; + if (reg.negative === true) { + return !result; } - } - - return str + 'est'; -}; -module.exports = to_superlative; // console.log(to_superlative("great")) + return result; + }; -},{"../../../world/more-data/irregularAdjectives":218}],16:[function(_dereq_,module,exports){ -'use strict'; //turn an adjective like 'soft' into a verb like 'soften' -//(don't do words like 'green' -> 'greenen') + var _doesMatch = wrapMatch; -var irregulars = { - red: 'redden', - sad: 'sadden', - fat: 'fatten' -}; + var boring = {}; + /** check a match object against this term */ -var toVerb = function toVerb(str) { - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } + var doesMatch_1 = function doesMatch_1(reg, index, length) { + return _doesMatch(this, reg, index, length); + }; + /** does this term look like an acronym? */ - if (/e$/.test(str) === true) { - return str + 'n'; - } - return str + 'en'; -}; + var isAcronym_1$1 = function isAcronym_1$1() { + return isAcronym_1(this.text); + }; + /** is this term implied by a contraction? */ -module.exports = toVerb; -},{}],17:[function(_dereq_,module,exports){ -'use strict'; + var isImplicit = function isImplicit() { + return this.text === '' && Boolean(this.implicit); + }; + /** does the term have at least one good tag? */ -var Text = _dereq_('../../text'); -var toAdjective = _dereq_('./toAdjective'); //the () subset class + var isKnown = function isKnown() { + return Object.keys(this.tags).some(function (t) { + return boring[t] !== true; + }); + }; + /** cache the root property of the term */ -var methods = { - data: function data() { - return this.terms().list.map(function (ts) { - var t = ts.terms[0]; - return { - adjectiveForm: toAdjective(t.normal), - normal: t.normal, - text: t.text - }; - }); - } -}; + var setRoot = function setRoot(world) { + var transform = world.transforms; + var str = this.implicit || this.clean; -var find = function find(r, n) { - r = r.splitAfter('#Comma'); - r = r.match('#Adverb+'); + if (this.tags.Plural) { + str = transform.toSingular(str, world); + } - if (typeof n === 'number') { - r = r.get(n); - } + if (this.tags.Verb && !this.tags.Negative && !this.tags.Infinitive) { + var tense = null; - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./toAdjective":18}],18:[function(_dereq_,module,exports){ -//turns 'quickly' into 'quick' -'use strict'; - -var irregulars = { - 'idly': 'idle', - 'sporadically': 'sporadic', - 'basically': 'basic', - 'grammatically': 'grammatical', - 'alphabetically': 'alphabetical', - 'economically': 'economical', - 'conically': 'conical', - 'politically': 'political', - 'vertically': 'vertical', - 'practically': 'practical', - 'theoretically': 'theoretical', - 'critically': 'critical', - 'fantastically': 'fantastic', - 'mystically': 'mystical', - 'pornographically': 'pornographic', - 'fully': 'full', - 'jolly': 'jolly', - 'wholly': 'whole' -}; -var transforms = [{ - 'reg': /bly$/i, - 'repl': 'ble' -}, { - 'reg': /gically$/i, - 'repl': 'gical' -}, { - 'reg': /([rsdh])ically$/i, - 'repl': '$1ical' -}, { - 'reg': /ically$/i, - 'repl': 'ic' -}, { - 'reg': /uly$/i, - 'repl': 'ue' -}, { - 'reg': /ily$/i, - 'repl': 'y' -}, { - 'reg': /(.{3})ly$/i, - 'repl': '$1' -}]; - -var toAdjective = function toAdjective(str) { - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } + if (this.tags.PastTense) { + tense = 'PastTense'; + } else if (this.tags.Gerund) { + tense = 'Gerund'; + } else if (this.tags.PresentTense) { + tense = 'PresentTense'; + } else if (this.tags.Participle) { + tense = 'Participle'; + } else if (this.tags.Actor) { + tense = 'Actor'; + } - for (var i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); + str = transform.toInfinitive(str, world, tense); } - } - return str; -}; // console.log(toAdjective('quickly')) - - -module.exports = toAdjective; - -},{}],19:[function(_dereq_,module,exports){ -'use strict'; //the plumbing to turn two words into a contraction - -var combine = function combine(a, b) { - b.whitespace.after = a.whitespace.after; - a.whitespace.after = ''; - b.whitespace.before = ''; - a.silent_term = a.text; - b.silent_term = b.text; - b.text = ''; - a.tag('Contraction', 'new-contraction'); - b.tag('Contraction', 'new-contraction'); -}; - -var irregulars = { - can: 'can\'t', - will: 'won\'t' -}; - -var contract = function contract(ts) { - if (ts.expanded === false || ts.match('#Contraction').found) { - return ts; - } //he is -> he's - - - ts.match('(#Noun|#QuestionWord) is').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'s'; - ls.contracted = true; - }); //he did -> he'd - - ts.match('#PronNoun did').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); //how do -> how'd - - ts.match('#QuestionWord (did|do)').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); //he would -> he'd - - ts.match('#Noun (could|would)').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); //they are -> they're - - ts.match('(they|we|you) are').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'re'; - ls.contracted = true; - }); //i am -> i'm - - ts.match('i am').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'m'; - ls.contracted = true; - }); //they will -> they'll - - ts.match('(#Noun|#QuestionWord) will').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'ll'; - ls.contracted = true; - }); //they have -> they've - - ts.match('(they|we|you|i) have').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'ve'; - ls.contracted = true; - }); //is not -> isn't - - ts.match('(#Copula|#Modal|do|does|have|has|can|will) not').list.forEach(function (ls) { - combine(ls.terms[0], ls.terms[1]); //can't, won't - - if (irregulars.hasOwnProperty(ls.terms[0].text) === true) { - ls.terms[0].text = irregulars[ls.terms[0].text]; - } else { - ls.terms[0].text += 'n\'t'; - } + this.root = str; + }; - ls.contracted = true; - }); - return ts; -}; + var _03Misc = { + doesMatch: doesMatch_1, + isAcronym: isAcronym_1$1, + isImplicit: isImplicit, + isKnown: isKnown, + setRoot: setRoot + }; -module.exports = contract; + var hasSpace = /[\s-]/; + var isUpperCase = /^[A-Z-]+$/; // const titleCase = str => { + // return str.charAt(0).toUpperCase() + str.substr(1) + // } -},{}],20:[function(_dereq_,module,exports){ -'use strict'; + /** return various text formats of this term */ -var Terms = _dereq_('../../paths').Terms; + var textOut = function textOut(options, showPre, showPost) { + options = options || {}; + var word = this.text; + var before = this.pre; + var after = this.post; // -word- -var contract = _dereq_('./contract'); + if (options.reduced === true) { + word = this.reduced || ''; + } -var expand = _dereq_('./expand'); + if (options.root === true) { + word = this.root || ''; + } -var ContractionCl = function ContractionCl(arr, world, original) { - Terms.call(this, arr, world, original); -}; //Inherit properties + if (options.implicit === true && this.implicit) { + word = this.implicit || ''; + } + if (options.normal === true) { + word = this.clean || this.text || ''; + } -ContractionCl.prototype = Object.create(Terms.prototype); + if (options.root === true) { + word = this.root || this.reduced || ''; + } -ContractionCl.prototype.data = function () { - var expanded = expand(this.clone()); - var contracted = contract(this.clone()); - return { - text: this.out('text'), - normal: this.out('normal'), - expanded: { - normal: expanded.out('normal'), - text: expanded.out('text') - }, - contracted: { - normal: contracted.out('normal'), - text: contracted.out('text') - }, - isContracted: Boolean(this.contracted) - }; -}; + if (options.unicode === true) { + word = unicode_1(word); + } // cleanup case -ContractionCl.prototype.expand = function () { - return expand(this); -}; -ContractionCl.prototype.contract = function () { - return contract(this); -}; + if (options.titlecase === true) { + if (this.tags.ProperNoun && !this.titleCase()) ; else if (this.tags.Acronym) { + word = word.toUpperCase(); //uppercase acronyms + } else if (isUpperCase.test(word) && !this.tags.Acronym) { + // lowercase everything else + word = word.toLowerCase(); + } + } -module.exports = ContractionCl; + if (options.lowercase === true) { + word = word.toLowerCase(); + } // remove the '.'s from 'F.B.I.' (safely) -},{"../../paths":8,"./contract":19,"./expand":21}],21:[function(_dereq_,module,exports){ -'use strict'; //turn `i'd` into `i would` -var expand = function expand(ts) { - if (ts.contracted === false) { - return ts; - } + if (options.acronyms === true && this.tags.Acronym) { + word = word.replace(/\./g, ''); + } // -before/after- - ts.terms.forEach(function (t) { - if (t.silent_term) { - //this term also needs a space now too - if (!t.text) { - t.whitespace.before = ' '; - } - t._text = t.silent_term; //handle (some) capitalization + if (options.whitespace === true || options.root) { + before = ''; + after = ' '; - if (t.tags.TitleCase) { - t.toTitleCase(); + if ((hasSpace.test(this.post) === false || options.last) && !this.implicit) { + after = ''; } - - t.normalize(); - t.silent_term = null; - t.unTag('Contraction', 'expanded'); } - }); - return ts; -}; - -module.exports = expand; - -},{}],22:[function(_dereq_,module,exports){ -'use strict'; //find contractable, expanded-contractions - -var find = function find(r) { - var remain = r.not('#Contraction'); - var m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)'); - m.concat(remain.match('(they|we|you|i) have')); - m.concat(remain.match('i am')); - m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')); - m.list.forEach(function (ts) { - ts.expanded = true; - }); - return m; -}; - -module.exports = find; -},{}],23:[function(_dereq_,module,exports){ -'use strict'; + if (options.punctuation === true && !options.root) { + //normalized end punctuation + if (this.hasPost('.') === true) { + after = '.' + after; + } else if (this.hasPost('?') === true) { + after = '?' + after; + } else if (this.hasPost('!') === true) { + after = '!' + after; + } else if (this.hasPost(',') === true) { + after = ',' + after; + } else if (this.hasEllipses() === true) { + after = '...' + after; + } + } -var Text = _dereq_('../../text'); + if (showPre !== true) { + before = ''; + } -var ContractionCl = _dereq_('./contraction'); + if (showPost !== true) { + // let keep = after.match(/\)/) || '' + after = ''; //keep //after.replace(/[ .?!,]+/, '') + } // remove the '.' from 'Mrs.' (safely) -var findPossible = _dereq_('./findPossible'); //the Contractions() subset class + if (options.abbreviations === true && this.tags.Abbreviation) { + after = after.replace(/^\./, ''); + } -var methods = { - contract: function contract() { - this.list.forEach(function (ts) { - return ts.contract(); - }); - return this; - }, - expand: function expand() { - this.list.forEach(function (ts) { - return ts.expand(); - }); - return this; - }, - contracted: function contracted() { - this.list = this.list.filter(function (ts) { - return ts.contracted; - }); - return this; - }, - expanded: function expanded() { - this.list = this.list.filter(function (ts) { - return !ts.contracted; - }); - return this; - } -}; - -var find = function find(r, n) { - //find currently-contracted - var found = r.match('#Contraction #Contraction #Contraction?'); - found.list = found.list.map(function (ts) { - var c = new ContractionCl(ts.terms, ts.world, ts.refText, ts.refTerms); - c.contracted = true; - return c; - }); //find currently-expanded - - var expanded = findPossible(r); - expanded.list.forEach(function (ts) { - var c = new ContractionCl(ts.terms, ts.world, ts.refText, ts.refTerms); - c.contracted = false; - found.list.push(c); - }); - found.sort('chronological'); //get nth element + return before + word + after; + }; - if (typeof n === 'number') { - found = found.get(n); - } + var _04Text = { + textOut: textOut + }; - return found; -}; + var boringTags = { + Auxiliary: 1, + Possessive: 1 + }; + /** a subjective ranking of tags kinda tfidf-based */ + + var rankTags = function rankTags(term, world) { + var tags = Object.keys(term.tags); + var tagSet = world.tags; + tags = tags.sort(function (a, b) { + //bury the tags we dont want + if (boringTags[b] || !tagSet[b]) { + return -1; + } // unknown tags are interesting -module.exports = Text.makeSubset(methods, find); -},{"../../text":192,"./contraction":20,"./findPossible":22}],24:[function(_dereq_,module,exports){ -'use strict'; + if (!tagSet[b]) { + return 1; + } -var Terms = _dereq_('../../paths').Terms; + if (!tagSet[a]) { + return 0; + } // then sort by #of parent tags (most-specific tags first) -var parseDate = _dereq_('./parseDate'); -var _Date = function _Date(arr, world, refText) { - Terms.call(this, arr, world, refText); - this.month = this.match('#Month'); -}; //Inherit properties + if (tagSet[a].lineage.length > tagSet[b].lineage.length) { + return 1; + } + if (tagSet[a].isA.length > tagSet[b].isA.length) { + return -1; + } -_Date.prototype = Object.create(Terms.prototype); + return 0; + }); + return tags; + }; -_Date.prototype.data = function () { - return { - text: this.out('text'), - normal: this.out('normal'), - date: parseDate(this) + var _bestTag = rankTags; + + var jsonDefault = { + text: true, + tags: true, + implicit: true, + clean: false, + id: false, + index: false, + offset: false, + whitespace: false, + bestTag: false }; -}; + /** return various metadata for this term */ -module.exports = _Date; + var json = function json(options, world) { + options = options || {}; + options = Object.assign({}, jsonDefault, options); + var result = {}; // default on -},{"../../paths":8,"./parseDate":28}],25:[function(_dereq_,module,exports){ -'use strict'; + if (options.text) { + result.text = this.text; + } -var Text = _dereq_('../../text'); + if (options.normal) { + result.normal = this.normal; + } -var Date = _dereq_('./date'); + if (options.tags) { + result.tags = Object.keys(this.tags); + } // default off -var weekdays = _dereq_('./weekday'); -var months = _dereq_('./month'); //the Dates() subset class + if (options.clean) { + result.clean = this.clean; + } + if (options.id || options.offset) { + result.id = this.id; + } -var methods = { - toShortForm: function toShortForm() { - this.match('#Month').terms().list.forEach(function (ts) { - var t = ts.terms[0]; - months.toShortForm(t); - }); - this.match('#WeekDay').terms().list.forEach(function (ts) { - var t = ts.terms[0]; - weekdays.toShortForm(t); - }); - return this; - }, - toLongForm: function toLongForm() { - this.match('#Month').terms().list.forEach(function (ts) { - var t = ts.terms[0]; - months.toLongForm(t); - }); - this.match('#WeekDay').terms().list.forEach(function (ts) { - var t = ts.terms[0]; - weekdays.toLongForm(t); - }); - return this; - } -}; + if (options.implicit && this.implicit !== null) { + result.implicit = this.implicit; + } -var find = function find(r, n) { - var dates = r.match('#Date+'); + if (options.whitespace) { + result.pre = this.pre; + result.post = this.post; + } - if (typeof n === 'number') { - dates = dates.get(n); - } - - dates.list = dates.list.map(function (ts) { - return new Date(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return dates; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./date":24,"./month":27,"./weekday":31}],26:[function(_dereq_,module,exports){ -"use strict"; - -//follow the javascript scheme -//january is 0 -exports.longMonths = { - 'january': 0, - 'february': 1, - 'march': 2, - 'april': 3, - 'may': 4, - 'june': 5, - 'july': 6, - 'august': 7, - 'september': 8, - 'october': 9, - 'november': 10, - 'december': 11 -}; -exports.shortMonths = { - 'jan': 0, - 'feb': 1, - 'mar': 2, - 'apr': 3, - 'may': 4, - 'jun': 5, - 'jul': 6, - 'aug': 7, - 'sep': 8, - 'oct': 9, - 'nov': 10, - 'dec': 11, - //extra ones - 'febr': 1, - 'sept': 8 -}; - -},{}],27:[function(_dereq_,module,exports){ -'use strict'; - -var data = _dereq_('./data'); - -var shortMonths = data.shortMonths; -var longMonths = data.longMonths; - -var titleCase = function titleCase(str) { - return str.charAt(0).toUpperCase() + str.substr(1); -}; - -module.exports = { - index: function index(t) { - if (t.tags.Month) { - if (longMonths[t.normal] !== undefined) { - return longMonths[t.normal]; - } - - if (shortMonths[t.normal] !== undefined) { - return shortMonths[t.normal]; - } + if (options.bestTag) { + result.bestTag = _bestTag(this, world)[0]; } - return null; - }, - toShortForm: function toShortForm(t) { - if (t.tags.Month !== undefined) { - if (longMonths[t.normal] !== undefined) { - var shorten = Object.keys(shortMonths); - var punct = t.getPunctuation() || ''; - t.text = shorten[longMonths[t.normal]] + punct; - - if (t.tags.TitleCase) { - t.text = titleCase(t.text); - } - } - } + return result; + }; - t.dirty = true; - return t; - }, - toLongForm: function toLongForm(t) { - if (t.tags.Month !== undefined) { - if (shortMonths[t.normal] !== undefined) { - var longer = Object.keys(longMonths); - var punct = t.getPunctuation() || ''; - t.text = longer[shortMonths[t.normal]] + punct; - - if (t.tags.TitleCase) { - t.text = titleCase(t.text); - } - } - } + var _05Json = { + json: json + }; - t.dirty = true; - return t; - } -}; + var methods = Object.assign({}, _01Case, _02Punctuation, _03Misc, _04Text, _05Json); -},{"./data":26}],28:[function(_dereq_,module,exports){ -'use strict'; + /** add spaces at the end */ + var padEnd = function padEnd(str, width) { + str = str.toString(); -var parseTime = _dereq_('./parseTime'); + while (str.length < width) { + str += ' '; + } -var weekdays = _dereq_('./weekday'); + return str; + }; + /** output for verbose-mode */ -var months = _dereq_('./month'); //a hugely-conservative and incomplete first-pass for parsing written-dates -//validate a day-of-month + var logTag = function logTag(t, tag, reason) { + var log = '\x1b[33m' + padEnd(t.clean, 15) + '\x1b[0m + \x1b[32m' + tag + '\x1b[0m '; -var isDate = function isDate(num) { - if (num && num < 31 && num > 0) { - return true; - } + if (reason) { + log = padEnd(log, 35) + ' ' + reason + ''; + } - return false; -}; //please change this in one thousand years + console.log(log); + }; + /** output for verbose mode */ -var isYear = function isYear(num) { - if (num && num > 1000 && num < 3000) { - return true; - } + var logUntag = function logUntag(t, tag, reason) { + var log = '\x1b[33m' + padEnd(t.clean, 3) + ' \x1b[31m - #' + tag + '\x1b[0m '; + + if (reason) { + log = padEnd(log, 35) + ' ' + reason; + } - return false; -}; // + console.log(log); + }; + var isArray = function isArray(arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; + }; -var parseDate = function parseDate(r) { - var result = { - month: null, - date: null, - weekday: null, - year: null, - named: null, - time: null + var titleCase = function titleCase(str) { + return str.charAt(0).toUpperCase() + str.substr(1); }; - var m = r.match('(#Holiday|today|tomorrow|yesterday)'); - if (m.found) { - result.named = m.out('normal'); - } + var fns = { + logTag: logTag, + logUntag: logUntag, + isArray: isArray, + titleCase: titleCase + }; - m = r.match('#Month'); + /** add a tag, and its descendents, to a term */ - if (m.found) { - result.month = months.index(m.list[0].terms[0]); - } + var addTag = function addTag(t, tag, reason, world) { + var tagset = world.tags; //support '.' or '-' notation for skipping the tag + + if (tag === '' || tag === '.' || tag === '-') { + return; + } - m = r.match('#WeekDay'); + if (tag[0] === '#') { + tag = tag.replace(/^#/, ''); + } - if (m.found) { - result.weekday = weekdays.index(m.list[0].terms[0]); - } + tag = fns.titleCase(tag); //if we already got this one - m = r.match('#Time'); + if (t.tags[tag] === true) { + return; + } // log it? + + + var isVerbose = world.isVerbose(); + + if (isVerbose === true) { + fns.logTag(t, tag, reason); + } //add tag - if (m.found) { - result.time = parseTime(r); - r.not('#Time'); //unsure - } //january fifth 1992 + t.tags[tag] = true; //whee! + //check tagset for any additional things to do... - m = r.match('#Month #Value #Year'); + if (tagset.hasOwnProperty(tag) === true) { + //add parent Tags + tagset[tag].isA.forEach(function (down) { + t.tags[down] = true; - if (m.found) { - var numbers = m.values().numbers(); + if (isVerbose === true) { + fns.logTag(t, '→ ' + down); + } + }); //remove any contrary tags - if (isDate(numbers[0])) { - result.date = numbers[0]; + t.unTag(tagset[tag].notA, '←', world); } + }; + /** support an array of tags */ - var year = parseInt(r.match('#Year').out('normal'), 10); - if (isYear(year)) { - result.year = year; + var addTags = function addTags(term, tags, reason, world) { + if (fns.isArray(tags) === true) { + tags.forEach(function (tag) { + return addTag(term, tag, reason, world); + }); + } else { + addTag(term, tags, reason, world); } - } + }; - if (!m.found) { - //january fifth, january 1992 - m = r.match('#Month #Value'); + var add = addTags; - if (m.found) { - var _numbers = m.values().numbers(); + /** remove this tag, and its descentents from the term */ + + var unTag = function unTag(t, tag, reason, world) { + var isVerbose = world.isVerbose(); //support '*' for removing all tags - var num = _numbers[0]; + if (tag === '*') { + t.tags = {}; + return t; + } // remove the tag - if (isDate(num)) { - result.date = num; + + if (t.tags[tag] === true && t.tags.hasOwnProperty(tag) === true) { + delete t.tags[tag]; //log in verbose-mode + + if (isVerbose === true) { + fns.logUntag(t, tag, reason); } - } //january 1992 + } //delete downstream tags too - m = r.match('#Month #Year'); + var tagset = world.tags; - if (m.found) { - var _num = parseInt(r.match('#Year').out('normal'), 10); + if (tagset[tag]) { + var lineage = tagset[tag].lineage; - if (isYear(_num)) { - result.year = _num; + for (var i = 0; i < lineage.length; i++) { + // unTag(t, also[i], ' - - - ', world) //recursive + if (t.tags[lineage[i]] === true) { + delete t.tags[lineage[i]]; + + if (isVerbose === true) { + fns.logUntag(t, ' - ' + lineage[i]); + } + } } } - } //fifth of january - - m = r.match('#Value of #Month'); + return t; + }; //handle an array of tags - if (m.found) { - var _num2 = m.values().numbers()[0]; - if (isDate(_num2)) { - result.date = _num2; + var untagAll = function untagAll(term, tags, reason, world) { + if (fns.isArray(tags) === true) { + tags.forEach(function (tag) { + return unTag(term, tag, reason, world); + }); + } else { + unTag(term, tags, reason, world); } - } + }; - return result; -}; + var unTag_1 = untagAll; -module.exports = parseDate; + var canBe = function canBe(term, tag, world) { + var tagset = world.tags; // cleanup tag -},{"./month":27,"./parseTime":29,"./weekday":31}],29:[function(_dereq_,module,exports){ -'use strict'; + if (tag[0] === '#') { + tag = tag.replace(/^#/, ''); + } //fail-fast -var ampm = /([12]?[0-9]) ?(am|pm)/i; -var hourMin = /([12]?[0-9]):([0-9][0-9]) ?(am|pm)?/i; // -var isHour = function isHour(num) { - if (num && num > 0 && num < 25) { - return true; - } + if (tagset[tag] === undefined) { + return true; + } //loop through tag's contradictory tags - return false; -}; -var isMinute = function isMinute(num) { - if (num && num > 0 && num < 60) { - return true; - } + var enemies = tagset[tag].notA || []; + + for (var i = 0; i < enemies.length; i++) { + if (term.tags[enemies[i]] === true) { + return false; + } + } - return false; -}; + if (tagset[tag].isA !== undefined) { + return canBe(term, tagset[tag].isA, world); //recursive + } -var parseTime = function parseTime(r) { - var result = { - logic: null, - hour: null, - minute: null, - second: null, - timezone: null + return true; }; - var logic = r.match('(by|before|for|during|at|until|after) #Time').firstTerm(); - if (logic.found) { - result.logic = logic.out('normal'); - } + var canBe_1 = canBe; - var time = r.match('#Time'); - time.terms().list.forEach(function (ts) { - var t = ts.terms[0]; //3pm + /** add a tag or tags, and their descendents to this term + * @param {string | string[]} tags - a tag or tags + * @param {string?} [reason] a clue for debugging + */ - var m = t.text.match(ampm); + var tag_1 = function tag_1(tags, reason, world) { + add(this, tags, reason, world); + return this; + }; + /** only tag this term if it's consistent with it's current tags */ - if (m !== null) { - result.hour = parseInt(m[1], 10); - if (m[2] === 'pm') { - result.hour += 12; - } + var tagSafe = function tagSafe(tags, reason, world) { + if (canBe_1(this, tags, world)) { + add(this, tags, reason, world); + } - if (isHour(result.hour) === false) { - result.hour = null; - } - } //3:15 + return this; + }; + /** remove a tag or tags, and their descendents from this term + * @param {string | string[]} tags - a tag or tags + * @param {string?} [reason] a clue for debugging + */ - m = t.text.match(hourMin); + var unTag_1$1 = function unTag_1$1(tags, reason, world) { + unTag_1(this, tags, reason, world); + return this; + }; + /** is this tag consistent with the word's current tags? + * @param {string | string[]} tags - a tag or tags + * @returns {boolean} + */ - if (m !== null) { - result.hour = parseInt(m[1], 10); - result.minute = parseInt(m[2], 10); - if (!isMinute(result.minute)) { - result.minute = null; - } + var canBe_1$1 = function canBe_1$1(tags, world) { + return canBe_1(this, tags, world); + }; - if (m[3] === 'pm') { - result.hour += 12; - } + var tag = { + tag: tag_1, + tagSafe: tagSafe, + unTag: unTag_1$1, + canBe: canBe_1$1 + }; - if (isHour(result.hour) === false) { - result.hour = null; - } - } - }); - return result; -}; - -module.exports = parseTime; - -},{}],30:[function(_dereq_,module,exports){ -"use strict"; - -//follow the javascript scheme -//sunday is 0 -exports.longDays = { - 'sunday': 0, - 'monday': 1, - 'tuesday': 2, - 'wednesday': 3, - 'thursday': 4, - 'friday': 5, - 'saturday': 6 -}; -exports.shortDays = { - 'sun': 0, - 'mon': 1, - 'tues': 2, - 'wed': 3, - 'weds': 3, - 'thurs': 4, - 'fri': 5, - 'sat': 6 -}; - -},{}],31:[function(_dereq_,module,exports){ -'use strict'; - -var data = _dereq_('./data'); - -var shortDays = data.shortDays; -var longDays = data.longDays; -module.exports = { - index: function index(t) { - if (t.tags.WeekDay) { - if (longDays[t.normal] !== undefined) { - return longDays[t.normal]; - } - - if (shortDays[t.normal] !== undefined) { - return shortDays[t.normal]; - } - } + var Term = + /*#__PURE__*/ + function () { + function Term() { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - return null; - }, - toShortForm: function toShortForm(t) { - if (t.tags.WeekDay) { - if (longDays[t.normal] !== undefined) { - var shorten = Object.keys(shortDays); - t.text = shorten[longDays[t.normal]]; - } - } + _classCallCheck(this, Term); - return t; - }, - toLongForm: function toLongForm(t) { - if (t.tags.WeekDay) { - if (shortDays[t.normal] !== undefined) { - var longer = Object.keys(longDays); - t.text = longer[shortDays[t.normal]]; + text = String(text); + var obj = parse(text); // the various forms of our text + + this.text = obj.text || ''; + this.clean = obj.clean; + this.reduced = obj.reduced; + this.root = null; + this.implicit = null; + this.pre = obj.pre || ''; + this.post = obj.post || ''; + this.tags = {}; + this.prev = null; + this.next = null; + this.id = _id(obj.clean); + this.isA = 'Term'; // easier than .constructor... + // support alternative matches + + if (obj.alias) { + this.alias = obj.alias; } } + /** set the text of the Term to something else*/ - return t; - } -}; - -},{"./data":30}],32:[function(_dereq_,module,exports){ -'use strict'; -var Ngrams = _dereq_('./index'); + _createClass(Term, [{ + key: "set", + value: function set(str) { + var obj = parse(str); + this.text = obj.text; + this.clean = obj.clean; + return this; + } + }]); -var getGrams = _dereq_('./getGrams'); //like an n-gram, but only the endings of matches + return Term; + }(); + /** create a deep-copy of this term */ -var EndGrams = function EndGrams(arr, world, original) { - Ngrams.call(this, arr, world, original); -}; //Inherit properties + Term.prototype.clone = function () { + var term = new Term(this.text); + term.pre = this.pre; + term.post = this.post; + term.tags = Object.assign({}, this.tags); //use the old id, so it can be matched with .match(doc) + // term.id = this.id + return term; + }; -EndGrams.prototype = Object.create(Ngrams.prototype); //like an n-gram, but only the startings of matches + Object.assign(Term.prototype, methods); + Object.assign(Term.prototype, tag); + var Term_1 = Term; -EndGrams.find = function (r, n, size) { - var opts = { - size: [1, 2, 3, 4], - edge: 'end' - }; //only look for bigrams, for example + /** return a flat array of Term objects */ + var terms = function terms(n) { + var terms = [this.pool.get(this.start)]; - if (size) { - opts.size = [size]; - } //fetch them + if (this.length === 0) { + return []; + } + for (var i = 0; i < this.length - 1; i += 1) { + var id = terms[terms.length - 1].next; - var arr = getGrams(r, opts); - r = new EndGrams(arr); //default sort + if (id === null) { + // throw new Error('linked-list broken') + console.error("Compromise error: Linked list broken in phrase '" + this.start + "'"); + break; + } - r.sort(); //grab top one, or something + var term = this.pool.get(id); + terms.push(term); //return this one? - if (typeof n === 'number') { - r = r.get(n); - } + if (n !== undefined && n === i) { + return terms[n]; + } + } - return r; -}; + if (n !== undefined) { + return terms[n]; + } -module.exports = EndGrams; + return terms; + }; + /** return a shallow or deep copy of this phrase */ -},{"./getGrams":33,"./index":35}],33:[function(_dereq_,module,exports){ -'use strict'; -var Gram = _dereq_('./gram'); //strip contractions - remove '' term for "it's" + var clone = function clone(isShallow) { + var _this = this; + if (isShallow) { + return this.buildFrom(this.start, this.length); + } //how do we clone part of the pool? -var noEmpty = function noEmpty(fts) { - return fts = fts.terms.filter(function (t) { - return t._text !== ''; - }); -}; //do all grams of one size, on one termList + var terms = this.terms(); + var newTerms = terms.map(function (t) { + return t.clone(); + }); //connect these new ids up -var getGrams = function getGrams(fts, n) { - var terms = noEmpty(fts); + newTerms.forEach(function (t, i) { + //add it to the pool.. + _this.pool.add(t); - if (terms.length < n) { - return []; - } + if (newTerms[i + 1]) { + t.next = newTerms[i + 1].id; + } - var arr = []; + if (newTerms[i - 1]) { + t.prev = newTerms[i - 1].id; + } + }); + return this.buildFrom(newTerms[0].id, newTerms.length); + }; + /** return last term object */ - for (var i = 0; i < terms.length - n + 1; i++) { - var gram = new Gram(terms.slice(i, i + n)); - arr.push(gram); - } - return arr; -}; //left-sided grams + var lastTerm = function lastTerm() { + var terms = this.terms(); + return terms[terms.length - 1]; + }; + /** quick lookup for a term id */ -var startGram = function startGram(fts, n) { - var terms = noEmpty(fts); + var hasId = function hasId(wantId) { + if (this.length === 0 || !wantId) { + return false; + } - if (terms.length < n) { - return []; - } + if (this.start === wantId) { + return true; + } - var arr = [new Gram(terms.slice(0, n))]; - return arr; -}; //right-sided grams + var lastId = this.start; + for (var i = 0; i < this.length - 1; i += 1) { + var term = this.pool.get(lastId); -var endGram = function endGram(fts, n) { - var terms = noEmpty(fts); + if (term === undefined) { + console.error("Compromise error: Linked list broken. Missing term '".concat(lastId, "' in phrase '").concat(this.start, "'\n")); // throw new Error('linked List error') - if (terms.length < n) { - return []; - } + return false; + } - var arr = [new Gram(terms.slice(terms.length - n, terms.length))]; - return arr; -}; //ngrams are consecutive terms of a specific size + if (term.next === wantId) { + return true; + } + lastId = term.next; + } -var buildGrams = function buildGrams(r, options) { - options = options || {}; - options.size = options.size || [1, 2, 3]; + return false; + }; + /** how many seperate, non-empty words is it? */ - if (typeof options.size === 'number') { - options.size = [options.size]; - } - var obj = {}; //collect and count all grams + var wordCount = function wordCount() { + return this.terms().filter(function (t) { + return t.text !== ''; + }).length; + }; - options.size.forEach(function (size) { - r.list.forEach(function (ts) { - var newGrams = []; + var _01Utils = { + terms: terms, + clone: clone, + lastTerm: lastTerm, + hasId: hasId, + wordCount: wordCount + }; - if (options.edge === 'start') { - newGrams = startGram(ts, size); - } else if (options.edge === 'end') { - newGrams = endGram(ts, size); + var trimEnd = function trimEnd(str) { + return str.replace(/ +$/, ''); + }; + /** produce output in the given format */ + + + var text = function text() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var isFirst = arguments.length > 1 ? arguments[1] : undefined; + var isLast = arguments.length > 2 ? arguments[2] : undefined; + + if (typeof options === 'string') { + if (options === 'normal') { + options = { + whitespace: true, + unicode: true, + lowercase: true, + punctuation: true, + acronyms: true, + abbreviations: true, + implicit: true, + normal: true + }; + } else if (options === 'clean') { + options = { + titlecase: false, + lowercase: true, + punctuation: true, + whitespace: true, + unicode: true, + implicit: true + }; + } else if (options === 'reduced') { + options = { + titlecase: false, + lowercase: true, + punctuation: false, + //FIXME: reversed + whitespace: true, + unicode: true, + implicit: true, + reduced: true + }; + } else if (options === 'root') { + options = { + titlecase: false, + lowercase: true, + punctuation: true, + whitespace: true, + unicode: true, + implicit: true, + root: true + }; } else { - newGrams = getGrams(ts, size); + options = {}; } + } - newGrams.forEach(function (g) { - if (obj.hasOwnProperty(g.key)) { - obj[g.key].inc(); - } else { - obj[g.key] = g; - } - }); - }); - }); //flatten to an array + var terms = this.terms(); //this this phrase a complete sentence? - var arr = Object.keys(obj).map(function (k) { - return obj[k]; - }); - return arr; -}; + var isFull = false; -module.exports = buildGrams; + if (terms[0] && terms[0].prev === null && terms[terms.length - 1].next === null) { + isFull = true; + } -},{"./gram":34}],34:[function(_dereq_,module,exports){ -'use strict'; + var text = terms.reduce(function (str, t, i) { + options.last = isLast && i === terms.length - 1; + var showPre = true; + var showPost = true; -var Terms = _dereq_('../../paths').Terms; //this is one-or-more terms together, sorted by frequency + if (isFull === false) { + // dont show beginning whitespace + if (i === 0 && isFirst) { + showPre = false; + } // dont show end-whitespace -var Gram = function Gram(arr, world, original) { - Terms.call(this, arr, world, original); //string to sort/uniq by + if (i === terms.length - 1 && isLast) { + showPost = false; + } + } - this.key = this.out('normal'); //bigram/trigram/etc + var txt = t.textOut(options, showPre, showPost); // if (options.titlecase && i === 0) { + // txt = titleCase(txt) + // } - this.size = arr.length; //number of occurances + return str + txt; + }, ''); //full-phrases show punctuation, but not whitespace - this.count = 1; -}; //Inherit properties + if (isFull === true && isLast) { + text = trimEnd(text); + } + if (options.trim) { + text = text.trim(); + } -Gram.prototype = Object.create(Terms.prototype); + return text; + }; -Gram.prototype.inc = function () { - this.count += 1; -}; + var _02Text = { + text: text + }; -module.exports = Gram; + /** remove start and end whitespace */ + var trim = function trim() { + var terms = this.terms(); -},{"../../paths":8}],35:[function(_dereq_,module,exports){ -'use strict'; + if (terms.length > 0) { + //trim starting + terms[0].pre = terms[0].pre.replace(/^\s+/, ''); //trim ending -var Text = _dereq_('../../text'); + var lastTerm = terms[terms.length - 1]; + lastTerm.post = lastTerm.post.replace(/\s+$/, ''); + } -var getGrams = _dereq_('./getGrams'); + return this; + }; -var _sort = function sort(r) { - r.list = r.list.sort(function (a, b) { - if (a.count > b.count) { - return -1; - } //(tie-braker) + var _03Change = { + trim: trim + }; + var endOfSentence = /[.?!]\s*$/; // replacing a 'word.' with a 'word!' - if (a.count === b.count && (a.size > b.size || a.key.length > b.key.length)) { - return -1; + var combinePost = function combinePost(before, after) { + //only transfer the whitespace + if (endOfSentence.test(after)) { + var whitespace = before.match(/\s*$/); + return after + whitespace; } - return 1; - }); - return r; -}; //the Ngrams() subset class + return before; + }; //add whitespace to the start of the second bit -var methods = { - data: function data() { - return this.list.map(function (ts) { - return { - normal: ts.out('normal'), - count: ts.count, - size: ts.size - }; - }); - }, - unigrams: function unigrams() { - this.list = this.list.filter(function (g) { - return g.size === 1; - }); - return this; - }, - bigrams: function bigrams() { - this.list = this.list.filter(function (g) { - return g.size === 2; - }); - return this; - }, - trigrams: function trigrams() { - this.list = this.list.filter(function (g) { - return g.size === 3; - }); - return this; - }, - //default sort the ngrams - sort: function sort() { - return _sort(this); - } -}; + var addWhitespace = function addWhitespace(beforeTerms, newTerms) { + // add any existing pre-whitespace to beginning + newTerms[0].pre = beforeTerms[0].pre; + var lastTerm = beforeTerms[beforeTerms.length - 1]; //add any existing punctuation to end of our new terms -var find = function find(r, obj) { - var sizes = []; //support .ngrams(3), for compat + var newTerm = newTerms[newTerms.length - 1]; + newTerm.post = combinePost(lastTerm.post, newTerm.post); // remove existing punctuation - if (typeof obj === 'number') { - obj = { - n: obj - }; - } + lastTerm.post = ''; //before ←[space] - after - obj = obj || {}; - var max = obj.max || 4; + if (lastTerm.post === '') { + lastTerm.post += ' '; + } + }; //insert this segment into the linked-list - for (var i = 1; i <= max; i++) { - sizes.push(i); - } //only look for bigrams, for example + var stitchIn = function stitchIn(main, newPhrase) { + // console.log(main.text(), newPhrase.text()) + var afterId = main.lastTerm().next; //connect ours in (main → newPhrase) - if (obj.size) { - sizes = [obj.size]; - } + main.lastTerm().next = newPhrase.start; //stich the end in (newPhrase → after) - var opts = { - size: sizes - }; //fetch them + newPhrase.lastTerm().next = afterId; //do it backwards, too - var arr = getGrams(r, opts); - r = new Text(arr); //default sort + if (afterId) { + // newPhrase ← after + var afterTerm = main.pool.get(afterId); + afterTerm.prev = newPhrase.lastTerm().id; + } // before ← newPhrase - r = _sort(r); //grab top one, or something - if (obj.n !== undefined) { - r = r.get(obj.n); - } + var beforeId = main.terms(0).id; - return r; -}; + if (beforeId) { + var newTerm = newPhrase.terms(0); + newTerm.prev = beforeId; + } + }; // avoid stretching a phrase twice. -module.exports = Text.makeSubset(methods, find); -},{"../../text":192,"./getGrams":33}],36:[function(_dereq_,module,exports){ -'use strict'; + var unique = function unique(list) { + return list.filter(function (o, i) { + return list.indexOf(o) === i; + }); + }; //append one phrase onto another. -var Ngrams = _dereq_('./index'); -var getGrams = _dereq_('./getGrams'); + var appendPhrase = function appendPhrase(before, newPhrase, doc) { + var beforeTerms = before.terms(); //spruce-up the whitespace issues -var StartGrams = function StartGrams(arr, world, original) { - Ngrams.call(this, arr, world, original); -}; //Inherit properties + addWhitespace(beforeTerms, newPhrase.terms()); //insert this segment into the linked-list + stitchIn(before, newPhrase); // stretch! + // make each effected phrase longer -StartGrams.prototype = Object.create(Ngrams.prototype); //like an n-gram, but only the startings of matches + var toStretch = [before]; + var hasId = before.start; + var docs = [doc]; + docs = docs.concat(doc.parents()); // find them all! -StartGrams.find = function (r, n, size) { - var opts = { - size: [1, 2, 3, 4], - edge: 'start' - }; //only look for bigrams, for example + docs.forEach(function (parent) { + // only the phrases that should change + var shouldChange = parent.list.filter(function (p) { + return p.hasId(hasId); + }); + toStretch = toStretch.concat(shouldChange); + }); // don't double-count a phrase - if (size) { - opts.size = [size]; - } //fetch them + toStretch = unique(toStretch); // console.log(toStretch) + toStretch.forEach(function (p) { + p.length += newPhrase.length; + }); + return before; + }; - var arr = getGrams(r, opts); - r = new StartGrams(arr); //default sort + var append = appendPhrase; + + var hasSpace$1 = / /; //a new space needs to be added, either on the new phrase, or the old one + // '[new] [◻old]' -or- '[old] [◻new] [old]' + + var addWhitespace$1 = function addWhitespace(newTerms) { + //add a space before our new text? + // add a space after our text + var lastTerm = newTerms[newTerms.length - 1]; + + if (hasSpace$1.test(lastTerm.post) === false) { + lastTerm.post += ' '; + } // let term = original.pool.get(original.start) + // if (term.prev) { + // //add our space ahead of our new terms + // let firstWord = newTerms[0] + // if (hasSpace.test(firstWord.post) === false) { + // firstWord.post += ' ' + // } + // return + // } + //otherwise, add our space to the start of original + // if (hasSpace.test(term.pre) === false) { + // term.pre = ' ' + term.pre + // } - r.sort(); //grab top one, or something - if (typeof n === 'number') { - r = r.get(n); - } + return; + }; //insert this segment into the linked-list - return r; -}; -module.exports = StartGrams; + var stitchIn$1 = function stitchIn(main, newPhrase, newTerms) { + // [newPhrase] → [main] + var lastTerm = newTerms[newTerms.length - 1]; + lastTerm.next = main.start; // [before] → [main] -},{"./getGrams":33,"./index":35}],37:[function(_dereq_,module,exports){ -'use strict'; //certain words can't be plural, like 'peace' + var pool = main.pool; + var start = pool.get(main.start); -var hasPlural = function hasPlural(t) { - //end quick - if (!t.tags.Noun) { - return false; - } + if (start.prev) { + var before = pool.get(start.prev); + before.next = newPhrase.start; + } //do it backwards, too + // before ← newPhrase - if (t.tags.Plural) { - return true; - } //is it potentially plural? + newTerms[0].prev = main.terms(0).prev; // newPhrase ← main - var noPlural = ['Pronoun', 'Place', 'Value', 'Person', 'Month', 'WeekDay', 'RelativeDay', 'Holiday']; + main.terms(0).prev = lastTerm.id; + }; //recursively increase the length of all parent phrases + // const stretchAll = function(doc, oldStart, newPhrase) { + // //find our phrase to stretch + // let phrase = doc.list.find(p => p.hasId(oldStart) || p.hasId(newPhrase.start)) + // if (phrase === undefined) { + // console.error('compromise error: Prepend missing start - ' + oldStart) + // return + // } + // //should we update the phrase's starting? + // if (phrase.start === oldStart) { + // phrase.start = newPhrase.start + // } + // // console.log(newPhrase) + // phrase.length += newPhrase.length + // if (doc.from) { + // stretchAll(doc.from, oldStart, newPhrase) + // } + // } - for (var i = 0; i < noPlural.length; i++) { - if (t.tags[noPlural[i]]) { - return false; - } - } //terms known as un-inflectable, like 'peace' + var unique$1 = function unique(list) { + return list.filter(function (o, i) { + return list.indexOf(o) === i; + }); + }; //append one phrase onto another - if (t.tags.Uncountable === true) { - return false; - } - return true; -}; + var joinPhrase = function joinPhrase(original, newPhrase, doc) { + var starterId = original.start; + var newTerms = newPhrase.terms(); //spruce-up the whitespace issues -module.exports = hasPlural; + addWhitespace$1(newTerms); //insert this segment into the linked-list -},{}],38:[function(_dereq_,module,exports){ -'use strict'; + stitchIn$1(original, newPhrase, newTerms); //increase the length of our phrases -var Text = _dereq_('../../text'); + var toStretch = [original]; + var docs = [doc]; + docs = docs.concat(doc.parents()); + docs.forEach(function (d) { + // only the phrases that should change + var shouldChange = d.list.filter(function (p) { + return p.hasId(starterId) || p.hasId(newPhrase.start); + }); + toStretch = toStretch.concat(shouldChange); + }); // don't double-count -var Noun = _dereq_('./noun'); //the () subset class + toStretch = unique$1(toStretch); // stretch these phrases + toStretch.forEach(function (p) { + p.length += newPhrase.length; // change the start too, if necessary -var methods = { - isPlural: function isPlural() { - this.list = this.list.filter(function (ts) { - return ts.isPlural(); - }); - return this; - }, - hasPlural: function hasPlural() { - return this.list.map(function (ts) { - return ts.hasPlural(); - }); - }, - toPlural: function toPlural() { - this.list.forEach(function (ts) { - return ts.toPlural(); - }); - return this; - }, - toSingular: function toSingular(verbose) { - this.list.forEach(function (ts) { - return ts.toSingular(verbose); - }); - return this; - }, - toPossessive: function toPossessive(verbose) { - this.list.forEach(function (ts) { - return ts.toPossessive(verbose); - }); - return this; - }, - articles: function articles() { - return this.list.map(function (ts) { - return { - text: ts.out('text'), - normal: ts.out('normal'), - article: ts.article() - }; + if (p.start === starterId) { + p.start = newPhrase.start; + } }); - } -}; + return original; + }; -var find = function find(r, n) { - r = r.clauses(); - r = r.match('#Noun+ (of|by)? the? #Noun+?'); //nouns that we don't want in these results, for weird reasons + var prepend = joinPhrase; - r = r.not('#Pronoun'); - r = r.not('(there|these)'); - r = r.not('(#Month|#WeekDay)'); //allow Durations, Holidays - // //allow possessives like "spencer's", but not generic ones like, + //recursively decrease the length of all the parent phrases + var shrinkAll = function shrinkAll(doc, id, deleteLength, after) { + var arr = doc.parents(); + arr.push(doc); + arr.forEach(function (d) { + //find our phrase to shrink + var phrase = d.list.find(function (p) { + return p.hasId(id); + }); - r = r.not('(my|our|your|their|her|his)'); - r = r.not('(of|for|by|the)$'); + if (!phrase) { + return; + } - if (typeof n === 'number') { - r = r.get(n); - } + phrase.length -= deleteLength; // does it start with this soon-removed word? - r.list = r.list.map(function (ts) { - return new Noun(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return r; -}; + if (phrase.start === id) { + phrase.start = after.id; + } + }); // cleanup empty phrase objects -module.exports = Text.makeSubset(methods, find); + doc.list = doc.list.filter(function (p) { + if (!p.start || !p.length) { + return false; + } -},{"../../text":192,"./noun":46}],39:[function(_dereq_,module,exports){ -'use strict'; + return true; + }); + }; + /** wrap the linked-list around these terms + * so they don't appear any more + */ -var rules = _dereq_('./methods/data/indicators'); -var prep = /([a-z]*) (of|in|by|for) [a-z]/; + var deletePhrase = function deletePhrase(phrase, doc) { + var pool = doc.pool(); + var terms = phrase.terms(); //grab both sides of the chain, -var hasPlural = _dereq_('./hasPlural'); + var prev = pool.get(terms[0].prev) || {}; + var after = pool.get(terms[terms.length - 1].next) || {}; -var knownPlural = { - i: false, - he: false, - she: false, - we: true, - they: true -}; //is it potentially plural? + if (terms[0].implicit && prev.implicit) { + prev.set(prev.implicit); + prev.post += ' '; + } // //first, change phrase lengths -var noPlural = ['Place', 'Value', 'Person', 'Month', 'WeekDay', 'RelativeDay', 'Holiday', 'Possessive']; //first, try to guess based on existing tags -var couldEvenBePlural = function couldEvenBePlural(t) { - if (hasPlural(t) === false) { - return false; - } + shrinkAll(doc, phrase.start, phrase.length, after); // connect [prev]->[after] - for (var i = 0; i < noPlural.length; i++) { - if (t.tags[noPlural[i]]) { - return false; - } - } + if (prev) { + prev.next = after.id; + } // connect [prev]<-[after] - return true; -}; -/** returns true, false, or null */ + if (after) { + after.prev = prev.id; + } // lastly, actually delete the terms from the pool? + // for (let i = 0; i < terms.length; i++) { + // pool.remove(terms[i].id) + // } -var isPlural = function isPlural(t, world) { - if (t.tags.Plural) { - return true; - } + }; - if (t.tags.Singular) { - return false; - } + var _delete = deletePhrase; - var str = t.normal; //whitelist a few easy ones + /** put this text at the end */ - if (knownPlural.hasOwnProperty(str) === true) { - return knownPlural[str]; - } //check given irregulars + var append_1 = function append_1(newPhrase, doc) { + append(this, newPhrase, doc); + return this; + }; + /** add this text to the beginning */ - if (world.plurals && world.plurals.hasOwnProperty(str) === true) { - return false; - } //check opposite-ones + var prepend_1 = function prepend_1(newPhrase, doc) { + prepend(this, newPhrase, doc); + return this; + }; + var delete_1 = function delete_1(doc) { + _delete(this, doc); + return this; + }; // stich-in newPhrase, stretch 'doc' + parents - if (world.cache.toSingular && world.cache.toSingular.hasOwnProperty(str) === true) { - return true; - } //inspect the existing tags to see if a plural is valid + var replace = function replace(newPhrase, doc) { + // doc.debug() + //add it do the end + var firstLength = this.length; + append(this, newPhrase, doc); //delete original terms - if (couldEvenBePlural(t) === false) { - return null; - } //handle 'mayors of chicago' + var tmp = this.buildFrom(this.start, this.length); + tmp.length = firstLength; // console.log(tmp) + _delete(tmp, doc); // return doc + }; + /** + * Turn this phrase object into 3 phrase objects + */ - var preposition = str.match(prep); - if (preposition !== null) { - str = preposition[1]; - } //check the suffix-type rules for indications + var splitOn = function splitOn(p) { + var terms = this.terms(); + var result = { + before: null, + match: null, + after: null + }; + var index = terms.findIndex(function (t) { + return t.id === p.start; + }); + if (index === -1) { + return result; + } //make all three sections into phrase-objects - for (var i = 0; i < rules.plural_indicators.length; i++) { - if (rules.plural_indicators[i].test(str) === true) { - return true; - } - } - for (var _i = 0; _i < rules.singular_indicators.length; _i++) { - if (rules.singular_indicators[_i].test(str) === true) { - return false; + var start = terms.slice(0, index); + + if (start.length > 0) { + result.before = this.buildFrom(start[0].id, start.length); } - } // a fallback 'looks check plural' rule.. + var match = terms.slice(index, index + p.length); - if (/s$/.test(str) === true && /ss$/.test(str) === false && str.length > 3) { - //needs some lovin' - return true; - } + if (match.length > 0) { + result.match = this.buildFrom(match[0].id, match.length); + } - return false; -}; + var end = terms.slice(index + p.length, terms.length); + + if (end.length > 0) { + result.after = this.buildFrom(end[0].id, end.length, this.pool); + } -module.exports = isPlural; // console.log(is_plural('octopus')) + return result; + }; -},{"./hasPlural":37,"./methods/data/indicators":41}],40:[function(_dereq_,module,exports){ -'use strict'; //chooses an indefinite aricle 'a/an' for a word + var _04Insert = { + append: append_1, + prepend: prepend_1, + "delete": delete_1, + replace: replace, + splitOn: splitOn + }; -var irregulars = { - 'hour': 'an', - 'heir': 'an', - 'heirloom': 'an', - 'honest': 'an', - 'honour': 'an', - 'honor': 'an', - 'uber': 'an' //german u + /** return json metadata for this phrase */ + var json$1 = function json() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var world = arguments.length > 1 ? arguments[1] : undefined; + var res = {}; // text data -}; //pronounced letters of acronyms that get a 'an' + if (options.text) { + res.text = this.text(); + } -var an_acronyms = { - a: true, - e: true, - f: true, - h: true, - i: true, - l: true, - m: true, - n: true, - o: true, - r: true, - s: true, - x: true -}; //'a' regexes + if (options.normal) { + res.normal = this.text('normal'); + } -var a_regexs = [/^onc?e/i, //'wu' sound of 'o' -/^u[bcfhjkqrstn][aeiou]/i, // 'yu' sound for hard 'u' -/^eul/i]; + if (options.clean) { + res.clean = this.text('clean'); + } -var makeArticle = function makeArticle(t) { - var str = t.normal; //no 'the john smith', but 'a london hotel' + if (options.reduced) { + res.reduced = this.text('reduced'); + } - if (t.tags.Person) { - return ''; - } //no a/an if it's plural + if (options.root) { + res.root = this.text('root'); + } + if (options.trim) { + if (res.text) { + res.text = res.text.trim(); + } - if (t.tags.Plural) { - return 'the'; - } //explicit irregular forms + if (res.normal) { + res.normal = res.normal.trim(); + } + if (res.reduced) { + res.reduced = res.reduced.trim(); + } + } // terms data - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } //spelled-out acronyms + if (options.terms) { + if (options.terms === true) { + options.terms = {}; + } - var firstLetter = str.substr(0, 1); + res.terms = this.terms().map(function (t) { + return t.json(options.terms, world); + }); + } - if (t.isAcronym() && an_acronyms.hasOwnProperty(firstLetter)) { - return 'an'; - } //'a' regexes + return res; + }; + var _05Json$1 = { + json: json$1 + }; - for (var i = 0; i < a_regexs.length; i++) { - if (a_regexs[i].test(str)) { - return 'a'; + /** match any terms after this phrase */ + var lookAhead = function lookAhead(regs) { + // if empty match string, return everything after + if (!regs) { + regs = '.*'; } - } //basic vowel-startings - - if (/^[aeiou]/i.test(str)) { - return 'an'; - } + var pool = this.pool; // get a list of all terms preceding our start - return 'a'; -}; + var terms = []; -module.exports = makeArticle; + var getAfter = function getAfter(id) { + var term = pool.get(id); -},{}],41:[function(_dereq_,module,exports){ -'use strict'; //similar to plural/singularize rules, but not the same + if (!term) { + return; + } -var plural_indicators = [/(^v)ies$/i, /ises$/i, /ives$/i, /(antenn|formul|nebul|vertebr|vit)ae$/i, /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, /(buffal|tomat|tornad)oes$/i, /(analy|ba|diagno|parenthe|progno|synop|the)ses$/i, /(vert|ind|cort)ices$/i, /(matr|append)ices$/i, /(x|ch|ss|sh|s|z|o)es$/i, /men$/i, /news$/i, /.tia$/i, /(^f)ves$/i, /(lr)ves$/i, /(^aeiouy|qu)ies$/i, /(m|l)ice$/i, /(cris|ax|test)es$/i, /(alias|status)es$/i, /ics$/i]; //similar to plural/singularize rules, but not the same + terms.push(term); -var singular_indicators = [/(ax|test)is$/i, /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, /(octop|vir)i$/i, /(rl)f$/i, /(alias|status)$/i, /(bu)s$/i, /(al|ad|at|er|et|ed|ad)o$/i, /(ti)um$/i, /(ti)a$/i, /sis$/i, /(?:(^f)fe|(lr)f)$/i, /hive$/i, /(^aeiouy|qu)y$/i, /(x|ch|ss|sh|z)$/i, /(matr|vert|ind|cort)(ix|ex)$/i, /(m|l)ouse$/i, /(m|l)ice$/i, /(antenn|formul|nebul|vertebr|vit)a$/i, /.sis$/i, /^(?!talis|.*hu)(.*)man$/i]; -module.exports = { - singular_indicators: singular_indicators, - plural_indicators: plural_indicators -}; + if (term.prev) { + getAfter(term.next); //recursion + } + }; -},{}],42:[function(_dereq_,module,exports){ -"use strict"; + var all = this.terms(); + var lastTerm = all[all.length - 1]; + getAfter(lastTerm.next); -//patterns for turning 'bus' to 'buses' -module.exports = [[/(ax|test)is$/i, '$1es'], [/(octop|vir|radi|nucle|fung|cact|stimul)us$/i, '$1i'], [/(octop|vir)i$/i, '$1i'], [/(kn|l|w)ife$/i, '$1ives'], [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)f$/i, '$1ves'], [/^(dwar|handkerchie|hoo|scar|whar)f$/i, '$1ves'], [/(alias|status)$/i, '$1es'], [/(bu)s$/i, '$1ses'], [/(al|ad|at|er|et|ed|ad)o$/i, '$1oes'], [/([ti])um$/i, '$1a'], [/([ti])a$/i, '$1a'], [/sis$/i, 'ses'], [/(hive)$/i, '$1s'], [/([^aeiouy]|qu)y$/i, '$1ies'], [/(x|ch|ss|sh|s|z)$/i, '$1es'], [/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices'], [/([m|l])ouse$/i, '$1ice'], [/([m|l])ice$/i, '$1ice'], [/^(ox)$/i, '$1en'], [/^(oxen)$/i, '$1'], [/(quiz)$/i, '$1zes'], [/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae'], [/(sis)$/i, 'ses'], [/^(?!talis|.*hu)(.*)man$/i, '$1men'], [/(.*)/i, '$1s']].map(function (a) { - return { - reg: a[0], - repl: a[1] - }; -}); + if (terms.length === 0) { + return []; + } // got the terms, make a phrase from them -},{}],43:[function(_dereq_,module,exports){ -"use strict"; -//patterns for turning 'dwarves' to 'dwarf' -module.exports = [[/([^v])ies$/i, '$1y'], [/ises$/i, 'isis'], [/(kn|[^o]l|w)ives$/i, '$1ife'], [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i, '$1f'], [/^(dwar|handkerchie|hoo|scar|whar)ves$/i, '$1f'], [/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a'], [/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i, '$1us'], [/(buffal|tomat|tornad)(oes)$/i, '$1o'], // [/(analy|diagno|parenthe|progno|synop|the)ses$/i, '$1sis'], -[/(..[aeiou]s)es$/i, '$1'], [/(vert|ind|cort)(ices)$/i, '$1ex'], [/(matr|append)(ices)$/i, '$1ix'], [/(x|ch|ss|sh|z|o)es$/i, '$1'], [/men$/i, 'man'], [/(n)ews$/i, '$1ews'], [/([ti])a$/i, '$1um'], [/([^aeiouy]|qu)ies$/i, '$1y'], [/(s)eries$/i, '$1eries'], [/(m)ovies$/i, '$1ovie'], [/([m|l])ice$/i, '$1ouse'], [/(cris|ax|test)es$/i, '$1is'], [/(alias|status)es$/i, '$1'], [/(ss)$/i, '$1'], [/(ics)$/i, '$1'], [/s$/i, '']].map(function (a) { - return { - reg: a[0], - repl: a[1] + var p = this.buildFrom(terms[0].id, terms.length); + return p.match(regs); }; -}); + /** match any terms before this phrase */ -},{}],44:[function(_dereq_,module,exports){ -'use strict'; // const irregulars = require('../../../lexicon/uncompressed/irregularPlurals').toPlural; - -var pluralRules = _dereq_('./data/pluralRules'); //turn 'shoe' into 'shoes' + var lookBehind = function lookBehind(regs) { + // if empty match string, return everything before + if (!regs) { + regs = '.*'; + } -var pluralize = function pluralize(str, world) { - var irregulars = world.plurals || {}; //irregular + var pool = this.pool; // get a list of all terms preceding our start - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } //regular rule-based inflector + var terms = []; + var getBefore = function getBefore(id) { + var term = pool.get(id); - for (var i = 0; i < pluralRules.length; i++) { - if (pluralRules[i].reg.test(str) === true) { - return str.replace(pluralRules[i].reg, pluralRules[i].repl); - } - } + if (!term) { + return; + } - return null; -}; + terms.push(term); -module.exports = pluralize; + if (term.prev) { + getBefore(term.prev); //recursion + } + }; -},{"./data/pluralRules":42}],45:[function(_dereq_,module,exports){ -'use strict'; + var term = pool.get(this.start); + getBefore(term.prev); -var singleRules = _dereq_('./data/singleRules'); //turn 'shoes' into 'shoe' + if (terms.length === 0) { + return []; + } // got the terms, make a phrase from them -var toSingle = function toSingle(str, world) { - //reverse it //TODO: cache in world object somewhere - var irregulars = world.cache.toSingular || {}; //check irregulars + var p = this.buildFrom(terms[terms.length - 1].id, terms.length); + return p.match(regs); + }; - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } + var _06Lookahead = { + lookAhead: lookAhead, + lookBehind: lookBehind + }; - if (world && world.plurals) { - //given irregulars - var keys = Object.keys(world.plurals); + var methods$1 = Object.assign({}, _01Utils, _02Text, _03Change, _04Insert, _05Json$1, _06Lookahead); - for (var i = 0; i < keys.length; i++) { - if (world.plurals[keys[i]] === str) { - return keys[i]; - } + // try to avoid doing the match + var failFast = function failFast(p, regs) { + if (regs.length === 0) { + return true; } - } //inflect first word of preposition-phrase + for (var i = 0; i < regs.length; i += 1) { + var reg = regs[i]; // //logical quick-ones - if (/([a-z]*) (of|in|by|for) [a-z]/.test(str) === true) { - var first = (str.match(/^([a-z]*) (of|in|by|for) [a-z]/) || [])[1]; + if (reg.optional !== true && reg.negative !== true) { + //start/end impossibilites + if (reg.start === true && i > 0) { + return true; + } // has almost no effect - if (first) { - var better_first = toSingle(first); //recursive - return better_first + str.replace(first, ''); - } - } //regular rule-based inflector + if (p.cache.words !== undefined && reg.word !== undefined && p.cache.words.hasOwnProperty(reg.word) !== true) { + // console.log('skip') + return true; + } + } //this is not possible - for (var _i = 0; _i < singleRules.length; _i++) { - if (singleRules[_i].reg.test(str) === true) { - return str.replace(singleRules[_i].reg, singleRules[_i].repl); + if (reg.anything === true && reg.negative === true) { + return true; + } } - } - - return null; -}; - -module.exports = toSingle; // console.log(toSingle('days')) -},{"./data/singleRules":43}],46:[function(_dereq_,module,exports){ -'use strict'; - -var Terms = _dereq_('../../paths').Terms; + return false; + }; -var _hasPlural = _dereq_('./hasPlural'); + var _02FailFast = failFast; -var _isPlural = _dereq_('./isPlural'); + // i formally apologize for how complicated this is. + //found a match? it's greedy? keep going! + var getGreedy = function getGreedy(terms, t, reg, until, index, length) { + var start = t; -var _toPossessive = _dereq_('./toPossessive'); + for (; t < terms.length; t += 1) { + //stop for next-reg match + if (until && terms[t].doesMatch(until, index + t, length)) { + return t; + } -var makeArticle = _dereq_('./makeArticle'); + var count = t - start + 1; // is it max-length now? -var pluralize = _dereq_('./methods/pluralize'); + if (reg.max !== undefined && count === reg.max) { + return t; + } //stop here -var singularize = _dereq_('./methods/singularize'); -var methods = { - article: function article() { - return makeArticle(this.main); - }, - isPlural: function isPlural() { - return _isPlural(this.main, this.world); - }, - hasPlural: function hasPlural() { - return _hasPlural(this.main); - }, - toPlural: function toPlural(verbose) { - var t = this.main; + if (terms[t].doesMatch(reg, index + t, length) === false) { + // is it too short? + if (reg.min !== undefined && count < reg.min) { + return null; + } - if (_hasPlural(t) && !_isPlural(t, this.world)) { - t.text = pluralize(t.normal, this.world, verbose) || t.text; - t.unTag('Singular', 'toPlural'); - t.tag('Plural', 'toPlural'); + return t; + } } - return this; - }, - toSingular: function toSingular(verbose) { - var t = this.main; + return t; + }; //'unspecific greedy' is a weird situation. - if (_isPlural(t, this.world)) { - t.text = singularize(t.normal, this.world, verbose) || t.text; - t.unTag('Plural', 'toSingular'); - t.tag('Singular', 'toSingular'); - } - return this; - }, - toPossessive: function toPossessive() { - var t = this.main; + var greedyTo = function greedyTo(terms, t, nextReg, index, length) { + //if there's no next one, just go off the end! + if (!nextReg) { + return terms.length; + } //otherwise, we're looking for the next one - if (t.tags.Possessive) { - return this; - } - t = _toPossessive(t); - return this; - }, - data: function data() { - var t = this.main; - var singular = t.text; + for (; t < terms.length; t += 1) { + if (terms[t].doesMatch(nextReg, index + t, length) === true) { + return t; + } + } //guess it doesn't exist, then. - if (_isPlural(t, this.world)) { - singular = singularize(t.normal, this.world) || t.text; - } - var plural = t.text; + return null; + }; + /** tries to match a sequence of terms, starting from here */ - if (_hasPlural(t) && !_isPlural(t, this.world)) { - plural = pluralize(t.normal, this.world) || t.text; - } //support 'mayors of chicago' + var tryHere = function tryHere(terms, regs, index, length) { + var captures = []; + var t = 0; // we must satisfy each rule in 'regs' - var qualifier = ''; + for (var r = 0; r < regs.length; r += 1) { + var reg = regs[r]; //should we fail here? - if (this.qualifier) { - qualifier = this.qualifier.out('normal'); - singular += ' ' + qualifier; - plural += ' ' + qualifier; - } + if (!terms[t]) { + //are all remaining regs optional? + var hasNeeds = regs.slice(r).some(function (remain) { + return !remain.optional; + }); - return { - text: this.out('text'), - normal: this.out('normal'), - article: this.article(), - main: t.normal, - qualifier: qualifier, - singular: singular, - plural: plural - }; - } -}; - -var Noun = function Noun(arr, world, refText) { - Terms.call(this, arr, world, refText); //support 'mayor of chicago' as one noun-phrase - - this.main = this.match('[#Noun+] (of|by|for)'); - - if (this.main.found) { - this.main = this.main.list[0].terms[0]; - } else { - this.main = this.terms[this.terms.length - 1]; - } //'of chicago' - - - this.qualifier = this.match(this.main.normal + ' [.+]').list[0]; -}; - -Noun.prototype = Object.create(Terms.prototype); -Object.keys(methods).forEach(function (k) { - Noun.prototype[k] = methods[k]; -}); -module.exports = Noun; - -},{"../../paths":8,"./hasPlural":37,"./isPlural":39,"./makeArticle":40,"./methods/pluralize":44,"./methods/singularize":45,"./toPossessive":47}],47:[function(_dereq_,module,exports){ -"use strict"; - -var exceptions = { - he: 'his', - she: 'hers', - they: 'theirs', - we: 'ours', - i: 'mine', - you: 'yours', - her: 'hers', - their: 'theirs', - our: 'ours', - my: 'mine', - your: 'yours' -}; // turn "David" to "David's" - -var toPossessive = function toPossessive(t) { - t.tag('Possessive', 'toPossessive'); // exceptions - - if (exceptions.hasOwnProperty(t.normal)) { - t.text = exceptions[t.normal]; - return t; - } // flanders' + if (hasNeeds === false) { + break; + } // have unmet needs - if (/s$/.test(t.normal)) { - t.text += '\''; - return t; - } //normal form: + return false; + } //support 'unspecific greedy' .* properly - t.text += '\'s'; - return t; -}; + if (reg.anything === true && reg.greedy === true) { + var skipto = greedyTo(terms, t, regs[r + 1], reg, index); // ensure it's long enough -module.exports = toPossessive; + if (reg.min !== undefined && skipto - t < reg.min) { + return false; + } // reduce it back, if it's too long -},{}],48:[function(_dereq_,module,exports){ -'use strict'; // make a statistical assumption about the gender of the person based on their given name -// used for pronoun resolution only. -// not intended for classification, or discrimination of people. -var gender = function gender(firstName) { - if (!firstName) { - return null; - } //statistical guesses + if (reg.max !== undefined && skipto - t > reg.max) { + t = t + reg.max; + continue; + } //TODO: support [*] properly - if (/.(i|ee|[a|e]y|a)$/.test(firstName) === true) { - //this is almost-always true - return 'Female'; - } + if (skipto === null) { + return false; //couldn't find it + } - if (/[ou]$/.test(firstName) === true) { - //if it ends in a 'oh or uh', male - return 'Male'; - } + t = skipto; + continue; + } //if it looks like a match, continue - if (/(nn|ll|tt)/.test(firstName) === true) { - //if it has double-consonants, female - return 'Female'; - } // name not recognized, or recognized as of indeterminate gender + if (reg.anything === true || terms[t].doesMatch(reg, index + t, length) === true) { + var startAt = t; // okay, it was a match, but if it optional too, + // we should check the next reg too, to skip it? - return null; -}; + if (reg.optional && regs[r + 1]) { + // does the next reg match it too? + if (terms[t].doesMatch(regs[r + 1], index + t, length) === true) { + // but does the next reg match the next term?? + // only skip if it doesn't + if (!terms[t + 1] || terms[t + 1].doesMatch(regs[r + 1], index + t, length) === false) { + r += 1; + } + } + } //advance to the next term! -module.exports = gender; -},{}],49:[function(_dereq_,module,exports){ -'use strict'; + t += 1; //check any ending '$' flags -var Text = _dereq_('../../text'); + if (reg.end === true) { + //if this isn't the last term, refuse the match + if (t !== terms.length && reg.greedy !== true) { + return false; + } + } //try keep it going! -var Person = _dereq_('./person'); //this is used for pronoun and honorifics, and not intented for more-than grammatical use (see #117) -//the () subset class + if (reg.greedy === true) { + t = getGreedy(terms, t, reg, regs[r + 1], index, length); -var methods = { - pronoun: function pronoun() { - return this.list.map(function (ts) { - return ts.pronoun(); - }); - }, - firstNames: function firstNames() { - return this.match('#FirstName'); - }, - lastNames: function lastNames() { - return this.match('#LastName'); - } -}; + if (t === null) { + return false; //greedy was too short + } + } -var find = function find(r, n) { - var people = r.clauses(); - people = people.match('#Person+'); + if (reg.capture) { + captures.push(startAt); //add greedy-end to capture - if (typeof n === 'number') { - people = people.get(n); - } + if (t > 1 && reg.greedy) { + captures.push(t - 1); + } + } - people.list = people.list.map(function (ts) { - return new Person(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return people; -}; + continue; + } //bah, who cares, keep going -module.exports = Text.makeSubset(methods, find); -},{"../../text":192,"./person":50}],50:[function(_dereq_,module,exports){ -'use strict'; + if (reg.optional === true) { + continue; + } // should we skip-over an implicit word? -var Terms = _dereq_('../../paths').Terms; -var _guessGender = _dereq_('./guessGender'); + if (terms[t].isImplicit() && regs[r - 1] && terms[t + 1]) { + // does the next one match? + if (terms[t + 1].doesMatch(reg, index + t, length)) { + t += 2; + continue; + } + } // console.log(' ❌\n\n') -var Person = function Person(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - this.firstName = this.match('#FirstName+'); - this.middleName = this.match('#Acronym+'); - this.nickName = this.match('#NickName+'); - this.honorifics = this.match('#Honorific'); - this.lastName = this.match('#LastName+'); //assume first-last - if (!this.firstName.found && this.length > 1) { - var m = this.not('(#Acronym|#Honorific)'); - this.firstName = m.first(); - this.lastName = m.last(); - } + return false; + } //we got to the end of the regs, and haven't failed! + //try to only return our [captured] segment - return this; -}; //Inherit properties + if (captures.length > 0) { + //make sure the array is the full-length we'd return anyways + var arr = terms.slice(captures[0], captures[captures.length - 1] + 1); //make sure the array is t-length (so we skip ahead full-length) -Person.prototype = Object.create(Terms.prototype); -var methods = { - data: function data() { - return { - text: this.out('text'), - normal: this.out('normal'), - firstName: this.firstName.out('normal'), - middleName: this.middleName.out('normal'), - nickName: this.nickName.out('normal'), - lastName: this.lastName.out('normal'), - genderGuess: this.guessGender(), - pronoun: this.pronoun(), - honorifics: this.honorifics.out('array') - }; - }, - guessGender: function guessGender() { - //try known honorifics - if (this.honorifics.match('(mr|mister|sr|sir|jr)').found) { - return 'Male'; - } + for (var tmp = 0; tmp < t; tmp++) { + arr[tmp] = arr[tmp] || null; //these get cleaned-up after + } - if (this.honorifics.match('(mrs|miss|ms|misses|mme|mlle)').found) { - return 'Female'; - } //try known first-names + return arr; + } //return our result - if (this.firstName.match('#MaleName').found) { - return 'Male'; - } + return terms.slice(0, t); + }; - if (this.firstName.match('#FemaleName').found) { - return 'Female'; - } //look-for regex clues + var _03TryMatch = tryHere; + /* break-down a match expression into this: + { + word:'', + tag:'', + regex:'', - var str = this.firstName.out('normal'); - return _guessGender(str); - }, - pronoun: function pronoun() { - var str = this.firstName.out('normal'); - var g = this.guessGender(str); + start:false, + end:false, + negative:false, + anything:false, + greedy:false, + optional:false, - if (g === 'Male') { - return 'he'; - } + capture:false, + choices:[], + } + */ + var hasMinMax = /\{([0-9]+,?[0-9]*)\}/; + var andSign = /&&/; - if (g === 'Female') { - return 'she'; - } + var titleCase$1 = function titleCase(str) { + return str.charAt(0).toUpperCase() + str.substr(1); + }; - return 'they'; - }, - root: function root() { - var first = this.firstName.out('root'); - var last = this.lastName.out('root'); + var end = function end(str) { + return str[str.length - 1]; + }; - if (first && last) { - return first + ' ' + last; - } + var start = function start(str) { + return str[0]; + }; - return last || first || this.out('root'); - } -}; -Object.keys(methods).forEach(function (k) { - Person.prototype[k] = methods[k]; -}); -module.exports = Person; + var stripStart = function stripStart(str) { + return str.substr(1); + }; -},{"../../paths":8,"./guessGender":48}],51:[function(_dereq_,module,exports){ -'use strict'; + var stripEnd = function stripEnd(str) { + return str.substr(0, str.length - 1); + }; -var Text = _dereq_('../../text'); // const Terms = require('../../paths').Terms; + var stripBoth = function stripBoth(str) { + str = stripStart(str); + str = stripEnd(str); + return str; + }; // -var methods = { - //remove the 's on the end of the word - strip: function strip() { - this.list.forEach(function (ts) { - var t = ts.terms[ts.terms.length - 1]; - t.text = t.text.replace(/'s$/, ''); - t.unTag('Possessive', '.strip()'); - }); - return this; - } -}; + var parseToken = function parseToken(w) { + var obj = {}; //collect any flags (do it twice) -var find = function find(r, n) { - r = r.match('#Possessive+'); - r = r.splitAfter('#Comma'); + for (var i = 0; i < 2; i += 1) { + //back-flags + if (end(w) === '+') { + obj.greedy = true; + w = stripEnd(w); + } - if (typeof n === 'number') { - r = r.get(n); - } + if (w !== '*' && end(w) === '*' && w !== '\\*') { + obj.greedy = true; + w = stripEnd(w); + } - return r; -}; + if (end(w) === '?') { + obj.optional = true; + w = stripEnd(w); + } -module.exports = Text.makeSubset(methods, find); + if (end(w) === '$') { + obj.end = true; + w = stripEnd(w); + } //front-flags -},{"../../text":192}],52:[function(_dereq_,module,exports){ -'use strict'; -var Text = _dereq_('../../text'); + if (start(w) === '^') { + obj.start = true; + w = stripStart(w); + } -var Sentence = _dereq_('./sentence'); //the Sentences() subset class + if (start(w) === '!') { + obj.negative = true; + w = stripStart(w); + } //wrapped-flags -var methods = { - /** conjugate the main/first verb*/ - toPastTense: function toPastTense() { - this.list = this.list.map(function (ts) { - ts = ts.toPastTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toPresentTense: function toPresentTense() { - this.list = this.list.map(function (ts) { - ts = ts.toPresentTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toFutureTense: function toFutureTense() { - this.list = this.list.map(function (ts) { - ts = ts.toFutureTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toContinuous: function toContinuous() { - this.list = this.list.map(function (ts) { - ts = ts.toContinuous(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, + if (start(w) === '(' && end(w) === ')') { + // support (one && two) + if (andSign.test(w)) { + obj.choices = w.split(andSign); + obj.operator = 'and'; + } else { + obj.choices = w.split('|'); + obj.operator = 'or'; + } //remove '(' and ')' - /** negative/positive */ - toNegative: function toNegative() { - this.list = this.list.map(function (ts) { - ts = ts.toNegative(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toPositive: function toPositive() { - this.list = this.list.map(function (ts) { - ts = ts.toPositive(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - /** look for 'was _ by' patterns */ - isPassive: function isPassive() { - this.list = this.list.filter(function (ts) { - return ts.isPassive(); - }); - return this; - }, - //return only questions - isQuestion: function isQuestion() { - // this.list = this.list.filter(ts => { - // return ts.isQuestion(); - // }); - return this.questions(); - }, + obj.choices[0] = stripStart(obj.choices[0]); + var last = obj.choices.length - 1; + obj.choices[last] = stripEnd(obj.choices[last]); // clean up the results - /** add a word to the start */ - prepend: function prepend(str) { - this.list = this.list.map(function (ts) { - return ts.prepend(str); - }); - return this; - }, + obj.choices = obj.choices.map(function (s) { + return s.trim(); + }); + obj.choices = obj.choices.filter(function (s) { + return s; + }); //recursion alert! - /** add a word to the end */ - append: function append(str) { - this.list = this.list.map(function (ts) { - return ts.append(str); - }); - return this; - }, + obj.choices = obj.choices.map(parseToken); + w = ''; + } //capture group (this one can span multiple-terms) - /** convert between question/statement/exclamation*/ - toExclamation: function toExclamation() { - this.list.forEach(function (ts) { - ts.setPunctuation('!'); - }); - return this; - }, - toQuestion: function toQuestion() { - this.list.forEach(function (ts) { - ts.setPunctuation('?'); - }); - return this; - }, - toStatement: function toStatement() { - this.list.forEach(function (ts) { - ts.setPunctuation('.'); - }); - return this; - } -}; -var find = function find(r, n) { - r = r.all(); + if (start(w) === '[' || end(w) === ']') { + obj.capture = true; + w = w.replace(/^\[/, ''); + w = w.replace(/\]$/, ''); + } //regex - if (typeof n === 'number') { - r = r.get(n); - } - r.list = r.list.map(function (ts) { - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return r; -}; + if (start(w) === '/' && end(w) === '/') { + w = stripBoth(w); + obj.regex = new RegExp(w); + return obj; + } //soft-match -module.exports = Text.makeSubset(methods, find); -},{"../../text":192,"./sentence":54}],53:[function(_dereq_,module,exports){ -'use strict'; //is this sentence asking a question? + if (start(w) === '~' && end(w) === '~') { + w = stripBoth(w); + obj.soft = true; + obj.word = w; + return obj; + } + } // support #Tag{0,9} -var isQuestion = function isQuestion(ts) { - var endPunct = ts.getPunctuation(); - var clauses = ts.match('*').splitAfter('#Comma'); - if (/\?/.test(endPunct) === true) { - return true; - } // Has ellipsis at the end means it's probably not a question - // e.g., Is this just fantasy... + if (hasMinMax.test(w) === true) { + w = w.replace(hasMinMax, function (a, b) { + var arr = b.split(/,/g); + if (arr.length === 1) { + // '{3}' Exactly three times + obj.min = Number(arr[0]); + obj.max = Number(arr[0]); + } else { + // '{2,4}' Two to four times + // '{3,}' Three or more times + obj.min = Number(arr[0]); + obj.max = Number(arr[1] || 999); + } - if (/\.\.$/.test(ts.out('text'))) { - return false; - } // Starts with question word, but has a comma, so probably not a question - // e.g., Why are we caught in a land slide, no escape from reality + obj.greedy = true; + return ''; + }); + } //do the actual token content - if (ts.has('^#QuestionWord') && ts.has('#Comma')) { - return false; - } // Starts with a #QuestionWord - // e.g., What open your eyes look up to the skies and see + if (start(w) === '#') { + obj.tag = stripStart(w); + obj.tag = titleCase$1(obj.tag); + return obj; + } //dynamic function on a term object - if (ts.has('^#QuestionWord')) { - return true; - } // Second word is a #QuestionWord - // e.g., I'm what a poor boy - // case ts.has('^\w+\s#QuestionWord'): - // return true; - // is it, do you - start of sentence - // e.g., Do I need no sympathy + if (start(w) === '@') { + obj.method = stripStart(w); + return obj; + } + if (w === '.') { + obj.anything = true; + return obj; + } //support alone-astrix - if (ts.has('^(do|does|did|is|was|can|could|will|would|may) #Noun')) { - return true; - } // these are a little more loose.. - // e.g., Must I be come easy come easy go + if (w === '*') { + obj.anything = true; + obj.greedy = true; + obj.optional = true; + return obj; + } - if (ts.has('^(have|must) you')) { - return true; - } // Clause starts with a question word - // e.g., Anyway the wind blows, what doesn't really matter to me + if (w) { + //somehow handle encoded-chars? + w = w.replace('\\*', '*'); + w = w.replace('\\.', '.'); + obj.word = w.toLowerCase(); + } + return obj; + }; - if (clauses.has('^#QuestionWord')) { - return true; - } //is wayne gretskzy alive + var parseToken_1 = parseToken; + var isArray$1 = function isArray(arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; + }; //split-up by (these things) - if (clauses.has('(do|does|is|was) #Noun+ #Adverb? (#Adjective|#Infinitive)$')) { - return true; - } // Probably not a question + var byParentheses = function byParentheses(str) { + var arr = str.split(/([\^\[\!]*\(.*?\)[?+*]*\]?\$?)/); + arr = arr.map(function (s) { + return s.trim(); + }); + return arr; + }; - return false; -}; + var byWords = function byWords(arr) { + var words = []; + arr.forEach(function (a) { + //keep brackets lumped together + if (/^[[^_/]?\(/.test(a[0])) { + words.push(a); + return; + } -module.exports = isQuestion; + var list = a.split(' '); + list = list.filter(function (w) { + return w; + }); + words = words.concat(list); + }); + return words; + }; //turn an array into a 'choices' list -},{}],54:[function(_dereq_,module,exports){ -'use strict'; -var Terms = _dereq_('../../paths').Terms; + var byArray = function byArray(arr) { + return [{ + choices: arr.map(function (s) { + return { + word: s + }; + }) + }]; + }; -var _toNegative = _dereq_('./toNegative'); + var postProcess = function postProcess(tokens) { + //ensure there's only one consecutive capture group. + var count = tokens.filter(function (t) { + return t.capture === true; + }).length; -var _toPositive = _dereq_('./toPositive'); + if (count > 1) { + var captureArr = tokens.map(function (t) { + return t.capture; + }); + var first = captureArr.indexOf(true); + var last = captureArr.length - 1 - captureArr.reverse().indexOf(true); //'fill in' capture groups between start-end -var Verb = _dereq_('../verbs/verb'); + for (var i = first; i < last; i++) { + tokens[i].capture = true; + } + } -var insert = _dereq_('./smartInsert'); //decide on main subject-verb-object + return tokens; + }; + var fromDoc = function fromDoc(doc) { + if (!doc || !doc.list || !doc.list[0]) { + return []; + } -var parse = function parse(s) { - //strip conditions first - var conditions = s.match('#Condition'); - var tmp = s.not('#Condition'); //choose the verb first + var ids = []; + doc.list.forEach(function (p) { + p.terms().forEach(function (t) { + ids.push({ + id: t.id + }); + }); + }); + return [{ + choices: ids, + greedy: true + }]; + }; + /** parse a match-syntax string into json */ - var verb = tmp.match('#VerbPhrase+').first(); //this should be much smarter - var vb = verb.out('normal'); //get subj noun left-of the verb + var syntax = function syntax(input) { + // fail-fast + if (input === null || input === undefined || input === '') { + return []; + } //try to support a ton of different formats: - var subject = tmp.match('#Determiner? #Adjective+? #Noun ' + vb).first().not('#VerbPhrase'); //get obj noun right-of the verb - var object = tmp.match(vb + ' #Preposition? #Determiner? #Noun').first().not('#VerbPhrase'); - s.conditions = conditions; - s.subject = subject; - s.verb = verb; - s.object = object; + if (_typeof(input) === 'object') { + if (isArray$1(input)) { + if (input.length === 0 || !input[0]) { + return []; + } //is it a pre-parsed reg-list? - if (s.verb.found) { - s.verb = new Verb(s.verb.list[0].terms, s.world, s.refText, s.refTerms); - } - return s; -}; + if (_typeof(input[0]) === 'object') { + return input; + } //support a flat array of normalized words -var fixContraction = function fixContraction(contr) { - if (contr.found) { - contr.contractions().expand(); - } -}; -var killContraction = function killContraction(s) { - s.terms = s.terms.filter(function (t) { - if (t.silent_term) { - if (t.silent_term === 'am' || t.silent_term === 'will' || t.silent_term === 'did') { - return false; - } + if (typeof input[0] === 'string') { + return byArray(input); + } + } //support passing-in a compromise object as a match - t.text = t.silent_term; - t.silent_term = null; - t.unTag('Contraction'); - if (t.tags.TitleCase === true) { - t.toTitleCase(); + if (input && input.isA === 'Doc') { + return fromDoc(input); } + + return []; } - return true; - }); -}; //if the subject of thr sentence is plural, use infinitive form of verb -// (he goes / i go) + if (typeof input === 'number') { + input = String(input); //go for it? + } + var tokens = byParentheses(input); + tokens = byWords(tokens); + tokens = tokens.map(parseToken_1); //clean up anything weird -var useInfinitive = function useInfinitive(s) { - if (s.subject.found && s.subject.has('(i|we)')) { - return true; - } + tokens = postProcess(tokens); // console.log(JSON.stringify(tokens, null, 2)) - return false; -}; + return tokens; + }; -var methods = { - /** inflect the main/first noun*/ - toSingular: function toSingular() { - var nouns = this.match('#Noun').match('!#Pronoun').firstTerm(); - nouns.things().toSingular(); - return this; - }, - toPlural: function toPlural() { - var nouns = this.match('#Noun').match('!#Pronoun').firstTerm(); - nouns.things().toPlural(); - return this; - }, + var syntax_1 = syntax; - /** find the first important verbPhrase. returns a Term object */ - mainVerb: function mainVerb() { - parse(this); //re-parse + /** returns a simple array of arrays */ - if (this.verb.found) { - return this.verb; - } + var matchAll = function matchAll(p, regs) { + var matchOne = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - return null; - }, + //if we forgot to parse it.. + if (typeof regs === 'string') { + regs = syntax_1(regs); + } //try to dismiss it, at-once - /** sentence tense conversion**/ - toPastTense: function toPastTense() { - var verb = this.mainVerb(); - if (verb) { - //this is really ugly.. - var start = verb.out('root'); - verb.toPastTense(); //support "i'm going" + if (_02FailFast(p, regs) === true) { + return []; + } //any match needs to be this long, at least - var contr = this.match('#Contraction ' + start); - fixContraction(contr); - var end = verb.out('root'); // this.replace(start, end) - var r = this.parentTerms.replace(start, end); - return r; - } + var minLength = regs.filter(function (r) { + return r.optional !== true; + }).length; + var terms = p.cache.terms || p.terms(); + var matches = []; //optimisation for '^' start logic - return this; - }, - toPresentTense: function toPresentTense() { - var verb = this.mainVerb(); + if (regs[0].start === true) { + var match = _03TryMatch(terms, regs, 0, terms.length); - if (verb) { - var start = verb.out('normal'); //plural/singular stuff + if (match !== false && match.length > 0) { + matches.push(match); + } // remove (intentional) null results - if (useInfinitive(this) === true) { - if (this.has('(am|will|did) ' + start)) { - killContraction(this); - } - verb.toInfinitive(); //irregular "i am" - // this.debug(); - // if (this.has('i #Adverb? is')) { - // this.replace(' #Adverb? [is]', 'am'); - // } - } else { - verb.toPresentTense(); - var contr = this.match('#Contraction ' + start); - fixContraction(contr); - } //support "i'm going" - - - var end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - - return this; - }, - toFutureTense: function toFutureTense() { - var verb = this.mainVerb(); - - if (verb) { - var start = verb.clone(); //.out('root'); - - verb.toFutureTense(); //support "i'm going" + matches = matches.map(function (arr) { + return arr.filter(function (t) { + return t; + }); + }); + return matches; + } //try starting, from every term - var contr = this.match('#Contraction ' + start.out('normal')); - fixContraction(contr); - var end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - return this; - }, - toContinuous: function toContinuous() { - var verb = this.mainVerb(); - - if (verb) { - var start = verb.clone(); //.out('root'); - //'is walking' or 'are walking'? - // let aux = 'is'; - // if (useInfinitive(this)) { - // aux = 'are'; - // } + for (var i = 0; i < terms.length; i += 1) { + // slice may be too short + if (i + minLength > terms.length) { + break; + } //try it! - verb.toGerund(); // verb.insertBefore(aux); - //support "i'm going" - var contr = this.match('#Contraction ' + start.out('normal')); - fixContraction(contr); - var end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } + var _match = _03TryMatch(terms.slice(i), regs, i, terms.length); - return this; - }, + if (_match !== false && _match.length > 0) { + //zoom forward! + i += _match.length - 1; //[capture-groups] return some null responses - /** negation **/ - isNegative: function isNegative() { - return this.match('#Negative').list.length === 1; - }, - toNegative: function toNegative() { - if (this.isNegative()) { - return this; - } + _match = _match.filter(function (m) { + return m; + }); + matches.push(_match); //ok, maybe that's enough? - return _toNegative(this); - }, - toPositive: function toPositive() { - if (!this.isNegative()) { - return this; + if (matchOne === true) { + return matches; + } + } } - return _toPositive(this); - }, - - /** smarter insert methods*/ - append: function append(str) { - return insert.append(this, str); - }, - prepend: function prepend(str) { - return insert.prepend(this, str); - }, - - /** look for 'was _ by' patterns */ - isPassive: function isPassive() { - return this.match('was #Adverb? #PastTense #Adverb? by').found; //haha - } -}; - -var Sentence = function Sentence(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - parse(this); -}; //Terms inheritence + return matches; + }; + var _01MatchAll = matchAll; -Sentence.prototype = Object.create(Terms.prototype); //add-in methods + /** return anything that doesn't match. + * returns a simple array of arrays + */ -Object.keys(methods).forEach(function (k) { - Sentence.prototype[k] = methods[k]; -}); -module.exports = Sentence; + var notMatch = function notMatch(p, regs) { + var found = {}; + var arr = _01MatchAll(p, regs); + arr.forEach(function (ts) { + ts.forEach(function (t) { + found[t.id] = true; + }); + }); //return anything not found -},{"../../paths":8,"../verbs/verb":94,"./smartInsert":55,"./toNegative":56,"./toPositive":57}],55:[function(_dereq_,module,exports){ -'use strict'; + var terms = p.terms(); + var result = []; + var current = []; + terms.forEach(function (t) { + if (found[t.id] === true) { + if (current.length > 0) { + result.push(current); + current = []; + } -var hasCapital = /^[A-Z]/; //sticking words at the start sentence-sensitive + return; + } -var prepend = function prepend(ts, str) { - var firstTerm = ts.terms[0]; - ts.insertAt(0, str); //handle titlecase of first-word + current.push(t); + }); - if (hasCapital.test(firstTerm.text)) { - //is it titlecased because it should be? - if (firstTerm.needsTitleCase() === false) { - firstTerm.toLowerCase(); + if (current.length > 0) { + result.push(current); } - var newTerm = ts.terms[0]; - newTerm.toTitleCase(); - } + return result; + }; - return ts; -}; //sticking words on end sentence-sensitive + var not = notMatch; + /** return an array of matching phrases */ -var append = function append(ts, str) { - var endTerm = ts.terms[ts.terms.length - 1]; //move the sentence punctuation to the end + var match_1 = function match_1(str) { + var _this = this; - var punct = ts.getPunctuation(); + var matches = _01MatchAll(this, str); //make them phrase objects - if (punct) { - endTerm.killPunctuation(); - } + matches = matches.map(function (list) { + return _this.buildFrom(list[0].id, list.length); + }); + return matches; + }; + /** return boolean if one match is found */ - ts.insertAt(ts.terms.length, str); - var newTerm = ts.terms[ts.terms.length - 1]; - if (punct) { - newTerm.text += punct; - } //move over sentence-ending whitespace too + var has = function has(str) { + var matches = _01MatchAll(this, str, true); + return matches.length > 0; + }; + /** remove all matches from the result */ - if (endTerm.whitespace.after) { - newTerm.whitespace.after = endTerm.whitespace.after; - endTerm.whitespace.after = ''; - } + var not$1 = function not$1(str) { + var _this2 = this; - return ts; -}; + var matches = not(this, str); //make them phrase objects -module.exports = { - append: append, - prepend: prepend -}; + matches = matches.map(function (list) { + return _this2.buildFrom(list[0].id, list.length); + }); + return matches; + }; + /** return a list of phrases that can have this tag */ -},{}],56:[function(_dereq_,module,exports){ -'use strict'; //these terms are nicer ways to negate a sentence -//ie. john always walks -> john always doesn't walk -var logicalNegate = { - everyone: 'no one', - everybody: 'nobody', - someone: 'no one', - somebody: 'nobody', - // everything:"nothing", - always: 'never' -}; //different rule for i/we/they/you + infinitive -//that is, 'i walk' -> 'i don\'t walk', not 'I not walk' + var canBe$1 = function canBe(tag, world) { + var _this3 = this; -var toNegative = function toNegative(ts) { - var lg = ts.match('(everyone|everybody|someone|somebody|always)').first(); + var results = []; + var terms = this.terms(); + var previous = false; - if (lg.found && logicalNegate[lg.out('normal')]) { - var found = lg.out('normal'); // ts = ts.replace(found, logicalNegate[found]); + for (var i = 0; i < terms.length; i += 1) { + var can = terms[i].canBe(tag, world); - ts = ts.match(found).replaceWith(logicalNegate[found]).list[0]; - return ts.parentTerms; - } //negate the main verb of the sentence + if (can === true) { + if (previous === true) { + //add it to the end + results[results.length - 1].push(terms[i]); + } else { + results.push([terms[i]]); //make a new one + } + previous = can; + } + } //turn them into Phrase objects - var vb = ts.mainVerb(); - if (vb) { - vb.toNegative(); - } + results = results.filter(function (a) { + return a.length > 0; + }).map(function (arr) { + return _this3.buildFrom(arr[0].id, arr.length); + }); + return results; + }; - return ts; -}; + var match = { + match: match_1, + has: has, + not: not$1, + canBe: canBe$1 + }; -module.exports = toNegative; + var Phrase = function Phrase(id, length, pool) { + _classCallCheck(this, Phrase); -},{}],57:[function(_dereq_,module,exports){ -'use strict'; //ie. john never walks -> john always walks -//nobody/noone are ambiguous logically (somebody? / everybody?) + this.start = id; + this.length = length; + this.isA = 'Phrase'; // easier than .constructor... -var logical = { - 'never': 'always', - 'nothing': 'everything' -}; + Object.defineProperty(this, 'pool', { + enumerable: false, + writable: true, + value: pool + }); + Object.defineProperty(this, 'cache', { + enumerable: false, + writable: true, + value: {} + }); + }; + /** create a new Phrase object from an id and length */ -var toPositive = function toPositive(ts) { - var m = ts.match('(never|nothing)').first(); - if (m.found) { - var str = m.out('normal'); + Phrase.prototype.buildFrom = function (id, length) { + var p = new Phrase(id, length, this.pool); - if (logical[str]) { - ts = ts.match(str).replaceWith(logical[str], true).list[0]; - return ts.parentTerms; + if (this.cache) { + p.cache = this.cache; + p.cache.terms = null; } - } //otherwise just remove 'not' - - - ts["delete"]('#Negative'); - return ts; -}; - -module.exports = toPositive; - -},{}],58:[function(_dereq_,module,exports){ -'use strict'; - -var Text = _dereq_('../../text'); - -var Terms = _dereq_('../../paths').Terms; //the Terms() subset class -//this is just a wrapper around the actual Term class, -//which is buried in `ts.terms[0]` + return p; + }; // Phrase.prototype.fromString = function(str) { + // console.log(tokenize) + // return tokenize.fromText(str) + // } + //apply methods -var methods = { - data: function data() { - return this.list.map(function (ts) { - var t = ts.terms[0]; - return { - spaceBefore: t.whitespace.before, - text: t.text, - spaceAfter: t.whitespace.after, - normal: t.normal, - implicit: t.silent_term, - bestTag: t.bestTag(), - tags: Object.keys(t.tags) - }; - }); - } -}; -var find = function find(r, n) { - var list = []; //make a Terms Object for every Term + Object.assign(Phrase.prototype, match); + Object.assign(Phrase.prototype, methods$1); //apply aliases - r.list.forEach(function (ts) { - ts.terms.forEach(function (t) { - list.push(new Terms([t], ts.world, r)); - }); + var aliases = { + term: 'terms' + }; + Object.keys(aliases).forEach(function (k) { + return Phrase.prototype[k] = Phrase.prototype[aliases[k]]; }); - r = new Text(list, r.world, r.parent); - - if (typeof n === 'number') { - r = r.get(n); - } - - return r; -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../paths":8,"../../text":192}],59:[function(_dereq_,module,exports){ -"use strict"; + var Phrase_1 = Phrase; -var numOrdinal = _dereq_('./numOrdinal'); + /** a key-value store of all terms in our Document */ + var Pool = + /*#__PURE__*/ + function () { + function Pool() { + var words = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; -var _textOrdinal = _dereq_('./textOrdinal'); - -var textCardinal = _dereq_('./textCardinal'); - -var niceNumber = _dereq_('./niceNumber'); //make all the number formats + _classCallCheck(this, Pool); + //quiet this property in console.logs + Object.defineProperty(this, 'words', { + enumerable: false, + value: words + }); + } + /** throw a new term object in */ -var fmt = { - nice: function nice(num) { - return niceNumber(num); - }, - ordinal: function ordinal(num) { - return numOrdinal(num); - }, - cardinal: function cardinal(num) { - return String(num); - }, - niceOrdinal: function niceOrdinal(num) { - num = numOrdinal(num); - num = niceNumber(num); - return num; - }, - text: function text(num) { - return textCardinal(num).join(' '); - }, - textOrdinal: function textOrdinal(num) { - return _textOrdinal(num); - } -}; -module.exports = fmt; -},{"./niceNumber":60,"./numOrdinal":61,"./textCardinal":62,"./textOrdinal":63}],60:[function(_dereq_,module,exports){ -'use strict'; //put a comma or two in + _createClass(Pool, [{ + key: "add", + value: function add(term) { + this.words[term.id] = term; + return this; + } + /** find a term by it's id */ -var niceNumber = function niceNumber(num) { - if (!num && num !== 0) { - return null; - } + }, { + key: "get", + value: function get(id) { + return this.words[id]; + } + /** find a term by it's id */ - num = String(num); - var x = num.split('.'); - var x1 = x[0]; - var x2 = x.length > 1 ? '.' + x[1] : ''; - var rgx = /(\d+)(\d{3})/; + }, { + key: "remove", + value: function remove(id) { + delete this.words[id]; + } + }, { + key: "merge", + value: function merge(pool) { + Object.assign(this.words, pool.words); + return this; + } + /** helper method */ - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + ',' + '$2'); - } + }, { + key: "stats", + value: function stats() { + return { + words: Object.keys(this.words).length + }; + } + }]); - return x1 + x2; -}; + return Pool; + }(); + /** make a deep-copy of all terms */ -module.exports = niceNumber; -},{}],61:[function(_dereq_,module,exports){ -'use strict'; + Pool.prototype.clone = function () { + var _this = this; -var toString = _dereq_('./toString'); //turn a number like 5 into an ordinal like 5th + var keys = Object.keys(this.words); + var words = keys.reduce(function (h, k) { + var t = _this.words[k].clone(); + h[t.id] = t; + return h; + }, {}); + return new Pool(words); + }; -var numOrdinal = function numOrdinal(num) { - if (!num && num !== 0) { - return null; - } //the teens are all 'th' + var Pool_1 = Pool; + //(Rule-based sentence boundary segmentation) - chop given text into its proper sentences. + // Ignore periods/questions/exclamations used in acronyms/abbreviations/numbers, etc. + // @spencermountain 2017 MIT + //proper nouns with exclamation marks + // const blacklist = { + // yahoo: true, + // joomla: true, + // jeopardy: true, + // } + //regs- + var initSplit = /(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g; + var hasSomething = /\S/; + var isAcronym$1 = /[ .][A-Z]\.? *$/i; + var hasEllipse = /(?:\u2026|\.{2,}) *$/; + var newLine = /((?:\r?\n|\r)+)/; // Match different new-line formats - var tens = num % 100; + var hasLetter = /[a-z0-9\u00C0-\u00FF\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]/i; + var startWhitespace = /^\s+/; // Start with a regex: - if (tens > 10 && tens < 20) { - return String(num) + 'th'; - } //the rest of 'em + var naiive_split = function naiive_split(text) { + var all = []; //first, split by newline + var lines = text.split(newLine); - var mapping = { - 0: 'th', - 1: 'st', - 2: 'nd', - 3: 'rd' - }; - var str = toString(num); - var last = str.slice(str.length - 1, str.length); - - if (mapping[last]) { - str += mapping[last]; - } else { - str += 'th'; - } + for (var i = 0; i < lines.length; i++) { + //split by period, question-mark, and exclamation-mark + var arr = lines[i].split(initSplit); - return str; -}; + for (var o = 0; o < arr.length; o++) { + all.push(arr[o]); + } + } -module.exports = numOrdinal; + return all; + }; + /** does this look like a sentence? */ -},{"./toString":64}],62:[function(_dereq_,module,exports){ -'use strict'; -var toString = _dereq_('./toString'); // turns an integer/float into a textual number, like 'fifty-five' + var isSentence = function isSentence(str, abbrevs) { + // check for 'F.B.I.' + if (isAcronym$1.test(str) === true) { + return false; + } //check for '...' -var tens_mapping = [['ninety', 90], ['eighty', 80], ['seventy', 70], ['sixty', 60], ['fifty', 50], ['forty', 40], ['thirty', 30], ['twenty', 20]]; -var ones_mapping = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']; -var sequence = [[1e24, 'septillion'], [1e21, 'sextillion'], [1e18, 'quintillion'], [1e15, 'quadrillion'], [1e12, 'trillion'], [1e9, 'billion'], [1e8, 'hundred million'], [1e6, 'million'], [100000, 'hundred thousand'], [1000, 'thousand'], [100, 'hundred'], [1, 'one']]; //turn number into an array of magnitudes, like [[5, million], [2, hundred]] + if (hasEllipse.test(str) === true) { + return false; + } // must have a letter -var breakdown_magnitudes = function breakdown_magnitudes(num) { - var working = num; - var have = []; - sequence.forEach(function (a) { - if (num >= a[0]) { - var howmany = Math.floor(working / a[0]); - working -= howmany * a[0]; - if (howmany) { - have.push({ - unit: a[1], - count: howmany - }); - } + if (hasLetter.test(str) === false) { + return false; } - }); - return have; -}; //turn numbers from 100-0 into their text + var txt = str.replace(/[.!?\u203D\u2E18\u203C\u2047-\u2049] *$/, ''); + var words = txt.split(' '); + var lastWord = words[words.length - 1].toLowerCase(); // check for 'Mr.' -var breakdown_hundred = function breakdown_hundred(num) { - var arr = []; + if (abbrevs.hasOwnProperty(lastWord)) { + return false; + } // //check for jeopardy! + // if (blacklist.hasOwnProperty(lastWord)) { + // return false + // } - if (num > 100) { - return arr; //something bad happened.. - } - for (var i = 0; i < tens_mapping.length; i++) { - if (num >= tens_mapping[i][1]) { - num -= tens_mapping[i][1]; - arr.push(tens_mapping[i][0]); - } - } //(hopefully) we should only have 20-0 now + return true; + }; + var splitSentences = function splitSentences(text, world) { + var abbrevs = world.cache.abbreviations; + text = text || ''; + text = String(text); + var sentences = []; // First do a greedy-split.. - if (ones_mapping[num]) { - arr.push(ones_mapping[num]); - } + var chunks = []; // Ensure it 'smells like' a sentence - return arr; -}; -/** print-out 'point eight nine'*/ + if (!text || typeof text !== 'string' || hasSomething.test(text) === false) { + return sentences; + } // Start somewhere: -var handle_decimal = function handle_decimal(num) { - var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']; - var arr = []; //parse it out like a string, because js math is such shit + var splits = naiive_split(text); // Filter-out the crap ones - var str = toString(num); - var decimal = str.match(/\.([0-9]+)/); + for (var i = 0; i < splits.length; i++) { + var s = splits[i]; - if (!decimal || !decimal[0]) { - return arr; - } + if (s === undefined || s === '') { + continue; + } //this is meaningful whitespace - arr.push('point'); - var decimals = decimal[0].split(''); - for (var i = 0; i < decimals.length; i++) { - arr.push(names[decimals[i]]); - } + if (hasSomething.test(s) === false) { + //add it to the last one + if (chunks[chunks.length - 1]) { + chunks[chunks.length - 1] += s; + continue; + } else if (splits[i + 1]) { + //add it to the next one + splits[i + 1] = s + splits[i + 1]; + continue; + } + } //else, only whitespace, no terms, no sentence - return arr; -}; -/** turns an integer into a textual number */ + chunks.push(s); + } //detection of non-sentence chunks: + //loop through these chunks, and join the non-sentence chunks back together.. -var to_text = function to_text(num) { - //big numbers, north of sextillion, aren't gonna work well.. - //keep them small.. - if (num > 1e21) { - return [String(num)]; - } - var arr = []; //handle negative numbers + for (var _i = 0; _i < chunks.length; _i++) { + var c = chunks[_i]; //should this chunk be combined with the next one? - if (num < 0) { - arr.push('negative'); - num = Math.abs(num); - } //break-down into units, counts + if (chunks[_i + 1] && isSentence(c, abbrevs) === false) { + chunks[_i + 1] = c + (chunks[_i + 1] || ''); + } else if (c && c.length > 0) { + //&& hasLetter.test(c) + //this chunk is a proper sentence.. + sentences.push(c); + chunks[_i] = ''; + } + } //if we never got a sentence, return the given text - var units = breakdown_magnitudes(num); //build-up the string from its components + if (sentences.length === 0) { + return [text]; + } //move whitespace to the ends of sentences, when possible + //['hello',' world'] -> ['hello ','world'] - for (var i = 0; i < units.length; i++) { - var unit_name = units[i].unit; - if (unit_name === 'one') { - unit_name = ''; //put an 'and' in here + for (var _i2 = 1; _i2 < sentences.length; _i2 += 1) { + var ws = sentences[_i2].match(startWhitespace); - if (arr.length > 1) { - arr.push('and'); + if (ws !== null) { + sentences[_i2 - 1] += ws[0]; + sentences[_i2] = sentences[_i2].replace(startWhitespace, ''); } } - arr = arr.concat(breakdown_hundred(units[i].count)); - arr.push(unit_name); - } //also support decimals - 'point eight' - - - arr = arr.concat(handle_decimal(num)); //remove empties - - arr = arr.filter(function (s) { - return s; - }); - - if (arr.length === 0) { - arr[0] = ''; - } - - return arr; -}; - -module.exports = to_text; // console.log(to_text(-1000.8)); - -},{"./toString":64}],63:[function(_dereq_,module,exports){ -'use strict'; + return sentences; + }; -var textValue = _dereq_('./textCardinal'); + var _01Sentences = splitSentences; // console.log(sentence_parser('john f. kennedy')); + + var wordlike = /\S/; + var isBoundary = /^[!?.]+$/; + var naiiveSplit = /(\S+)/; + var isSlash = /\/\W*$/; + var notWord = { + '.': true, + '-': true, + //dash + '–': true, + //en-dash + '—': true, + //em-dash + '--': true, + '...': true // '/': true, // 'one / two' -var ordinalWord = _dereq_('../../../world/more-data/numbers').toOrdinal; // + }; + var hasHyphen$1 = function hasHyphen(str) { + //dont split 're-do' + if (/^(re|un)-?[^aeiou]./.test(str) === true) { + return false; + } //letter-number -var textOrdinal = function textOrdinal(num) { - var words = textValue(num); //convert the last number to an ordinal - var last = words[words.length - 1]; - words[words.length - 1] = ordinalWord[last] || last; - return words.join(' '); -}; + var reg = /^([a-z\u00C0-\u00FF`"'/]+)(-|–|—)([a-z0-9\u00C0-\u00FF].*)/i; -module.exports = textOrdinal; + if (reg.test(str) === true) { + return true; + } //support weird number-emdash combo '2010–2011' + // let reg2 = /^([0-9]+)(–|—)([0-9].*)/i + // if (reg2.test(str)) { + // return true + // } -},{"../../../world/more-data/numbers":220,"./textCardinal":62}],64:[function(_dereq_,module,exports){ -"use strict"; -//turn big numbers, like 2.3e+22, into a tonne of 0's -var numToString = function numToString(n) { - if (n < 1000000) { - return String(n); - } + return false; + }; // 'he / she' should be one word - var str = n.toFixed(0); - if (str.indexOf('e+') === -1) { - return str; - } + var combineSlashes = function combineSlashes(arr) { + for (var i = 1; i < arr.length - 1; i++) { + if (isSlash.test(arr[i])) { + arr[i - 1] += arr[i] + arr[i + 1]; + arr[i] = null; + arr[i + 1] = null; + } + } - return str.replace('.', '').split('e+').reduce(function (p, b) { - return p + Array(b - p.length + 2).join(0); - }); -}; + return arr; + }; -module.exports = numToString; // console.log(numToString(2.5e+22)); + var splitHyphens = function splitHyphens(word) { + var arr = []; //support multiple-hyphenated-terms -},{}],65:[function(_dereq_,module,exports){ -'use strict'; + var hyphens = word.split(/[-–—]/); -var Text = _dereq_('../../text'); + for (var o = 0; o < hyphens.length; o++) { + if (o === hyphens.length - 1) { + arr.push(hyphens[o]); + } else { + arr.push(hyphens[o] + '-'); + } + } -var Value = _dereq_('./value'); + return arr; + }; //turn a string into an array of terms (naiive for now, lumped later) -var parse = _dereq_('./parse'); //the Values() subset class + var splitWords = function splitWords(str) { + var result = []; + var arr = []; //start with a naiive split -var methods = { - noDates: function noDates() { - return this.not('#Date'); - }, - noUnits: function noUnits() { - return this.not('#Unit'); - }, - units: function units() { - return this.match('#Unit+'); - }, + str = str || ''; - /** five -> 5 */ - numbers: function numbers() { - return this.list.map(function (ts) { - return ts.number(); - }); - }, + if (typeof str === 'number') { + str = String(str); + } - /** five -> '5' */ - toNumber: function toNumber() { - this.list = this.list.map(function (ts) { - return ts.toNumber(); - }); - return this; - }, + var words = str.split(naiiveSplit); - /**5 -> 'five' */ - toText: function toText() { - this.list = this.list.map(function (ts) { - return ts.toText(); - }); - return this; - }, + for (var i = 0; i < words.length; i++) { + //split 'one-two' + if (hasHyphen$1(words[i]) === true) { + arr = arr.concat(splitHyphens(words[i])); + continue; + } - /**5th -> 5 */ - toCardinal: function toCardinal() { - this.list = this.list.map(function (ts) { - return ts.toCardinal(); - }); - return this; - }, + arr.push(words[i]); + } //greedy merge whitespace+arr to the right - /**5 -> 5th */ - toOrdinal: function toOrdinal() { - this.list = this.list.map(function (ts) { - return ts.toOrdinal(); - }); - return this; - }, - /**5900 -> 5,900 */ - toNice: function toNice() { - this.list = this.list.map(function (ts) { - return ts.toNice(); - }); - return this; - }, + var carry = ''; - /**seven === 7th */ - isEqual: function isEqual(num) { - num = parse(num); - this.list = this.list.filter(function (ts) { - return num !== null && ts.number() === num; - }); - return this; - }, + for (var _i = 0; _i < arr.length; _i++) { + var word = arr[_i]; //if it's more than a whitespace - /**eight > 7th */ - greaterThan: function greaterThan(num) { - num = parse(num); - this.list = this.list.filter(function (ts) { - return num !== null && ts.number() > num; - }); - return this; - }, + if (wordlike.test(word) === true && notWord.hasOwnProperty(word) === false && isBoundary.test(word) === false) { + //put whitespace on end of previous term, if possible + if (result.length > 0) { + result[result.length - 1] += carry; + result.push(word); + } else { + //otherwise, but whitespace before + result.push(carry + word); + } - /**five < 7th */ - lessThan: function lessThan(num) { - num = parse(num); - this.list = this.list.filter(function (ts) { - return num !== null && ts.number() < num; - }); - return this; - }, - between: function between(min, max) { - if (min === undefined || max === undefined) { - return this; - } + carry = ''; + } else { + carry += word; + } + } //handle last one - min = parse(min); - max = parse(max); - this.list = this.list.filter(function (ts) { - var n = ts.number(); - return n > min && n < max; - }); - return this; - }, - /**seven + 2 = 'nine' */ - add: function add(n) { - this.list = this.list.map(function (ts) { - return ts.add(n); - }); - return this; - }, + if (carry && result.length > 0) { + result[result.length - 1] += carry; //put it on the end + } // combine 'one / two' - /**seven - 2 = 'five' */ - subtract: function subtract(n) { - this.list = this.list.map(function (ts) { - return ts.subtract(n); - }); - return this; - }, - /**seven -> 'eight' */ - increment: function increment() { - this.list = this.list.map(function (ts) { - return ts.add(1); - }); - return this; - }, + result = combineSlashes(result); // remove empty results - /**seven -> 'eight' */ - decrement: function decrement() { - this.list = this.list.map(function (ts) { - return ts.subtract(1); + result = result.filter(function (s) { + return s; }); - return this; - } -}; - -var find = function find(r, n) { - var tens = 'twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty'; - var teens = 'eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen'; - r = r.match('#Value+ #Unit?'); // r = r.match('#Value+ #Unit?'); - //"50 83" - - if (r.has('#NumericValue #NumericValue')) { - //a comma may mean two numbers - if (r.has('#Value #Comma #Value')) { - r.splitAfter('#Comma'); - } else { - r.splitAfter('#NumericValue'); - } - } //three-length - - - if (r.has('#Value #Value #Value') && !r.has('#Multiple')) { - //twenty-five-twenty - if (r.has('(' + tens + ') #Cardinal #Cardinal')) { - r.splitAfter('(' + tens + ') #Cardinal'); - } - } //two-length ones - - - if (r.has('#Value #Value')) { - //june 21st 1992 is two seperate values - if (r.has('#NumericValue #NumericValue')) { - r.splitOn('#Year'); - } //sixty fifteen - - - if (r.has('(' + tens + ') (' + teens + ')')) { - r.splitAfter('(' + tens + ')'); - } //"72 82" - + return result; + }; - var _double = r.match('#Cardinal #Cardinal'); + var _02Words = splitWords; - if (_double.found && !r.has('(point|decimal)')) { - //not 'two hundred' - if (!_double.has('#Cardinal (#Multiple|point|decimal)')) { - //one proper way, 'twenty one', or 'hundred one' - if (!_double.has('(' + tens + ') #Cardinal') && !_double.has('#Multiple #Value')) { - r.splitAfter(_double.terms(0).out('normal')); - } + var addLinks = function addLinks(terms) { + terms.forEach(function (term, i) { + if (i > 0) { + term.prev = terms[i - 1].id; } - } //seventh fifth - - if (r.match('#Ordinal #Ordinal').match('#TextValue').found && !r.has('#Multiple')) { - //the one proper way, 'twenty first' - if (!r.has('(' + tens + ') #Ordinal')) { - r.splitAfter('#Ordinal'); + if (terms[i + 1]) { + term.next = terms[i + 1].id; } - } //fifth five + }); + }; + /** turn a string into an array of Phrase objects */ - if (r.has('#Ordinal #Cardinal')) { - r.splitBefore('#Cardinal+'); - } //five 2017 (support '5 hundred', and 'twenty 5' + var fromText = function fromText() { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var world = arguments.length > 1 ? arguments[1] : undefined; + var pool = arguments.length > 2 ? arguments[2] : undefined; + //a bit of validation, first + if (typeof text !== 'string') { + if (typeof text === 'number') { + text = String(text); + } + } //tokenize into words - if (r.has('#TextValue #NumericValue') && !r.has('(' + tens + '|#Multiple)')) { - r.splitBefore('#NumericValue+'); - } - } //5-8 + var sentences = _01Sentences(text, world); + sentences = sentences.map(function (str) { + return _02Words(str); + }); //turn them into proper objects - if (r.has('#NumberRange')) { - r.splitAfter('#NumberRange'); - } + pool = pool || new Pool_1(); + var phrases = sentences.map(function (terms) { + terms = terms.map(function (str) { + var term = new Term_1(str); + pool.add(term); + return term; + }); //add next/previous ids - if (typeof n === 'number') { - r = r.get(n); - } + addLinks(terms); //return phrase objects - var world = r.world(); - r.list = r.list.map(function (ts) { - return new Value(ts.terms, world, ts.refText, ts.refTerms); - }); - return r; -}; + return new Phrase_1(terms[0].id, terms.length, pool); + }); //return them ready for a Document object -module.exports = Text.makeSubset(methods, find); + return phrases; + }; // parse the compressed format '3,2|2,4' -},{"../../text":192,"./parse":66,"./value":74}],66:[function(_dereq_,module,exports){ -'use strict'; -var parseText = _dereq_('./parseText'); // 2.5, $5.50, 3,432, etc - + var parseTags = function parseTags(text, tagList) { + return text.split('|').map(function (str) { + var numList = str.split(','); + numList = numList.map(function (n) { + return parseInt(n, 10); + }); // convert a list pf numbers into an array of tag names + return numList.map(function (num) { + if (!tagList[num]) { + console.warn('Compromise import: missing tag at index ' + num); + } -var numeric = /^-?(\$|€|¥|£)?\.?[0-9]+[0-9,\.]*(st|nd|rd|th|rth|%)?$/; + return tagList[num]; + }); + }); + }; + /** create a word-pool and Phrase objects from .export() json*/ -var parseString = function parseString(str) { - if (numeric.test(str) === true) { - //clean up a number, like '$4,342.00' - str = str.replace(/,/g, ''); - str = str.replace(/^[\$|€|¥|£]/g, ''); - str = str.replace(/%$/, ''); - str = str.replace(/(st|nd|rd|th|rth)$/g, ''); - var num = parseFloat(str); - if (num || num === 0) { - return num; + var fromJSON = function fromJSON(json, world) { + if (typeof json === 'string') { + json = JSON.parse(json); } - } - - return parseText(str); -}; //turn it all into a number - -var parse = function parse(val) { - if (val === null || val === undefined || typeof val === 'number') { - return val; - } - - if (typeof val === 'string') { - return parseString(val); - } //numerical values can only be one term + var pool = new Pool_1(); //create Phrase objects + var phrases = json.list.map(function (o) { + // tokenize words from sentence text + var terms = _02Words(o[0]); // unpack the tag data for each term - if (val.terms.length === 1 && val.terms[0].tags.TextValue !== true) { - var str = val.terms[0].normal; - return parseString(str); - } + var tagArr = parseTags(o[1], json.tags); //create Term objects - return parseText(val.out('normal')); -}; + terms = terms.map(function (str, i) { + var term = new Term_1(str); + tagArr[i].forEach(function (tag) { + return term.tag(tag, '', world); + }); + pool.add(term); + return term; + }); //add prev/next links -module.exports = parse; + addLinks(terms); // return a proper Phrase object -},{"./parseText":69}],67:[function(_dereq_,module,exports){ -"use strict"; + return new Phrase_1(terms[0].id, terms.length, pool); + }); + return phrases; + }; -var numbers = _dereq_('../../../world/more-data/numbers'); + var _01Tokenizer = { + fromText: fromText, + fromJSON: fromJSON + }; -var fns = _dereq_('../paths').fns; //setup number-word data + var _version = '12.0.0'; + + var _data = { + "Comparative": "true¦better", + "Superlative": "true¦earlier", + "PresentTense": "true¦is,sounds", + "Value": "true¦a few", + "Noun": "true¦a8b7c5e3f2here,ie,lit,m1no doubt,p0tce,vs;d,l;a,d;t,y;g,sp,tc,x0;!p;a,ca,o0;l,rp;a,c,l;d,l,rc", + "Copula": "true¦a1is,w0;as,ere;m,re", + "PastTense": "true¦be3came,d2had,meant,sa2taken,w0;as,e0;nt,re;id;en,gan", + "Condition": "true¦if,unless", + "Gerund": "true¦accord0be0develop0go0result0stain0;ing", + "Negative": "true¦n0;ever,o0;!n,t", + "QuestionWord": "true¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s", + "Plural": "true¦records", + "Conjunction": "true¦&,aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh", + "Pronoun": "true¦'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s", + "Singular": "true¦0:0X;1:10;a0Wb0Kc0Bd04e02fXgShOici1jel0kitty,lNmJnIoHpDquestion mark,rBs7t4u2womW;nc0Rs 2;doll0Dst0F; rex,a3h2ic,ragedy,v show;ere,i1;l0x return;ist0Pky,omeone,t2uper bowl,yst0W;ep3ri1u2;de0Pff;faMmoM;al0i1o2;om,se;a4i0Jr3u2;dLrpoD;erogaVobl0O;rt,te0I;bjSceGthers;othi1umb0E;a4ee04o2;del,m2nopo0th0C;!my;n,yf0;i0unch;ead start,o2;l0me3u2;se;! run;adf0entlem5irlZlaci04od,rand3u2;l0y; slam,fa2mo2;th01;an;a5ella,ly,ol0r3un2;di1;iTo2;ntiWsN;mi0thV;conomy,gg,ner5veWx2;ampQecu7;ad7e4innSo2ragonf0ude;cumentFg2i0l0or;gy;ath,t2;ec2;tive;!dy;a8eili1h6i4o2redit card;ttage,u2;riJsin;ty,vil w2;ar;andeliGocol2;ate;n2rD;ary;aAel0lesHo6r4u2;n2tterf0;ti1;eakfast,o2;!th8;dy,tt4y2;!fri2;end;le;nki1r2;ri2;er;d4l0noma0u2;nt;ly; homin4verti2;si1;ng;em", + "Actor": "true¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt", + "Honorific": "true¦a03b00cSdReQfiLgKhon,jr,king,lJmEoDp8queen,r4s0taoiseach,vice7;e1fc,gt,ir,r,u0;ltTpt,rg;c0nDrgeaL;ond liJretary;abbi,e0;ar1pAs,v0;!erend; admirY;astPhd,r0vt;esideEi1of0;!essN;me mini5nce0;!ss;fficOp,rd;a3essrs,i2lle,me,r1s0;!tr;!s;stK;gistrate,j,r6yF;i3lb,t;en,ov;eld mar3rst l0;ady,i0;eutena0;nt;shG;sq,xcellency;et,oct6r,utchess;apt6hance4mdr,o0pl;lonel,m2ngress0unci3;m0wom0;an;dr,mand5;ll0;or;!ain;ldg,rig0;!adi0;er;d0sst,tty,yatullah;j,m0v;!ir0;al", + "SportsTeam": "true¦0:1A;1:1H;2:1G;a1Eb16c0Td0Kfc dallas,g0Ihouston 0Hindiana0Gjacksonville jagua0k0El0Bm01newToQpJqueens parkIreal salt lake,sAt5utah jazz,vancouver whitecaps,w3yW;ashington 3est ham0Rh10;natio1Oredski2wizar0W;ampa bay 6e5o3;ronto 3ttenham hotspur;blue ja0Mrapto0;nnessee tita2xasC;buccanee0ra0K;a7eattle 5heffield0Kporting kansas0Wt3;. louis 3oke0V;c1Frams;marine0s3;eah15ounG;cramento Rn 3;antonio spu0diego 3francisco gJjose earthquak1;char08paA; ran07;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat1steele0;il3oenix su2;adelphia 3li1;eagl1philNunE;dr1;akland 3klahoma city thunder,rlando magic;athle0Mrai3;de0; 3castle01;england 7orleans 6york 3;city fc,g4je0FknXme0Fred bul0Yy3;anke1;ian0D;pelica2sain0C;patrio0Brevolut3;ion;anchester Be9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Fvi3;kings;imberwolv1wi2;rewe0uc0K;dolphi2heat,marli2;mphis grizz3ts;li1;cXu08;a4eicesterVos angeles 3;clippe0dodDla9; galaxy,ke0;ansas city 3nE;chiefs,roya0E; pace0polis colU;astr06dynamo,rockeTtexa2;olden state warrio0reen bay pac3;ke0;.c.Aallas 7e3i05od5;nver 5troit 3;lio2pisto2ti3;ge0;broncZnuggeM;cowbo4maver3;ic00;ys; uQ;arCelKh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki1;brow2cavalie0india2;bengaWre3;ds;arlotte horAicago 3;b4cubs,fire,wh3;iteB;ea0ulR;diff3olina panthe0; c3;ity;altimore 9lackburn rove0oston 5rooklyn 3uffalo bilN;ne3;ts;cel4red3; sox;tics;rs;oriol1rave2;rizona Ast8tlanta 3;brav1falco2h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls", + "Uncountable": "true¦a1Ib1Ac11d0Ye0Rf0Lg0Hh0Ci08j07knowled1Hl02mUnews,oTpQrLsAt5vi4w0;a2ea05i1oo0;d,l;ldlife,ne;rmth,t17;neg0Yol06tae;e3h2oothpaste,r0una;affPou0;ble,sers,t;ermod1Eund12;a,nnis;a8cene04eri0Oh7il6kittl0Onow,o5p3t1u0;g0Rnshi0H;ati1De0;am,el;ace16e0;ci0Jed;ap,cc0U;k,v0T;eep,ingl0G;d04fe10l0nd;m0St;a3e1ic0;e,ke0D;c0laxa09search;ogni08rea08;bi09in;aJe1hys10last5o0ressV;lit0Zrk,w0J;a0Vtrol;bstetr0Xil,xygen;a5e3ilk,o2u0;mps,s0;ic;nGo0A;a0chan0S;slZt;chine0il,themat0Q; learn05ry;aught08e2i1ogi0Nu0;ck,g0C;ce,ghtn02ngui0LteratH;a0isG;th04;ewel7usti0G;ce,mp0nformaOtself;a0ortan0E;ti0;en0C;a3isto2o0;ck0mework,n0spitali06;ey;ry;ir,libut,ppi7;en01o1r0um,ymna08;a6ound;l0ssip;d,f;i4lour,o1urnit0;ure;od,rgive0uriNwl;ne0;ss;c6sh;conomZduca5lectr4n2quip3thZvery0;body,o0thE;ne;joy0tertain0;ment;iciNonU;tiF;ar1iabet0raugh1;es;ts;a7elcius,h3ivPl2o0urrency;al,ld w0nfusiAttA;ar;assMoth2;aos,e0;e1w0;ing;se;r4sh;a4eef,i1lood,owls,read,utt0;er;lliar1s0;on;ds;g0ss;ga0;ge;c6dvi5ero3ir2mnes1rt,thl0;et7;ty;craft;b4d0naut4;ynam3;ce;id,ou0;st0;ics", + "Infinitive": "true¦0:6H;1:6V;2:55;3:6S;4:6T;5:5W;6:64;7:6R;8:6N;9:6F;A:6P;B:6M;C:6A;D:6W;a67b5Wc4Yd46e3Qf3Dg37h30i2Nj2Lk2Jl2Am20n1Xo1Tp1Eques3Er0Ms01tTuPvMwFyE;awn,ield;aHe1Thist6iGoEre60;nd0rE;k,ry;pe,sh,th0;lk,nFrEsh,tCve;n,raD;d0t;aFiEo7;ew,sB;l68ry;nFpEr3se;gra4Jli3W;dEi7lo5O;er47o;aKeJhIoHrFuEwi8;ne,rn;aEe0Ki5Ku8y;de,in,nsf0p,v5C;r2VuC;ank,reat2L;nd,st;lk,rg1Ms7;aXcUeThRi48kip,lQmPnee3Ho4WpOtHuEwitC;bmBck,ff0gge8ppFrEspe5;ge,pri1rou4Tvi4;ly,o32;aJeIoHrFuE;dy,mb6;a4NeEi4;ngth2Bss,tC;p,re;m,p;in,ke,r0Oy;la50oil,rink6;e1Vi6o3F;am,ip;a2iv0oE;ck,ut;arCem,le5n1r4tt6;aFo2rE;atCew;le,re;il,ve;a03eGisk,oFuE;in,le,sh;am,ll;aZcXdu9fWgVje5lSmRnt,pOquNsItHvEwa5L;eEiew,o32;al,l,rE;se,t;a41i2u3Y;eHi8oGtE;!o2rE;i5uc1W;l4rt;mb6nt,r4;e8i2;air,eFlEo3XreseD;a9y;at;a3Remb0i3To4;aFeEi4y;a1nt;te,x;a53r0F;act1Uer,le5u1;a0Zei4k5FoEyc6;gni28nci6rd;ch,li27s5D;i1nE;ge,k;aRerQiPlMoKrGuE;b1Xll,mp,rEsh;cha1s4G;ai1eGiDoE;cEdu9greAhibBmi1te8vi2R;eAlaim;di5pa2ss,veD;iDp,rtr3WsEur;e,t;aFuE;g,n3;n,y;ck,le;fo2YmBsi8;ck,iDrt4Css,u1;bGccur,ff0pera7utweFverEwe;co3Xlap,ta1Yu1whelm;igh;ser4ta2Y;eFotE;e,i9;ed,gle5;aJeIiGoFuE;ltip3Ard0;nit10ve;nErr0Z;d,g6us;asu2lt,n0Mr3ssa3;inta2Ona3rFtE;ch,t0;ch,kEry;et;aKeJiGoEu1A;aEck,ok,ve;d,n;ft,ke,mBnFstEve;!en;e,k;a2Bc0Ct;b0Lck,uE;gh,nC;iEno2W;ck,ll,ss;am,o29uE;d3mp;gno2mOnEss39;cMdica7flu0KhLsItGvE;eEol4;nt,st;erErodu9;a5fe2;i8tE;aEru5;ll;abBibB;lu1Cr1A;agi20pE;lemeDo1Yro4;aIeGi2oFuE;nt,rry;n00pe,st;aElp;d,t;nd6ppErm,te;en;aIloAove1KrGuE;arEeAi11;ant30d;aEip,umb6;b,sp;in,th0ze;aOeaNiLlJoGracFuncE;ti3A;tu2;cus,lFrE;ce,eca8m,s2S;d,l1W;a1ToE;at,od,w;gu2lEni1Rx;e,l;r,tu2;il,vE;or;a11cho,le5mQnNstLvalua7xE;a08cJerIi8pEte15;a14eFla12oEreA;rt,se;ct,riE;en9;ci1t;el,han3;abEima7;li1D;ab6couVdFfor9ga3han9j01riCsu2t0vE;isi2Ny;!u2;body,er3pE;hasiEow0;ze;a04eSiJoIrFuE;mp;aFeAiE;ft;g,in;d3ubt;ff0p,re5sFvE;iWor9;aIcFliEmiApl13tingui0Y;ke;oEuA;uEv0;ra3;gr1QppE;ear,ro4;cLem,fJliv0ma0Bny,pIsFterE;mi0C;cribe,er4iFtrE;oy;gn,re;a07e06i5osB;eEi07y;at,ct;iGlFrE;ea1;a2i03;de;ma3n9re,te;a08e07h04i7l02oHrE;aFeEoAu0Dy;a7dB;ck,ve;llXmQnFok,py,uEv0;gh,nt;ceNdu5fKsItGvE;eEin9;rt,y;aNin0PrE;a8ibu7ol;iEtitu7;d0st;iFoEroD;rm;gu2rm;rn;biJfoImaHpE;a2laE;in;re;nd;rt;ne;ap1e5;aEip,o1;im,w;aFeE;at,ck,w;llen3n3r3se;a1nt0;ll,ncFrEt0u1;e,ry;el;aNeKloJoHruGuE;lEry;ly;sh;a8mb,o8rrEth0un9;ow;ck;ar,lFnefBtrE;ay;ie4ong;ng,se;band0Hc09d04ffo03gr02id,lZmu1nWppRrOsIttEvoid,waB;acGeFra5;ct;m0Dnd;h,k;k,sE;eGiFocia7uE;me;gn,st;mb6rt;le;chFgEri4;ue;!i4;eaHlGroE;aCve;ch;aud,y;l,r;noun9sw0tE;icipa7;ce;lFt0;er;e3ow;ee;rd;aPdGju8mBoP;it;st;!reA;ss;cHhie4knowled3tiva7;te;ge;ve;eGouDu1;se;nt;pt;on", + "Unit": "true¦0:16;a11b0Zc0Ld0Ke0If0Dg09h06in0Ejoule0k00lYmNnMoLpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Kb,d0Qears old,o1;tt0E;att0b;able4b3e2on1sp;!ne0;a2r0A;!l,sp;spo01; ft,uare 1;c0Fd0Ef3i0Ckilo0Gm1ya0B;e0Jil1;e0li0E;eet0o0A;t,uart0;ascals,e2i1ou0Mt;c0Jnt0;rcent,tZ;hms,uVz;an0GewtQ;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;e1g,z;ct1rtz0;aXogQ;al2b,igAra1;in0m0;!l1;on0;a4emtPl2t1;²,³; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s", + "Organization": "true¦0:46;a3Ab2Qc2Ad21e1Xf1Tg1Lh1Gi1Dj19k17l13m0Sn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0Xou1w0X;gov,tu2S;a3e1orld trade organizati41;lls fargo,st1;fie22inghou16;l1rner br3D;-m11gree31l street journ25m11;an halNeriz3Wisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Rps;es35i1;lev2Xted natio2Uv; mobi2Kaco bePd bMeAgi frida9h3im horto2Tmz,o1witt2W;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen33daily ma2Xguess w2holli0rolling st1Ms1w2;mashing pumpki2Ouprem0;ho;ea1lack eyed pe3Fyrds;ch bo1tl0;ys;l2s1;co,la m12;efoni07us;a6e4ieme2Gnp,o2pice gir5ta1ubaru;rbucks,to2N;ny,undgard1;en;a2Rx pisto1;ls;few25insbu26msu1X;.e.m.,adiohead,b6e3oyal 1yan2X;b1dutch she4;ank;/max,aders dige1Ed 1vl32;bu1c1Uhot chili peppe2Klobst28;ll;c,s;ant2Vizno2F;an5bs,e3fiz24hilip morrBi2r1;emier27octer & gamb1Rudenti14;nk floyd,zza hut;psi28tro1uge08;br2Qchina,n2Q; 2ason1Xda2G;ld navy,pec,range juli2xf1;am;us;a9b8e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0K;l,s;c,st1Etflix,w1; 1sweek;kids on the block,york08;a,c;nd1Us2t1;ional aca2Fo,we0Q;a,cYd0O;aAcdonald9e5i3lb,o1tv,yspace;b1Nnsanto,ody blu0t1;ley crue,or0O;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt13z1Y;'ore09a3e1g,ittle caesa1Ktd;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1K;art;iffy lu0Lo3pmorgan1sa;! cha1;se;hnson & johns1Sy d1R;bm,hop,n1tv;c,g,te1;l,rpol; & m,asbro,ewlett-packaTi3o1sbc,yundai;me dep1n1J;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Iu1;cci,ns n ros0;ldman sachs,o1;dye1g0B;ar;axo smith kliZencore;electr0Im1;oto0V;a3bi,da,edex,i1leetwood mac,oGrito-l0A;at,nancial1restoV; tim0;cebook,nnie mae;b06sa,u3xxon1; m1m1;ob0H;!rosceptics;aiml0Ae5isney,o3u1;nkin donuts,po0Wran dur1;an;j,w j1;on0;a,f leppa3ll,p2r spiegZstiny's chi1;ld;eche mode,t;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra05;al;!ca c5l4m1o0Ast05;ca2p1;aq;st;dplMgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Hy;dbury,pital o1rl's jr;ne;aGbc,eCfAl6mw,ni,o2p,r1;exiteeWos;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roX;ckbuster video,omingda1;le; g1g1;oodriN;cht3e ge0n & jer2rkshire hathaw1;ay;ryH;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bXcSdidRerosmith,ig,lLmFnheuser-busEol,ppleAr7s3t&t,v2y1;er;is,on;hland2s1;n,ociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c", + "Demonym": "true¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an", + "Possessive": "true¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne", + "Currency": "true¦$,aud,bScQdLeurKfJgbp,hkd,iIjpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotySł;en,uanR;af,of;h0t5;e0il5;k0q0;elM;iel,oubleLp,upeeL;e2ound st0;er0;lingI;n0soH;ceGn0;ies,y;e0i8;i,mpi7;n,r0wanzaCyatC;!onaBw;ls,nr;ori7ranc9;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s", + "City": "true¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,sario,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg", + "Abbreviation": "true¦a08b05cZdXeUfSgRhQiPjNkanMlKmGnEoDpCque,rAs6t4u3v2w0;is0y00;!c;a,s,t;niv,safa,t;ce,e0;nn,x;ask,e1fc,gt,ir,r,t,u0;pt,rg;nDp0;!t;d,e0;pAs,v;a,d,ennGhd,l,rof,vt;ct,kla,nt,p,rd;eb0ov;!r;a2d,essrs,i1lle,me,r5s0t;!tr;nn,ster;!j,r;it,lb,t0;!d;!s;an,r,u0;l,n;a,da,e,nc;on,wy;a,en,ov;eb,l0t,y;!a;g,s1tc,x0;!p;p,q;ak,e0ist,r;c,pt,t;a3ca,l,m2o0pl,res,t;!l0m1nn,rp;!o;dr;!l0pt;!if;a,c,l1r0;ig,os;!dg,vd;d3l2pr,r1ss0tty,ug,ve;n,t;c,iz;!ta;!j,m,v", + "Place": "true¦a07b05cZdYeXfVgRhQiOjfk,kMlKmHneEoDp9que,rd,s8t5u4v3w0yyz;is1y0;!o;!c;a,t;pYsafa,t;e1he 0;bronx,hamptons;nn,x;ask,fo,oho,t,under6yd;a2e1h0;l,x;k,nnK;!cifX;kla,nt;b1w eng0;land;!r;a1co,i0t,uc;dKnn;libu,nhattS;a0gw,hr;s,x;an0ul;!s;a0cn,da,ndianMst;!x;arlem,kg,nd,wy;a2re0;at 0enwich;britain,lak6;!y village;co,l0ra;!a;urope,verglad2;ak,en,fw,ist,own4xb;al4dg,gk,hina3l2o1r0t;es;lo,nn;!t;town;!if;cn,e0kk,lvd,rooklyn;l air,verly hills;frica,lta,m5ntarct2r1sia,tl0ve;!ant1;ct0iz;ic0; oce0;an;ericas,s", + "Country": "true¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an", + "Region": "true¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma", + "FemaleName": "true¦0:FY;1:G2;2:FR;3:FD;4:FC;5:EP;6:ER;7:FS;8:GF;9:EZ;A:GB;B:E5;C:FO;D:FL;E:G8;F:EG;aE2bD4cB8dAIe9Gf91g8Hh83i7Sj6Uk60l4Om38n2To2Qp2Fqu2Er1Os0Qt04ursu6vUwOyLzG;aJeHoG;e,la,ra;lGna;da,ma;da,ra;as7EeHol1TvG;et5onB9;le0sen3;an9endBNhiB4iG;lInG;if3AniGo0;e,f39;a,helmi0lGma;a,ow;aMeJiG;cHviG;an9XenG1;kCZtor3;da,l8Vnus,rG;a,nGoniD2;a,iDC;leGnesEC;nDLrG;i1y;aSePhNiMoJrGu6y4;acG3iGu0E;c3na,sG;h9Mta;nHrG;a,i;i9Jya;a5IffaCGna,s7;al3eGomasi0;a,l8Go6Xres1;g7Uo6WrHssG;!a,ie;eFi,ri8;bNliMmKnIrHs7tGwa0;ia0um;a,yn;iGya;a,ka,s7;a4e4iGmCAra;!ka;a,t7;at7it7;a05carlet2Ye04hUiSkye,oQtMuHyG;bFJlvi1;e,sHzG;an2Tet5ie,y;anGi8;!a,e,nG;aDe;aIeG;fGl3DphG;an2;cF8r6;f3nGphi1;d4ia,ja,ya;er4lv3mon1nGobh75;dy;aKeGirlBLo0y6;ba,e0i6lIrG;iGrBPyl;!d70;ia,lBV;ki4nIrHu0w0yG;la,na;i,leAon,ron;a,da,ia,nGon;a,on;l5Yre0;bMdLi9lKmIndHrGs7vannaD;aDi0;ra,y;aGi4;nt7ra;lBNome;e,ie;in1ri0;a02eXhViToHuG;by,thBK;bQcPlOnNsHwe0xG;an94ie,y;aHeGie,lE;ann8ll1marBFtB;!lGnn1;iGyn;e,nG;a,d7W;da,i,na;an9;hel53io;bin,erByn;a,cGkki,na,ta;helBZki;ea,iannDXoG;da,n12;an0bIgi0i0nGta,y0;aGee;!e,ta;a,eG;cARkaD;chGe,i0mo0n5EquCDvCy0;aCCelGi9;!e,le;een2ia0;aMeLhJoIrG;iGudenAW;scil1Uyamva9;lly,rt3;ilome0oebe,ylG;is,lis;arl,ggy,nelope,r6t4;ige,m0Fn4Oo6rvaBBtHulG;a,et5in1;ricGsy,tA8;a,e,ia;ctav3deHfAWlGphAW;a,ga,iv3;l3t5;aQePiJoGy6;eHrG;aDeCma;ll1mi;aKcIkGla,na,s7ta;iGki;!ta;hoB2k8BolG;a,eBH;!mh;l7Tna,risF;dIi5PnHo23taG;li1s7;cy,et5;eAiCO;a01ckenz2eViLoIrignayani,uriBGyG;a,rG;a,na,tAS;i4ll9XnG;a,iG;ca,ka,qB4;a,chOkaNlJmi,nIrGtzi;aGiam;!n9;a,dy,erva,h,n2;a,dIi9JlG;iGy;cent,e;red;!e6;ae6el3G;ag4KgKi,lHrG;edi61isFyl;an2iGliF;nGsAM;a,da;!an,han;b08c9Ed06e,g04i03l01nZrKtJuHv6Sx87yGz2;a,bell,ra;de,rG;a,eC;h75il9t2;a,cSgOiJjor2l6In2s7tIyG;!aGbe5QjaAlou;m,n9S;a,ha,i0;!aIbALeHja,lEna,sGt53;!a,ol,sa;!l06;!h,m,nG;!a,e,n1;arIeHie,oGr3Kueri5;!t;!ry;et3IiB;elGi61y;a,l1;dGon,ue6;akranBy;iGlo36;a,ka,n9;a,re,s2;daGg2;!l2W;alEd2elGge,isBGon0;eiAin1yn;el,le;a0Ie08iWoQuKyG;d3la,nG;!a,dHe9SnGsAQ;!a,e9R;a,sAO;aB1cJelIiFlHna,pGz;e,iB;a,u;a,la;iGy;a2Ae,l25n9;is,l1GrHtt2uG;el6is1;aIeHi8na,rG;a6Zi8;lei,n1tB;!in1;aQbPd3lLnIsHv3zG;!a,be4Ket5z2;a,et5;a,dG;a,sGy;ay,ey,i,y;a,iaIlG;iGy;a8Ge;!n4F;b7Terty;!n5R;aNda,e0iLla,nKoIslARtGx2;iGt2;c3t3;la,nGra;a,ie,o4;a,or1;a,gh,laG;!ni;!h,nG;a,d4e,n4N;cNdon7Si6kes7na,rMtKurIvHxGy6;mi;ern1in3;a,eGie,yn;l,n;as7is7oG;nya,ya;a,isF;ey,ie,y;aZeUhadija,iMoLrIyG;lGra;a,ee,ie;istGy5B;a,en,iGy;!e,n48;ri,urtn9A;aMerLl99mIrGzzy;a,stG;en,in;!berlG;eGi,y;e,y;a,stC;!na,ra;el6PiJlInHrG;a,i,ri;d4na;ey,i,l9Qs2y;ra,s7;c8Wi5XlOma6nyakumari,rMss5LtJviByG;!e,lG;a,eG;e,i78;a5EeHhGi3PlEri0y;ar5Cer5Cie,leCr9Fy;!lyn73;a,en,iGl4Uyn;!ma,n31sF;ei72i,l2;a04eVilToMuG;anKdJliGst56;aHeGsF;!nAt0W;!n8X;i2Ry;a,iB;!anLcelEd5Vel71han6IlJni,sHva0yG;a,ce;eGie;fi0lEph4X;eGie;en,n1;!a,e,n36;!i10lG;!i0Z;anLle0nIrHsG;i5Qsi5Q;i,ri;!a,el6Pif1RnG;a,et5iGy;!e,f1P;a,e72iHnG;a,e71iG;e,n1;cLd1mi,nHqueliAsmin2Uvie4yAzG;min8;a8eHiG;ce,e,n1s;!lGsFt06;e,le;inHk2lEquelG;in1yn;da,ta;lPmNnMo0rLsHvaG;!na;aHiGob6U;do4;!belGdo4;!a,e,l2G;en1i0ma;a,di4es,gr5R;el9ogG;en1;a,eAia0o0se;aNeKilHoGyacin1N;ll2rten1H;aHdGlaH;a,egard;ry;ath0WiHlGnrietBrmiAst0W;en24ga;di;il75lKnJrGtt2yl75z6D;iGmo4Fri4G;etG;!te;aDnaD;ey,l2;aYeTiOlMold12rIwG;enGyne18;!dolE;acHetGisel9;a,chC;e,ieG;!la;adys,enGor3yn1Y;a,da,na;aJgi,lHna,ov71selG;a,e,le;da,liG;an;!n0;mYnIorgHrG;ald35i,m2Stru73;et5i5T;a,eGna;s1Nvieve;briel3Fil,le,rnet,yle;aReOio0loMrG;anHe9iG;da,e9;!cG;esHiGoi0G;n1s3V;!ca;!rG;a,en43;lHrnG;!an9;ec3ic3;rHtiGy8;ma;ah,rah;d0FileCkBl00mUn4ArRsMtLuKvG;aIelHiG;e,ta;in0Ayn;!ngel2H;geni1la,ni3R;h52ta;meral9peranJtG;eHhGrel6;er;l2Pr;za;iGma,nest29yn;cGka,n;a,ka;eJilImG;aGie,y;!liA;ee,i1y;lGrald;da,y;aTeRiMlLma,no4oJsIvG;a,iG;na,ra;a,ie;iGuiG;se;a,en,ie,y;a0c3da,nJsGzaH;aGe;!beG;th;!a,or;anor,nG;!a;in1na;en,iGna,wi0;e,th;aWeKiJoGul2U;lor51miniq3Yn30rGtt2;a,eCis,la,othGthy;ea,y;an09naDonAx2;anPbOde,eNiLja,lImetr3nGsir4U;a,iG;ce,se;a,iHla,orGphiA;es,is;a,l5J;dGrdG;re;!d4Mna;!b2CoraDra;a,d4nG;!a,e;hl3i0mMnKphn1rHvi1WyG;le,na;a,by,cHia,lG;a,en1;ey,ie;a,et5iG;!ca,el1Aka;arGia;is;a0Qe0Mh04i02lUoJrHynG;di,th3;istGy04;al,i0;lOnLrHurG;tn1D;aId28iGn28riA;!nG;a,e,n1;!l1S;n2sG;tanGuelo;ce,za;eGleC;en,t5;aIeoHotG;il4B;!pat4;ir8rIudG;et5iG;a,ne;a,e,iG;ce,sX;a4er4ndG;i,y;aPeMloe,rG;isHyG;stal;sy,tG;aHen,iGy;!an1e,n1;!l;lseHrG;!i8yl;a,y;nLrG;isJlHmG;aiA;a,eGot5;n1t5;!sa;d4el1PtG;al,el1O;cHlG;es5i3F;el3ilG;e,ia,y;iYlXmilWndVrNsLtGy6;aJeIhGri0;erGleCrEy;in1;ri0;li0ri0;a2GsG;a2Fie;a,iMlKmeIolHrG;ie,ol;!e,in1yn;lGn;!a,la;a,eGie,y;ne,y;na,sF;a0Di0D;a,e,l1;isBl2;tlG;in,yn;arb0CeYianXlVoTrG;andRePiIoHyG;an0nn;nwEok8;an2NdgKg0ItG;n27tG;!aHnG;ey,i,y;ny;etG;!t8;an0e,nG;da,na;i8y;bbi8nG;iBn2;ancGossom,ythe;a,he;ca;aRcky,lin9niBrNssMtIulaDvG;!erlG;ey,y;hHsy,tG;e,i0Zy8;!anG;ie,y;!ie;nGt7yl;adHiG;ce;et5iA;!triG;ce,z;a4ie,ra;aliy29b24d1Lg1Hi19l0Sm0Nn01rWsNthe0uJvIyG;anGes7;a,na;a,r25;drIgusHrG;el3;ti0;a,ey,i,y;hHtrG;id;aKlGt1P;eHi8yG;!n;e,iGy;gh;!nG;ti;iIleHpiB;ta;en,n1t5;an19elG;le;aYdWeUgQiOja,nHtoGya;inet5n3;!aJeHiGmI;e,ka;!mGt5;ar2;!belHliFmT;sa;!le;ka,sGta;a,sa;elGie;a,iG;a,ca,n1qG;ue;!t5;te;je6rea;la;!bHmGstas3;ar3;el;aIberHel3iGy;e,na;!ly;l3n9;da;aTba,eNiKlIma,yG;a,c3sG;a,on,sa;iGys0J;e,s0I;a,cHna,sGza;a,ha,on,sa;e,ia;c3is7jaIna,ssaIxG;aGia;!nd4;nd4;ra;ia;i0nHyG;ah,na;a,is,naD;c7da,leCmLnslKsG;haDlG;inGyW;g,n;!h;ey;ee;en;at7g2nG;es;ie;ha;aVdiSelLrG;eIiG;anLenG;a,e,ne;an0;na;aKeJiHyG;nn;a,n1;a,e;!ne;!iG;de;e,lEsG;on;yn;!lG;iAyn;ne;agaJbHiG;!gaI;ey,i8y;!e;il;ah", + "WeekDay": "true¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s", + "Month": "true¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il", + "FirstName": "true¦aEblair,cCdevBj8k6lashawn,m3nelly,quinn,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0r9;ls7nyatta,rry;am0ess1ude;ie,m0;ie;an,on;as0heyenne;ey,sidy;lex1ndra,ubr0;ey;is", + "LastName": "true¦0:34;1:39;2:3B;3:2Y;4:2E;5:30;a3Bb31c2Od2Ee2Bf25g1Zh1Pi1Kj1Ek17l0Zm0Nn0Jo0Gp05rYsMtHvFwCxBy8zh6;a6ou,u;ng,o;a6eun2Uoshi1Kun;ma6ng;da,guc1Zmo27sh21zaR;iao,u;a7eb0il6o3right,u;li3Bs1;gn0lk0ng,tanabe;a6ivaldi;ssilj37zqu2;a9h8i2Go7r6sui,urn0;an,ynisJ;lst0Prr1Uth;at1Uomps1;kah0Vnaka,ylor;aEchDeChimizu,iBmiAo9t7u6zabo;ar2lliv2AzuE;a6ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n7sa6to;ki;ch2dLtos,z;amBeag1Zi9o7u6;bio,iz,sD;b6dri1MgIj0Tme24osevelt,ssi,ux;erts,ins1;c6ve0F;ci,hards1;ir2os;aEeAh8ic6ow20;as6hl0;so;a6illips;m,n1T;ders5et8r7t6;e0Nr4;ez,ry;ers;h21rk0t6vl4;el,te0J;baBg0Blivei01r6;t6w1O;ega,iz;a6eils1guy5ix1owak,ym1E;gy,ka6var1K;ji6muW;ma;aEeCiBo8u6;ll0n6rr0Bssolini,ñ6;oz;lina,oKr6zart;al0Me6r0U;au,no;hhail4ll0;rci0ssi6y0;!er;eWmmad4r6tsu07;in6tin2;!o;aCe8i6op2uo;!n6u;coln,dholm;fe7n0Qr6w0J;oy;bv6v6;re;mmy,rs5u;aBennedy,imuAle0Lo8u7wo6;k,n;mar,znets4;bay6vacs;asY;ra;hn,rl9to,ur,zl4;aAen9ha3imen2o6u3;h6nYu3;an6ns1;ss1;ki0Es5;cks1nsse0D;glesi9ke8noue,shik7to,vano6;u,v;awa;da;as;aBe8itchcock,o7u6;!a3b0ghNynh;a3ffmann,rvat;mingw7nde6rN;rs1;ay;ns5rrQs7y6;asDes;an4hi6;moJ;a9il,o8r7u6;o,tierr2;ayli3ub0;m2nzal2;nd6o,rcia;hi;erAis9lor8o7uj6;ita;st0urni0;es;ch0;nand2;d7insteHsposi6vaL;to;is1wards;aCeBi9omin8u6;bo6rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw7vi6;es,s;in;aFhBlarkAo6;h5l6op0rbyn,x;em7li6;ns;an;!e;an8e7iu,o6ristens5u3we;i,ng,u3w,y;!n,on6u3;!g;mpb7rt0st6;ro;ell;aBe8ha3lanco,oyko,r6yrne;ooks,yant;ng;ck7ethov5nnett;en;er,ham;ch,h8iley,rn6;es,i0;er;k,ng;dDl9nd6;ers6rA;en,on,s1;on;eks7iy8var2;ez;ej6;ev;ams", + "MaleName": "true¦0:CE;1:BL;2:C2;3:BT;4:B5;5:9V;6:BZ;7:AT;8:BD;9:AX;A:AO;aB4bA8c97d87e7Gf6Yg6Gh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt06u05v00wNxavi3yGzB;aBor0;cBh8Ine;hCkB;!aB1;ar51eB0;ass2i,oCuB;sDu25;nEsDusB;oBsC;uf;ef;at0g;aJeHiCoByaAP;lfgang,odrow;lBn1O;bDey,frBJlB;aA5iB;am,e,s;e89ur;i,nde5sB;!l7t1;de,lCrr6yB;l1ne;lBt3;a93y;aEern1iB;cCha0nceBrg9Bva0;!nt;ente,t5A;lentin49n8Yughn;lyss4Msm0;aTeOhKiIoErCyB;!l3ro8s1;av9QeBist0oy,um0;nt9Iv54y;bDd7XmBny;!as,mBoharu;aAYie,y;i83y;mBt9;!my,othy;adDeoCia7DomB;!as;!do7M;!de9;dErB;en8HrB;an8GeBy;ll,n8F;!dy;dgh,ic9Tnn3req,ts45;aRcotPeNhJiHoFpenc3tBur1Oylve8Hzym1;anDeBua7B;f0phAFvBwa7A;e57ie;!islaw,l7;lom1nA3uB;leyma8ta;dBl7Jm1;!n7;aDeB;lBrm0;d1t1;h6Sne,qu0Uun,wn,y8;aBbasti0k1Xl41rg40th,ymo9I;m9n;!tB;!ie,y;lCmBnti21q4Iul;!mAu4;ik,vato6V;aWeShe92iOoFuCyB;an,ou;b6LdCf9pe6QssB;!elAI;ol2Uy;an,bIcHdGel,geFh0landA9mEnDry,sCyB;!ce;coe,s;!a95nA;an,eo;l3Jr;e4Qg3n7olfo,ri68;co,ky;bAe9U;cBl7;ar5Oc5NhCkBo;!ey,ie,y;a85ie;gCid,ub6x,yBza;ansh,nS;g8WiB;na8Ss;ch5Yfa4lDmCndBpha4sh6Uul,ymo70;al9Yol2By;i9Ion;f,ph;ent2inB;cy,t1;aFeDhilCier62ol,reB;st1;!ip,lip;d9Brcy,tB;ar,e2V;b3Sdra6Ft44ul;ctav2Vliv3m96rFsCtBum8Uw6;is,to;aCc8SvB;al52;ma;i,l49vJ;athJeHiDoB;aBel,l0ma0r2X;h,m;cCg4i3IkB;h6Uola;hol5XkBol5X;!ol5W;al,d,il,ls1vB;il50;anBy;!a4i4;aWeTiKoFuCyB;l21r1;hamCr5ZstaB;fa,p4G;ed,mF;dibo,e,hamDis1XntCsBussa;es,he;e,y;ad,ed,mB;ad,ed;cGgu4kElDnCtchB;!e5;a78ik;house,o03t1;e,olB;aj;ah,hBk7;a4eB;al,l;hClv2rB;le,ri5v2;di,met;ck,hNlLmOnu4rHs1tDuricCxB;!imilian8Cwe5;e,io;eo,hCi52tB;!eo,hew,ia;eBis;us,w;cDio,k86lCqu6Gsha5tBv2;i2Hy;in,on;!el,oKus;achBcolm,ik;ai,y;amBdi,moud;adB;ou;aReNiMlo2RoIuCyB;le,nd1;cEiDkBth3;aBe;!s;gi,s;as,iaB;no;g0nn6RrenDuBwe5;!iB;e,s;!zo;am,on4;a7Bevi,la4SnDoBst3vi;!nB;!a60el;!ny;mCnBr67ur4Twr4T;ce,d1;ar,o4N;aIeDhaled,iBrist4Vu48y3B;er0p,rB;by,k,ollos;en0iEnBrmit,v2;!dCnBt5C;e0Yy;a5ri4N;r,th;na68rBthem;im,l;aYeQiOoDuB;an,liBst2;an,o,us;aqu2eJhnInGrEsB;eChBi7Bue;!ua;!ph;dBge;an,i,on;!aBny;h,s,th4X;!ath4Wie,nA;!l,sBy;ph;an,e,mB;!mA;d,ffGrDsB;sBus;!e;a5JemCmai8oBry;me,ni0O;i6Uy;!e58rB;ey,y;cHd6kGmFrDsCvi3yB;!d6s1;on,p3;ed,od,rBv4M;e4Zod;al,es,is1;e,ob,ub;k,ob,quB;es;aNbrahMchika,gKkeJlija,nuIrGsDtBv0;ai,sB;uki;aBha0i6Fma4sac;ac,iaB;h,s;a,vinBw2;!g;k,nngu52;!r;nacBor;io;im;in,n;aJeFina4VoDuByd56;be25gBmber4CsD;h,o;m3ra33sBwa3X;se2;aDctCitCn4ErB;be20m0;or;th;bKlJmza,nIo,rDsCyB;a43d6;an,s0;lEo4FrDuBv7;hi40ki,tB;a,o;is1y;an,ey;k,s;!im;ib;aQeMiLlenKoIrEuB;illerCsB;!tavo;mo;aDegBov3;!g,orB;io,y;dy,h57nt;nzaBrd1;lo;!n;lbe4Qno,ovan4R;ne,oDrB;aBry;ld,rd4U;ffr7rge;bri4l6rBv2;la1Zr3Eth,y;aReNiLlJorr0IrB;anDedBitz;!dAeBri24;ri23;cDkB;!ie,lB;in,yn;esJisB;!co,zek;etch3oB;yd;d4lBonn;ip;deriDliCng,rnB;an01;pe,x;co;bi0di;arZdUfrTit0lNmGnFo2rCsteb0th0uge8vBym6zra;an,ere2V;gi,iCnBrol,v2w2;est45ie;c07k;och,rique,zo;aGerFiCmB;aFe2P;lCrB;!h0;!io;s1y;nu4;be09d1iEliDmCt1viBwood;n,s;er,o;ot1Ts;!as,j43sB;ha;a2en;!dAg32mEuCwB;a25in;arB;do;o0Su0S;l,nB;est;aYeOiLoErDuCwByl0;ay8ight;a8dl7nc0st2;ag0ew;minFnDri0ugCyB;le;!l03;!a29nBov0;e5ie,y;go,icB;!k;armuCeBll1on,rk;go;id;anIj0lbeHmetri9nFon,rEsDvCwBxt3;ay8ey;en,in;hawn,mo08;ek,ri0F;is,nBv3;is,y;rt;!dB;re;lKmInHrDvB;e,iB;!d;en,iDne5rByl;eBin,yl;l2Vn;n,o,us;!e,i4ny;iBon;an,en,on;e,lB;as;a06e04hWiar0lLoGrEuCyrB;il,us;rtB;!is;aBistobal;ig;dy,lEnCrB;ey,neli9y;or,rB;ad;by,e,in,l2t1;aGeDiByI;fBnt;fo0Ct1;meCt9velaB;nd;nt;rDuCyB;!t1;de;enB;ce;aFeErisCuB;ck;!tB;i0oph3;st3;d,rlBs;eBie;s,y;cBdric,s11;il;lEmer1rB;ey,lCro5y;ll;!os,t1;eb,v2;ar02eUilTlaSoPrCuByr1;ddy,rtI;aJeEiDuCyB;an,ce,on;ce,no;an,ce;nCtB;!t;dCtB;!on;an,on;dCndB;en,on;!foBl7y;rd;bCrByd;is;!by;i8ke;al,lA;nFrBshoi;at,nCtB;!r10;aBie;rd0S;!edict,iCjam2nA;ie,y;to;n7rBt;eBy;tt;ey;ar0Xb0Nd0Jgust2hm0Gid6ja0ElZmXnPputsiOrFsaEuCveBya0ziz;ry;gust9st2;us;hi;aIchHi4jun,maFnDon,tBy0;hBu06;ur;av,oB;ld;an,nd0A;el;ie;ta;aq;dGgel05tB;hoEoB;i8nB;!i02y;ne;ny;reBy;!as,s,w;ir,mBos;ar;an,beOd6eIfFi,lEonDphonHt1vB;aMin;on;so,zo;an,en;onCrB;edP;so;c,jaEksandDssaExB;!and3;er;ar,er;ndB;ro;rtH;ni;en;ad,eB;d,t;in;aColfBri0vik;!o;mBn;!a;dFeEraCuB;!bakr,lfazl;hBm;am;!l;allEel,oulaye,ulB;!lCrahm0;an;ah,o;ah;av,on", + "Person": "true¦ashton kutchSbRcMdKeIgastNhGinez,jEkDleCmBnettJoAp8r4s3t2v0;a0irgin maG;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussain,carlett johanssJlobodan milosevic,uB;ay romano,eese witherspoIo1ush limbau0;gh;d stewart,nald0;inho,o;a0ipJ;lmIris hiltD;prah winfrFra;essiaen,itt romnEubarek;bron james,e;anye west,iefer sutherland,obe bryant;aime,effers8k rowli0;ng;alle ber0itlBulk hogan;ry;ff0meril lagasse,zekiel;ie;a0enzel washingt2ick wolf;lt1nte;ar1lint0ruz;on;dinal wols1son0;! palm2;ey;arack obama,rock;er", + "Verb": "true¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en", + "PhrasalVerb": "true¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2fast,oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut", + "Modal": "true¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld", + "Adjective": "true¦0:75;1:7K;2:7Q;3:7J;4:7C;5:5C;6:48;7:49;8:4S;9:61;A:7H;B:70;C:6Z;D:73;E:5X;a6Jb65c5Rd57e4Tf49g41h3Qi35j33k32l2Rm2Gn27o1Rp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6C;d6Ezy;despr75s5G;!sa7;eGlFste26;co1Il o4L;!k5;aGiFola4B;b7Tce versa,ol55;ca2gabo63nilla;ltWnJpGrb5Asu4tterF;!moC; f34b1OpGsFti1H;ca7et,ide dMtairs;er,i3N;aPbeco6Rconvin27deMeLfair,ivers4knKprecedYrIsGwF;iel20ritt5Z;i1VuF;pervis0specti3;eFu5;cognLgul6Hl6H;own;ndi3v5Txpect0;cid0rF;!grou5OsF;iz0tood;b7ppeaLssu6GuthorF;iz0;i24ra;aJeHhough4PoGrF;i1oubl0;geth8p,rpB;en5QlFm50rr2Ust0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3EoPpOqueami3EtJuFymb64;bHi gener55pFrprisi3;erFre0L;! dup8b,i29;du0seq4U;anda6UeIi0PrFy38;aightFip0; fFfF;or5B;adfaCreotyp0;aEec2Gir1JlendBot on; call0le,mb8phist1XrFu0Xvi42;dBry;gnifica2nF;ceEg7;am2Pe8ocki3ut;cFda1em5lfi2Yni1Wpa69re6;o1Gr3W;at58ient28reec58;cr0me,ns serif;aMeIiGoF;buCtt4UuSy4;ghtFv4;!-29f9;ar,bel,condi1du63fres52lHpublic3WsFtard0;is48oF;lu1na2;e1Euc46;bBciF;al,st;aQeOicayu6lacBopuliCrGuF;bl5Amp0;eJiGoF;!b0AfuDmi32p8;mGor,sFva1;ti6;a4We;ciDmF;a0IiF;er,um;ac20rFti1;feAma2Uplexi3v34;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Msi46;en,posi1; boa5Gg2Kli6;!ay; gua5EbFli6;eat;eHsF;cFer0Hole1;e6uE;d2Tse;ak0eMiLoFua4P;nJrGtF;ab7;thF;!eF;rn;chala2descri50stop;ght5;arby,cessa3Xighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuE;di4FnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abEho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3D;!-0C;nguBst,tt8;ap1Tind5no0A;agg0uF;niOstifi0veni7;de4gno4Clleg4mSnHpso 1WrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenDoxF;ic37;a6i2S;a1er,oce2;iGoF;or;reA;deq3Kppr2Z;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0R;d2RnD;aKelJiHoFumdr3C;neCok0rrFs07ur5;if2T;ghfalut1PspF;an2R;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Kiga23lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Eob4;aUeOinNlMoHrF;a1UeFoz1L;e2Eq13tf9;oHrF; keeps,eFm8tuna1;g05ign;liF;sh;ag30ue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lDr Gux,voF;ri1uri1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiE;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erD;creHeas0gruntl0honeCordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarElJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraBg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainCgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerD;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt", + "Comparable": "true¦0:40;1:4H;2:44;3:4A;4:2X;5:3W;a4Nb43c3Nd3Ce34f2Qg2Eh23i1Uj1Tk1Ql1Hm1Bn15o13p0Tqu0Rr0IsRtKuIvFw7y6za11;ell26ou3;aBe9hi1Xi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Lt;k,ry;n1Sr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Lse5;like0ti1;aAen9hi8i7ough,r6;anqu2Pen1ue;dy,g3Tme0ny,r09;ck,n,rs2Q;d41se;ll,me,rt,s6wd46;te5;aVcarUeThRiQkin0FlMmKoHpGqua1GtAu7w6;eet,ift;b7dd14per0Gr6;e,re2I;sta2Gt4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Gn0V;a1ep,rn;le,rk;e23i3Gright0;ci29ft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g36m6;!y;ek,nd3E;ck,l0mp4;a6iTort,rill,y;dy,ll0Yrp;cu0Sve0Sxy;ce,ed,y;d,fe,int0l1Wv15;aBe9i8o6ude;mantic,o1Jsy,u6;gh,nd;ch,pe,tzy;a6d,mo0I;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aEhoDi1RlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fouZud;ey,k0;li05or,te1C;ain,easa2;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd", + "TextValue": "true¦bMeIfChundredNmMnin9one,qu8s6t0zeroN;enMh3rLw0;e0o;l0ntC;fGve;ir0ousandIree;d,t5;e0ix7;cond,ptEven6xtE;adrDintD;e0th;!t0;e9ie8y;i3o0;rt1ur0;!t2;ie4y;ft0rst,ve;e3h,ie2y;ight0lev2;!e1h,ie0y;th;en1;illion0;!th", + "Ordinal": "true¦bGeDf9hundredHmGnin7qu6s4t0zeroH;enGh1rFwe0;lfFn9;ir0ousandE;d,t4;e0ixt9;cond,ptAvent8xtA;adr9int9;et0th;e6ie8;i2o0;r0urt3;tie5;ft1rst;ight0lev1;e0h,ie2;en1;illion0;th", + "Cardinal": "true¦bGeDf7hundred,mGnine9one,qu6s4t0zero;en,h2rFw0;e0o;lve,n7;irt8ousand,ree;e0ix4;ptAven3xtA;adr9int9;i3o0;r1ur0;!t2;ty;ft0ve;e2y;ight0lev1;!e0y;en;illion", + "Expression": "true¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la", + "Adverb": "true¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori", + "Preposition": "true¦'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut", + "Determiner": "true¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er" + }; + var entity = ['Person', 'Place', 'Organization']; + var nouns = { + Noun: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + // - singular + Singular: { + isA: 'Noun', + notA: 'Plural' + }, + //a specific thing that's capitalized + ProperNoun: { + isA: 'Noun' + }, + // -- people + Person: { + isA: ['ProperNoun', 'Singular'], + notA: ['Place', 'Organization'] + }, + FirstName: { + isA: 'Person' + }, + MaleName: { + isA: 'FirstName', + notA: ['FemaleName', 'LastName'] + }, + FemaleName: { + isA: 'FirstName', + notA: ['MaleName', 'LastName'] + }, + LastName: { + isA: 'Person', + notA: ['FirstName'] + }, + Honorific: { + isA: 'Noun', + notA: ['FirstName', 'LastName'] + }, + // -- places + Place: { + isA: 'Singular', + notA: ['Person', 'Organization'] + }, + Country: { + isA: ['Place', 'ProperNoun'], + notA: ['City'] + }, + City: { + isA: ['Place', 'ProperNoun'], + notA: ['Country'] + }, + Region: { + isA: ['Place', 'ProperNoun'] + }, + Address: { + isA: 'Place' + }, + //---Orgs--- + Organization: { + isA: ['Singular', 'ProperNoun'], + notA: ['Person', 'Place'] + }, + SportsTeam: { + isA: 'Organization' + }, + School: { + isA: 'Organization' + }, + Company: { + isA: 'Organization' + }, + // - plural + Plural: { + isA: 'Noun', + notA: ['Singular'] + }, + //(not plural or singular) + Uncountable: { + isA: 'Noun' + }, + Pronoun: { + isA: 'Noun', + notA: entity + }, + //a word for someone doing something -'plumber' + Actor: { + isA: 'Noun', + notA: entity + }, + //a gerund-as-noun - 'swimming' + Activity: { + isA: 'Noun', + notA: ['Person', 'Place'] + }, + //'kilograms' + Unit: { + isA: 'Noun', + notA: entity + }, + //'Canadians' + Demonym: { + isA: ['Noun', 'ProperNoun'], + notA: entity + }, + //`john's` + Possessive: { + isA: 'Noun' // notA: 'Pronoun', -var ones = fns.extend(numbers.ordinal.ones, numbers.cardinal.ones); -var teens = fns.extend(numbers.ordinal.teens, numbers.cardinal.teens); -var tens = fns.extend(numbers.ordinal.tens, numbers.cardinal.tens); -var multiples = fns.extend(numbers.ordinal.multiples, numbers.cardinal.multiples); //add this one - -multiples.grand = 1000; -module.exports = { - ones: ones, - teens: teens, - tens: tens, - multiples: multiples -}; - -},{"../../../world/more-data/numbers":220,"../paths":73}],68:[function(_dereq_,module,exports){ -'use strict'; //support global multipliers, like 'half-million' by doing 'million' then multiplying by 0.5 - -var findModifiers = function findModifiers(str) { - var mults = [{ - reg: /^(minus|negative)[\s\-]/i, - mult: -1 - }, { - reg: /^(a\s)?half[\s\-](of\s)?/i, - mult: 0.5 // { - // reg: /^(a\s)?quarter[\s\-]/i, - // mult: 0.25 - // } - - }]; - - for (var i = 0; i < mults.length; i++) { - if (mults[i].reg.test(str) === true) { - return { - amount: mults[i].mult, - str: str.replace(mults[i].reg, '') - }; } - } - - return { - amount: 1, - str: str }; -}; - -module.exports = findModifiers; - -},{}],69:[function(_dereq_,module,exports){ -'use strict'; - -var findModifiers = _dereq_('./findModifiers'); - -var words = _dereq_('./data'); - -var isValid = _dereq_('./validate'); - -var parseDecimals = _dereq_('./parseDecimals'); - -var parseNumeric = _dereq_('./parseNumeric'); - -var improperFraction = /^([0-9,\. ]+)\/([0-9,\. ]+)$/; //some numbers we know - -var casualForms = { - // 'a few': 3, - 'a couple': 2, - 'a dozen': 12, - 'two dozen': 24, - zero: 0 -}; // a 'section' is something like 'fifty-nine thousand' -// turn a section into something we can add to - like 59000 - -var section_sum = function section_sum(obj) { - return Object.keys(obj).reduce(function (sum, k) { - sum += obj[k]; - return sum; - }, 0); -}; //turn a string into a number - -var parse = function parse(str) { - //convert some known-numbers - if (casualForms.hasOwnProperty(str) === true) { - return casualForms[str]; - } //'a/an' is 1 - - - if (str === 'a' || str === 'an') { - return 1; - } - - var modifier = findModifiers(str); - str = modifier.str; - var last_mult = null; - var has = {}; - var sum = 0; - var isNegative = false; - var terms = str.split(/[ -]/); - - for (var i = 0; i < terms.length; i++) { - var w = terms[i]; - w = parseNumeric(w); - - if (!w || w === 'and') { - continue; + var verbs = { + Verb: { + notA: ['Noun', 'Adjective', 'Adverb', 'Value'] + }, + // walks + PresentTense: { + isA: 'Verb', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // neutral form - 'walk' + Infinitive: { + isA: 'PresentTense', + notA: ['PastTense', 'Gerund'] + }, + // walking + Gerund: { + isA: 'PresentTense', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // walked + PastTense: { + isA: 'Verb', + notA: ['FutureTense'] + }, + // will walk + FutureTense: { + isA: 'Verb' + }, + // is + Copula: { + isA: 'Verb' + }, + // would have + Modal: { + isA: 'Verb', + notA: ['Infinitive'] + }, + // had walked + PerfectTense: { + isA: 'Verb', + notA: 'Gerund' + }, + Pluperfect: { + isA: 'Verb' + }, + // shown + Participle: { + isA: 'Verb' + }, + // show up + PhrasalVerb: { + isA: 'Verb' + }, + //'up' part + Particle: { + isA: 'PhrasalVerb' } + }; - if (w === '-' || w === 'negative') { - isNegative = true; - continue; + var values = { + Value: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + Ordinal: { + isA: 'Value', + notA: ['Cardinal'] + }, + Cardinal: { + isA: 'Value', + notA: ['Ordinal'] + }, + RomanNumeral: { + isA: 'Cardinal', + //can be a person, too + notA: ['Ordinal', 'TextValue'] + }, + TextValue: { + isA: 'Value', + notA: ['NumericValue'] + }, + NumericValue: { + isA: 'Value', + notA: ['TextValue'] + }, + Money: { + isA: 'Cardinal' + }, + Percent: { + isA: 'Value' } + }; - if (w.charAt(0) === '-') { - isNegative = true; - w = w.substr(1); - } //decimal mode - - - if (w === 'point') { - sum += section_sum(has); - sum += parseDecimals(terms.slice(i + 1, terms.length)); - sum *= modifier.amount; - return sum; - } //improper fraction - - - var fm = w.match(improperFraction); + var anything = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Value']; + var misc = { + //--Adjectives-- + Adjective: { + notA: ['Noun', 'Verb', 'Adverb', 'Value'] + }, + // adjectives that can conjugate + Comparable: { + isA: ['Adjective'] + }, + // better + Comparative: { + isA: ['Adjective'] + }, + // best + Superlative: { + isA: ['Adjective'], + notA: ['Comparative'] + }, + NumberRange: { + isA: ['Contraction'] + }, + Adverb: { + notA: ['Noun', 'Verb', 'Adjective', 'Value'] + }, + // Dates: + //not a noun, but usually is + Date: { + notA: ['Verb', 'Conjunction', 'Adverb', 'Preposition', 'Adjective'] + }, + Month: { + isA: ['Date', 'Singular'], + notA: ['Year', 'WeekDay', 'Time'] + }, + WeekDay: { + isA: ['Date', 'Noun'] + }, + //glue + Determiner: { + notA: anything + }, + Conjunction: { + notA: anything + }, + Preposition: { + notA: anything + }, + // what, who, why + QuestionWord: { + notA: ['Determiner'] + }, + // peso, euro + Currency: {}, + // ughh + Expression: { + notA: ['Noun', 'Adjective', 'Verb', 'Adverb'] + }, + // dr. + Abbreviation: {}, + // internet tags + Url: { + notA: ['HashTag', 'PhoneNumber', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + PhoneNumber: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + HashTag: {}, + AtMention: { + isA: ['Noun'], + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'Email'] + }, + Emoji: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Emoticon: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Email: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + //non-exclusive + Auxiliary: { + notA: ['Noun', 'Adjective', 'Value'] + }, + Acronym: { + notA: ['Plural', 'RomanNumeral'] + }, + Negative: { + notA: ['Noun', 'Adjective', 'Value'] + }, + // if, unless, were + Condition: { + notA: ['Verb', 'Adjective', 'Noun', 'Value'] + } + }; - if (fm) { - var num = parseFloat(fm[1].replace(/[, ]/g, '')); - var denom = parseFloat(fm[2].replace(/[, ]/g, '')); + // i just made these up + var colorMap = { + Noun: 'blue', + Verb: 'green', + Negative: 'green', + Date: 'red', + Value: 'red', + Adjective: 'magenta', + Preposition: 'cyan', + Conjunction: 'cyan', + Determiner: 'cyan', + Adverb: 'cyan' + }; + /** add a debug color to some tags */ - if (denom) { - sum += num / denom || 0; + var addColors = function addColors(tags) { + Object.keys(tags).forEach(function (k) { + if (colorMap[k]) { + tags[k].color = colorMap[k]; + return; } - continue; - } //prevent mismatched units, like 'seven eleven' - - - if (isValid(w, has) === false) { - return null; - } //buildOut section, collect 'has' values + tags[k].isA.some(function (t) { + if (colorMap[t]) { + tags[k].color = colorMap[t]; + return true; + } + return false; + }); + }); + return tags; + }; - if (/^[0-9\.]+$/.test(w)) { - has['ones'] = parseFloat(w); //not technically right - } else if (words.ones.hasOwnProperty(w) === true) { - has['ones'] = words.ones[w]; - } else if (words.teens.hasOwnProperty(w) === true) { - has['teens'] = words.teens[w]; - } else if (words.tens.hasOwnProperty(w) === true) { - has['tens'] = words.tens[w]; - } else if (words.multiples.hasOwnProperty(w) === true) { - var mult = words.multiples[w]; //something has gone wrong : 'two hundred five hundred' + var _color = addColors; - if (mult === last_mult) { - return null; - } //support 'hundred thousand' - //this one is tricky.. + var unique$2 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); + }; //add 'downward' tags (that immediately depend on this one) - if (mult === 100 && terms[i + 1] !== undefined) { - // has['hundreds']= - var w2 = terms[i + 1]; + var inferIsA = function inferIsA(tags) { + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; + var len = tag.isA.length; - if (words.multiples[w2]) { - mult *= words.multiples[w2]; //hundredThousand/hundredMillion + for (var i = 0; i < len; i++) { + var down = tag.isA[i]; - i += 1; + if (tags[down]) { + tag.isA = tag.isA.concat(tags[down].isA); } - } //natural order of things - //five thousand, one hundred.. - - - if (last_mult === null || mult < last_mult) { - sum += (section_sum(has) || 1) * mult; - last_mult = mult; - has = {}; - } else { - //maybe hundred .. thousand - sum += section_sum(has); - last_mult = mult; - sum = (sum || 1) * mult; - has = {}; - } - } - } //dump the remaining has values - - - sum += section_sum(has); //post-process add modifier - - sum *= modifier.amount; - sum *= isNegative ? -1 : 1; //dont return 0, if it went straight-through - - if (sum === 0 && Object.keys(has).length === 0) { - return null; - } + } // clean it up - return sum; -}; -module.exports = parse; + tag.isA = unique$2(tag.isA); + }); + return tags; + }; -},{"./data":67,"./findModifiers":68,"./parseDecimals":70,"./parseNumeric":71,"./validate":72}],70:[function(_dereq_,module,exports){ -'use strict'; + var _isA = inferIsA; -var words = _dereq_('./data'); //concatenate into a string with leading '0.' + var unique$3 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); + }; // crawl the tag-graph and infer any conflicts + // faster than doing this at tag-time -var parseDecimals = function parseDecimals(arr) { - var str = '0.'; + var inferNotA = function inferNotA(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.notA = tag.notA || []; + tag.isA.forEach(function (down) { + if (tags[down] && tags[down].notA) { + // borrow its conflicts + var notA = typeof tags[down].notA === 'string' ? [tags[down].isA] : tags[down].notA || []; + tag.notA = tag.notA.concat(notA); + } + }); // any tag that lists us as a conflict, we conflict it back. - for (var i = 0; i < arr.length; i++) { - var w = arr[i]; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; - if (words.ones.hasOwnProperty(w) === true) { - str += words.ones[w]; - } else if (words.teens.hasOwnProperty(w) === true) { - str += words.teens[w]; - } else if (words.tens.hasOwnProperty(w) === true) { - str += words.tens[w]; - } else if (/^[0-9]$/.test(w) === true) { - str += w; - } else { - return 0; - } - } + if (tags[key].notA.indexOf(k) !== -1) { + tag.notA.push(key); + } + } // clean it up - return parseFloat(str); -}; -module.exports = parseDecimals; + tag.notA = unique$3(tag.notA); + }); + return tags; + }; -},{"./data":67}],71:[function(_dereq_,module,exports){ -'use strict'; //parse a string like "4,200.1" into Number 4200.1 + var _notA = inferNotA; -var parseNumeric = function parseNumeric(str) { - //remove ordinal - 'th/rd' - str = str.replace(/1st$/, '1'); - str = str.replace(/2nd$/, '2'); - str = str.replace(/3rd$/, '3'); - str = str.replace(/([4567890])r?th$/, '$1'); //remove prefixes + // a lineage is all 'incoming' tags that have this as 'isA' + var inferLineage = function inferLineage(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.lineage = []; // find all tags with it in their 'isA' set - str = str.replace(/^[$€¥£¢]/, ''); //remove suffixes + for (var i = 0; i < keys.length; i++) { + if (tags[keys[i]].isA.indexOf(k) !== -1) { + tag.lineage.push(keys[i]); + } + } + }); + return tags; + }; - str = str.replace(/[%$€¥£¢]$/, ''); //remove commas + var _lineage = inferLineage; - str = str.replace(/,/g, ''); //split '5kg' from '5' + var validate = function validate(tags) { + // cleanup format + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; // ensure isA is an array - str = str.replace(/([0-9])([a-z]{1,2})$/, '$1'); - return str; -}; + tag.isA = tag.isA || []; -module.exports = parseNumeric; + if (typeof tag.isA === 'string') { + tag.isA = [tag.isA]; + } // ensure notA is an array -},{}],72:[function(_dereq_,module,exports){ -'use strict'; -var words = _dereq_('./data'); //prevent things like 'fifteen ten', and 'five sixty' + tag.notA = tag.notA || []; + if (typeof tag.notA === 'string') { + tag.notA = [tag.notA]; + } + }); + return tags; + }; // build-out the tag-graph structure -var isValid = function isValid(w, has) { - if (words.ones.hasOwnProperty(w)) { - if (has.ones || has.teens) { - return false; - } - } else if (words.teens.hasOwnProperty(w)) { - if (has.ones || has.teens || has.tens) { - return false; - } - } else if (words.tens.hasOwnProperty(w)) { - if (has.ones || has.teens || has.tens) { - return false; - } - } - return true; -}; + var inferTags = function inferTags(tags) { + // validate data + tags = validate(tags); // build its 'down tags' -module.exports = isValid; + tags = _isA(tags); // infer the conflicts -},{"./data":67}],73:[function(_dereq_,module,exports){ -"use strict"; + tags = _notA(tags); // debug tag color -module.exports = _dereq_('../../paths'); + tags = _color(tags); // find incoming links -},{"../../paths":8}],74:[function(_dereq_,module,exports){ -'use strict'; + tags = _lineage(tags); + return tags; + }; -var paths = _dereq_('../../paths'); + var inference = inferTags; -var Terms = paths.Terms; + var addIn = function addIn(obj, tags) { + Object.keys(obj).forEach(function (k) { + tags[k] = obj[k]; + }); + }; -var parse = _dereq_('./parse'); + var build = function build() { + var tags = {}; + addIn(nouns, tags); + addIn(verbs, tags); + addIn(values, tags); + addIn(misc, tags); // do the graph-stuff -var fmt = _dereq_('./format'); // const unpackRange = function(ts) { -// if (ts.has('#NumberRange')) { -// ts.terms.forEach(t => { -// if (t.silent_term && !t._text) { -// t.text = t.silent_term; -// } -// }); -// } -// return ts; -// }; + tags = inference(tags); + return tags; + }; + var tags = build(); -var parseValue = function parseValue(ts) { - ts.val = ts.match('#Value+'); // ts.val = unpackRange(ts.val); + var seq = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", + cache = seq.split("").reduce(function (n, o, e) { + return n[o] = e, n; + }, {}), + toAlphaCode = function toAlphaCode(n) { + if (void 0 !== seq[n]) return seq[n]; + var o = 1, + e = 36, + t = ""; - ts.val = ts.val.list[0]; - ts.unit = ts.match('#Unit+'); + for (; n >= e; n -= e, o++, e *= 36) { + } - if (ts.unit.found) { - ts.unit = ts.unit.list[0]; - } + for (; o--;) { + var _o = n % 36; - return ts; -}; + t = String.fromCharCode((_o < 10 ? 48 : 55) + _o) + t, n = (n - _o) / 36; + } -var isPercent = function isPercent(val, unit) { - //pre-tagged - if (val.has('#Percent') || unit.has('#Percent')) { - return true; - } // 'five percent' + return t; + }, + fromAlphaCode = function fromAlphaCode(n) { + if (void 0 !== cache[n]) return cache[n]; + var o = 0, + e = 1, + t = 36, + r = 1; + for (; e < n.length; o += t, e++, t *= 36) { + } - if (unit.out('normal') === 'percent') { - return true; - } //'5%' + for (var _e = n.length - 1; _e >= 0; _e--, r *= 36) { + var _t = n.charCodeAt(_e) - 48; + _t > 10 && (_t -= 7), o += _t * r; + } - if (val.out('normal').match(/%$/) !== null) { - return true; - } + return o; + }; - return false; -}; //set the text as the same num format + var encoding = { + toAlphaCode: toAlphaCode, + fromAlphaCode: fromAlphaCode + }, + symbols = function symbols(n) { + var o = new RegExp("([0-9A-Z]+):([0-9A-Z]+)"); + for (var e = 0; e < n.nodes.length; e++) { + var t = o.exec(n.nodes[e]); -var setNumber = function setNumber(ts, num) { - var str = ts.val.out(); + if (!t) { + n.symCount = e; + break; + } - if (ts.has('#Ordinal')) { - if (ts.has('#TextValue')) { - str = fmt.textOrdinal(num); //ordinal text - } else { - str = fmt.ordinal(num); //ordinal number + n.syms[encoding.fromAlphaCode(t[1])] = encoding.fromAlphaCode(t[2]); } - } else if (ts.has('#TextValue')) { - str = fmt.text(num); //cardinal text - } else if (ts.has('#NiceNumber')) { - str = fmt.nice(num); //8,929 number - } else { - str = fmt.cardinal(num); //cardinal number - } //add the unit at the end - - - if (ts.unit.found) { - str += ts.unit.out('text'); - } - ts = ts.replaceWith(str, true); - return parseValue(ts); -}; - -var Value = function Value(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - parseValue(this); -}; //Terms inheritence + n.nodes = n.nodes.slice(n.symCount, n.nodes.length); + }; + var indexFromRef = function indexFromRef(n, o, e) { + var t = encoding.fromAlphaCode(o); + return t < n.symCount ? n.syms[t] : e + t + 1 - n.symCount; + }, + toArray = function toArray(n) { + var o = [], + e = function e(t, r) { + var s = n.nodes[t]; + "!" === s[0] && (o.push(r), s = s.slice(1)); + var c = s.split(/([A-Z0-9,]+)/g); + + for (var _s = 0; _s < c.length; _s += 2) { + var u = c[_s], + i = c[_s + 1]; + if (!u) continue; + var l = r + u; + + if ("," === i || void 0 === i) { + o.push(l); + continue; + } -Value.prototype = Object.create(Terms.prototype); -var methods = { - data: function data() { - var num = parse(this.val); - return { - number: num, - nice: fmt.nice(num), - ordinal: fmt.ordinal(num), - niceOrdinal: fmt.niceOrdinal(num), - text: fmt.text(num), - textOrdinal: fmt.textOrdinal(num), - unit: this.unit.out('normal') + var f = indexFromRef(n, i, t); + e(f, l); + } }; - }, - number: function number() { - return parse(this.val); - }, - // /** five -> '5' */ - toNumber: function toNumber() { - var num = parse(this.val); - if (num || num === 0) { - var str = ''; - - if (this.val.has('#Ordinal')) { - str = fmt.ordinal(num); - } else { - str = String(num); //convert 'five percent' -> '5%' + return e(0, ""), o; + }, + unpack = function unpack(n) { + var o = { + nodes: n.split(";"), + syms: [], + symCount: 0 + }; + return n.match(":") && symbols(o), toArray(o); + }; - if (isPercent(this.val, this.unit)) { - str = str + '%'; - this.unit["delete"](); - } - } // let before = this.terms[0].whitespace.before; - // let after = this.terms[this.terms.length - 1].whitespace.after; + var unpack_1 = unpack, + unpack_1$1 = function unpack_1$1(n) { + var o = n.split("|").reduce(function (n, o) { + var e = o.split("¦"); + return n[e[0]] = e[1], n; + }, {}), + e = {}; + return Object.keys(o).forEach(function (n) { + var t = unpack_1(o[n]); + "true" === n && (n = !0); + + for (var _o2 = 0; _o2 < t.length; _o2++) { + var r = t[_o2]; + !0 === e.hasOwnProperty(r) ? !1 === Array.isArray(e[r]) ? e[r] = [e[r], n] : e[r].push(n) : e[r] = n; + } + }), e; + }; + var efrtUnpack_min = unpack_1$1; - if (this.unit.found) { - str = str + this.unit.out('text'); + //safely add it to the lexicon + var addWord = function addWord(word, tag, lex) { + if (lex[word] !== undefined) { + if (typeof lex[word] === 'string') { + lex[word] = [lex[word]]; } - this.replaceWith(str, true).tag('NumericValue'); //make sure unit gets the right tag.. - - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } // this.whitespace.before(before); - // this.whitespace.after(after); - + lex[word].push(tag); + } else { + lex[word] = tag; } + }; // blast-out more forms for some given words - return this; - }, - // /**5 -> 'five' */ - toText: function toText() { - var num = parse(this.val); - - if (num || num === 0) { - var str = ''; - - if (this.val.has('#Ordinal')) { - str = fmt.textOrdinal(num); - } else { - str = fmt.text(num); //add percent - if (isPercent(this.val, this.unit)) { - str = str + ' percent'; - } - } + var addMore = function addMore(word, tag, world) { + var lexicon = world.words; + var transform = world.transforms; // cache multi-words - if (this.unit.found) { - str = str + this.unit.out('text'); - } + var words = word.split(' '); - this.replaceWith(str, true).tag('TextValue'); //make sure unit gets the right tag.. + if (words.length > 1) { + //cache the beginning word + world.hasCompound[words[0]] = true; + } // inflect our nouns - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5th -> 5 */ - toCardinal: function toCardinal() { - var num = parse(this.val); + if (tag === 'Singular') { + var plural = transform.toPlural(word, world); + lexicon[plural] = lexicon[plural] || 'Plural'; // only if it's safe + } //conjugate our verbs - if (num || num === 0) { - var str = ''; - if (this.val.has('#TextValue')) { - str = fmt.text(num); - } else { - str = num; - } + if (tag === 'Infinitive') { + var conj = transform.conjugate(word, world); + var tags = Object.keys(conj); - if (this.unit.found) { - str = str + this.unit.out('text'); + for (var i = 0; i < tags.length; i++) { + var w = conj[tags[i]]; + lexicon[w] = lexicon[w] || tags[i]; // only if it's safe } + } //derive more adjective forms - this.replaceWith(str, true).tag('Cardinal'); //make sure unit gets the right tag.. - - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5 -> 5th */ - toOrdinal: function toOrdinal() { - var num = parse(this.val); + if (tag === 'Comparable') { + var _conj = transform.adjectives(word); - if (num || num === 0) { - var str = ''; + var _tags = Object.keys(_conj); - if (this.val.has('#TextValue')) { - str = fmt.textOrdinal(num); - } else { - str = fmt.ordinal(num); + for (var _i = 0; _i < _tags.length; _i++) { + var _w = _conj[_tags[_i]]; + lexicon[_w] = lexicon[_w] || _tags[_i]; // only if it's safe } + } //conjugate phrasal-verbs - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('Ordinal'); //make sure unit gets the right tag.. + if (tag === 'PhrasalVerb') { + //add original form + addWord(word, 'Infinitive', lexicon); //conjugate first word - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } + var _conj2 = transform.conjugate(words[0], world); - return this; - }, - // - // /**5900 -> 5,900 */ - toNice: function toNice() { - var num = parse(this.val); + var _tags2 = Object.keys(_conj2); - if (num || num === 0) { - var str = ''; + for (var _i2 = 0; _i2 < _tags2.length; _i2++) { + //add it to our cache + world.hasCompound[_conj2[_tags2[_i2]]] = true; //first + last words - if (this.val.has('#Ordinal')) { - str = fmt.niceOrdinal(num); - } else { - str = fmt.nice(num); - } + var _w2 = _conj2[_tags2[_i2]] + ' ' + words[1]; - if (this.unit.found) { - str = str + this.unit.out('text'); + addWord(_w2, _tags2[_i2], lexicon); + addWord(_w2, 'PhrasalVerb', lexicon); } + } // inflect our demonyms - 'germans' - this.replaceWith(str, true).tag('NumericValue'); //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - - return this; - }, + if (tag === 'Demonym') { + var _plural = transform.toPlural(word, world); - /** seven + 2 = nine */ - add: function add(n) { - if (!n) { - return this; + lexicon[_plural] = lexicon[_plural] || ['Demonym', 'Plural']; // only if it's safe } + }; // throw a bunch of words in our lexicon + // const doWord = function(words, tag, world) { + // let lexicon = world.words + // for (let i = 0; i < words.length; i++) { + // addWord(words[i], tag, lexicon) + // // do some fancier stuff + // addMore(words[i], tag, world) + // } + // } - var num = parse(this.val) || 0; - num += n; //add it - return setNumber(this, num); - }, + var addWords = { + addWord: addWord, + addMore: addMore + }; - /** seven - 2 = five */ - subtract: function subtract(n) { - if (!n) { - return this; - } + // add words from plurals and conjugations data + var addIrregulars = function addIrregulars(world) { + //add irregular plural nouns + var nouns = world.irregulars.nouns; + var words = Object.keys(nouns); - var num = parse(this.val) || 0; - num -= n; //subtract it + for (var i = 0; i < words.length; i++) { + var w = words[i]; + world.words[w] = 'Singular'; + world.words[nouns[w]] = 'Plural'; + } // add irregular verb conjugations - return setNumber(this, num); - }, - /**seven -> 'eight' */ - increment: function increment() { - return this.add(1); - }, + var verbs = world.irregulars.verbs; + var keys = Object.keys(verbs); - /**seven -> 'six' */ - decrement: function decrement() { - return this.subtract(1); - } -}; -Object.keys(methods).forEach(function (k) { - Value.prototype[k] = methods[k]; -}); -module.exports = Value; + var _loop = function _loop(_i) { + var inf = keys[_i]; //add only if it it's safe... -},{"../../paths":8,"./format":59,"./parse":66}],75:[function(_dereq_,module,exports){ -'use strict'; + world.words[inf] = world.words[inf] || 'Infinitive'; + var forms = world.transforms.conjugate(inf, world); + forms = Object.assign(forms, verbs[inf]); //add the others -var Text = _dereq_('../../text'); + Object.keys(forms).forEach(function (tag) { + world.words[forms[tag]] = world.words[forms[tag]] || tag; + }); + }; -var Verb = _dereq_('./verb'); //the () subset class + for (var _i = 0; _i < keys.length; _i++) { + _loop(_i); + } + }; + var addIrregulars_1 = addIrregulars; + + //words that can't be compressed, for whatever reason + var misc$1 = { + // numbers + '20th century fox': 'Organization', + // '3m': 'Organization', + '7 eleven': 'Organization', + '7-eleven': 'Organization', + g8: 'Organization', + 'motel 6': 'Organization', + vh1: 'Organization', + q1: 'Date', + q2: 'Date', + q3: 'Date', + q4: 'Date' + }; -var methods = { - conjugation: function conjugation(verbose) { - return this.list.map(function (ts) { - return ts.conjugation(verbose); - }); - }, - conjugate: function conjugate(num, verbose) { - //suppport only conjugating one verb in our result.. - if (num !== null && typeof num === 'number' && this.list[num]) { - return this.list[num].conjugate(verbose); - } //otherwise, return an array of conjugations + //nouns with irregular plural/singular forms + //used in noun.inflect, and also in the lexicon. + var plurals = { + addendum: 'addenda', + alga: 'algae', + alumna: 'alumnae', + alumnus: 'alumni', + analysis: 'analyses', + antenna: 'antennae', + appendix: 'appendices', + avocado: 'avocados', + axis: 'axes', + bacillus: 'bacilli', + barracks: 'barracks', + beau: 'beaux', + bus: 'buses', + cactus: 'cacti', + chateau: 'chateaux', + child: 'children', + circus: 'circuses', + clothes: 'clothes', + corpus: 'corpora', + criterion: 'criteria', + curriculum: 'curricula', + database: 'databases', + deer: 'deer', + diagnosis: 'diagnoses', + echo: 'echoes', + embargo: 'embargoes', + epoch: 'epochs', + foot: 'feet', + formula: 'formulae', + fungus: 'fungi', + genus: 'genera', + goose: 'geese', + halo: 'halos', + hippopotamus: 'hippopotami', + index: 'indices', + larva: 'larvae', + leaf: 'leaves', + libretto: 'libretti', + loaf: 'loaves', + man: 'men', + matrix: 'matrices', + memorandum: 'memoranda', + modulus: 'moduli', + mosquito: 'mosquitoes', + mouse: 'mice', + move: 'moves', + nebula: 'nebulae', + nucleus: 'nuclei', + octopus: 'octopi', + opus: 'opera', + ovum: 'ova', + ox: 'oxen', + parenthesis: 'parentheses', + person: 'people', + phenomenon: 'phenomena', + prognosis: 'prognoses', + quiz: 'quizzes', + radius: 'radii', + referendum: 'referenda', + rodeo: 'rodeos', + sex: 'sexes', + shoe: 'shoes', + sombrero: 'sombreros', + stimulus: 'stimuli', + stomach: 'stomachs', + syllabus: 'syllabi', + synopsis: 'synopses', + tableau: 'tableaux', + thesis: 'theses', + thief: 'thieves', + tooth: 'teeth', + tornado: 'tornados', + tuxedo: 'tuxedos', + vertebra: 'vertebrae' // virus: 'viri', + // zero: 'zeros', + }; - return this.list.map(function (ts) { - return ts.conjugate(verbose); - }); - }, - - /** plural/singular **/ - isPlural: function isPlural() { - this.list = this.list.filter(function (ts) { - return ts.isPlural(); - }); - return this; - }, - isSingular: function isSingular() { - this.list = this.list.filter(function (ts) { - return !ts.isPlural(); - }); - return this; - }, - - /** negation **/ - isNegative: function isNegative() { - this.list = this.list.filter(function (ts) { - return ts.isNegative(); - }); - return this; - }, - isPositive: function isPositive() { - this.list = this.list.filter(function (ts) { - return !ts.isNegative(); - }); - return this; - }, - toNegative: function toNegative() { - this.list = this.list.map(function (ts) { - return ts.toNegative(); - }); - return this; - }, - toPositive: function toPositive() { - this.list.forEach(function (ts) { - ts.toPositive(); - }); - return this; - }, - - /** tense **/ - toPastTense: function toPastTense() { - this.list.forEach(function (ts) { - ts.toPastTense(); - }); - return this; - }, - toPresentTense: function toPresentTense() { - this.list.forEach(function (ts) { - ts.toPresentTense(); - }); - return this; - }, - toFutureTense: function toFutureTense() { - this.list.forEach(function (ts) { - ts.toFutureTense(); - }); - return this; - }, - toInfinitive: function toInfinitive() { - this.list.forEach(function (ts) { - ts.toInfinitive(); - }); - return this; - }, - toGerund: function toGerund() { - this.list.forEach(function (ts) { - ts.toGerund(); - }); - return this; - }, - asAdjective: function asAdjective() { - return this.list.map(function (ts) { - return ts.asAdjective(); - }); - } -}; //aliases - -methods.toContinuous = methods.toGerund; - -var find = function find(r, n) { - r = r.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); - r = r.splitAfter('#Comma'); - r.list.forEach(function (ts) { - ts.terms.forEach(function (t) { - if (t.whitespace.before.match('/')) { - r.splitOn(t.normal); - } - }); - }); - r = r["if"]('#Verb'); //this should be (much) smarter - - if (typeof n === 'number') { - r = r.get(n); - } - - r.list = r.list.map(function (ts) { - return new Verb(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return new Text(r.list, this.world, this.parent); -}; - -module.exports = Text.makeSubset(methods, find); - -},{"../../text":192,"./verb":94}],76:[function(_dereq_,module,exports){ -'use strict'; - -var predict = _dereq_('./methods/predict'); - -var isPlural = _dereq_('./methods/isPlural'); //'walking' - aka progressive - - -var isContinuous = function isContinuous(ts) { - return ts.match('#Gerund').found; -}; //will not walk - - -var isNegative = function isNegative(ts) { - var negs = ts.match('#Negative').list; - - if (negs.length === 2) { - return false; - } - - if (negs.length === 1) { - return true; - } - - return false; -}; //been walked by.. - - -var isPassive = function isPassive(ts) { - if (ts.match('is being #PastTense').found) { - return true; - } - - if (ts.match('(had|has) been #PastTense').found) { - return true; - } - - if (ts.match('will have been #PastTense').found) { - return true; - } - - return false; -}; //had walked - - -var isPerfect = function isPerfect(ts) { - if (ts.match('^(had|have) #PastTense')) { - return true; - } - - return false; -}; //should walk, could walk - - -var getModal = function getModal(ts) { - var modal = ts.match('#Modal'); - - if (!modal.found) { - return null; - } - - return modal.out('normal'); -}; //past/present/future - - -var getTense = function getTense(ts) { - //look at the preceding words - if (ts.auxiliary.found) { - //'will' - if (ts.match('will have #PastTense').found) { - return 'Past'; - } - - if (ts.auxiliary.match('will').found) { - return 'Future'; - } //'was' - - - if (ts.auxiliary.match('was').found) { - return 'Past'; - } - } //look at the main verb tense - - - if (ts.verb) { - var tenses = { - PastTense: 'Past', - FutureTense: 'Future', - FuturePerfect: 'Future' - }; - var tense = predict(ts.verb); //yikes - - return tenses[tense] || 'Present'; - } - - return 'Present'; -}; // const isImperative = function(ts) {}; -// const isConditional = function(ts) {}; -// detect signals in Auxiliary verbs -// 'will' -> future, 'have'->perfect, modals, negatives, adverbs - - -var interpret = function interpret(ts) { - var isNeg = isNegative(ts); // let aux = ts.Auxiliary.clone(); - // aux = aux.not('(#Negative|#Adverb)'); - - var obj = { - negative: isNeg, - continuous: isContinuous(ts), - passive: isPassive(ts), - perfect: isPerfect(ts), - plural: isPlural(ts), - modal: getModal(ts), - tense: getTense(ts) - }; - return obj; -}; - -module.exports = interpret; - -},{"./methods/isPlural":86,"./methods/predict":87}],77:[function(_dereq_,module,exports){ -'use strict'; - -var checkIrregulars = _dereq_('./irregulars'); - -var suffixPass = _dereq_('./suffixes'); - -var toActor = _dereq_('./toActor'); - -var generic = _dereq_('./generic'); - -var predict = _dereq_('../predict'); - -var toInfinitive = _dereq_('../toInfinitive'); - -var toBe = _dereq_('./toBe'); //turn a verb into all it's forms - - -var conjugate = function conjugate(t, world) { - //handle is/was/will-be specially - if (t.normal === 'is' || t.normal === 'was' || t.normal === 'will') { - return toBe(); - } //dont conjugate didn't - - - if (t.tags.Contraction) { - t.text = t.silent_term; - } - - var all = { - PastTense: null, - PresentTense: null, - Infinitive: null, - Gerund: null, - Actor: null - }; //first, get its current form - - var form = predict(t); - - if (form) { - all[form] = t.normal; - } - - if (form !== 'Infinitive') { - all['Infinitive'] = toInfinitive(t, world) || ''; - } //check irregular forms - - - var irregObj = checkIrregulars(all['Infinitive'], world) || {}; - Object.keys(irregObj).forEach(function (k) { - if (irregObj[k] && !all[k]) { - all[k] = irregObj[k]; - } - }); //ok, send this infinitive to all conjugators - - var inf = all['Infinitive'] || t.normal; //check suffix rules - - var suffObj = suffixPass(inf); - Object.keys(suffObj).forEach(function (k) { - if (suffObj[k] && !all[k]) { - all[k] = suffObj[k]; - } - }); //ad-hoc each missing form - //to Actor - - if (!all.Actor) { - all.Actor = toActor(inf); - } //use fallback, generic transformations - - - Object.keys(all).forEach(function (k) { - if (!all[k] && generic[k]) { - all[k] = generic[k](all); - } - }); - return all; -}; - -module.exports = conjugate; - -},{"../predict":87,"../toInfinitive":90,"./generic":80,"./irregulars":82,"./suffixes":83,"./toActor":84,"./toBe":85}],78:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = [{ - reg: /(eave)$/i, - repl: { - pr: '$1s', - pa: '$1d', - gr: 'eaving', - ar: '$1r' - } -}, { - reg: /(ink)$/i, - repl: { - pr: '$1s', - pa: 'unk', - gr: '$1ing', - ar: '$1er' - } -}, { - reg: /([aeiou]k)in$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing', - ar: '$1er' - } -}, { - reg: /(end)$/i, - repl: { - pr: '$1s', - pa: 'ent', - gr: '$1ing', - ar: '$1er' - } -}, { - reg: /(ide)$/i, - repl: { - pr: '$1s', - pa: 'ode', - gr: 'iding', - ar: 'ider' - } -}, { - reg: /(ake)$/i, - repl: { - pr: '$1s', - pa: 'ook', - gr: 'aking', - ar: '$1r' - } -}, { - reg: /(eed)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing', - ar: '$1er' - } -}, { - reg: /(e)(ep)$/i, - repl: { - pr: '$1$2s', - pa: '$1pt', - gr: '$1$2ing', - ar: '$1$2er' - } -}, { - reg: /(a[tg]|i[zn]|ur|nc|gl|is)e$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing', - prt: '$1en' - } -}, { - reg: /([i|f|rr])y$/i, - repl: { - pr: '$1ies', - pa: '$1ied', - gr: '$1ying' - } -}, { - reg: /([td]er)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } -}, { - reg: /([bd]l)e$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } -}, { - reg: /(ish|tch|ess)$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } -}, { - reg: /(ion|end|e[nc]t)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } -}, { - reg: /(om)e$/i, - repl: { - pr: '$1es', - pa: 'ame', - gr: '$1ing' - } -}, { - reg: /(.eat)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } -}, { - reg: /([aeiu])([pt])$/i, - repl: { - pr: '$1$2s', - pa: '$1$2', - gr: '$1$2$2ing' - } -}, { - reg: /(er)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } -}, { - reg: /(en)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } -}, { - reg: /(ed)$/i, - repl: { - pr: '$1s', - pa: '$1ded', - ar: '$1der', - gr: '$1ding' - } -}, { - reg: /(..)(ow)$/i, - repl: { - pr: '$1$2s', - pa: '$1ew', - gr: '$1$2ing', - prt: '$1$2n' - } -}, { - reg: /(..)([cs]h)$/i, - repl: { - pr: '$1$2es', - pa: '$1$2ed', - gr: '$1$2ing' - } -}, { - reg: /([^aeiou][ou])(g|d)$/i, - repl: { - pr: '$1$2s', - pa: '$1$2$2ed', - gr: '$1$2$2ing' - } -}, { - reg: /([^aeiou][aeiou])(b|t|p|m)$/i, - repl: { - pr: '$1$2s', - pa: '$1$2$2ed', - gr: '$1$2$2ing' - } -}, { - reg: /([aeiou]zz)$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } -}]; - -},{}],79:[function(_dereq_,module,exports){ -'use strict'; - -var checkIrregulars = _dereq_('./irregulars'); - -var suffixPass = _dereq_('./suffixes'); - -var generic = _dereq_('./generic'); //this method is the same as regular conjugate, but optimised for use in the lexicon during warm-up. -//it's way faster because it knows input is already infinitive - - -var want = ['Gerund', 'PastTense', 'PresentTense']; - -var fasterConjugate = function fasterConjugate(inf, world) { - var all = { - Infinitive: inf - }; //check irregulars list - - if (world && world.conjugations) { - var irregObj = checkIrregulars(all['Infinitive'], world); - - if (irregObj !== null) { - Object.keys(irregObj).forEach(function (k) { - if (irregObj[k] && !all[k]) { - all[k] = irregObj[k]; - } - }); - } - } //check suffix rules - - - var suffObj = suffixPass(inf); - Object.keys(suffObj).forEach(function (k) { - if (suffObj[k] && !all[k]) { - all[k] = suffObj[k]; - } - }); - - for (var i = 0; i < want.length; i++) { - if (all[want[i]] === undefined) { - all[want[i]] = generic[want[i]](all); - } - } - - return all; -}; - -module.exports = fasterConjugate; // console.log(fasterConjugate('repeat')); - -},{"./generic":80,"./irregulars":82,"./suffixes":83}],80:[function(_dereq_,module,exports){ -'use strict'; //non-specifc, 'hail-mary' transforms from infinitive, into other forms - -var hasY = /[bcdfghjklmnpqrstvwxz]y$/; -var generic = { - Gerund: function Gerund(o) { - var inf = o.Infinitive; - - if (inf.charAt(inf.length - 1) === 'e') { - return inf.replace(/e$/, 'ing'); - } - - return inf + 'ing'; - }, - PresentTense: function PresentTense(o) { - var inf = o.Infinitive; - - if (inf.charAt(inf.length - 1) === 's') { - return inf + 'es'; - } - - if (hasY.test(inf) === true) { - return inf.slice(0, -1) + 'ies'; - } - - return inf + 's'; - }, - PastTense: function PastTense(o) { - var inf = o.Infinitive; - - if (inf.charAt(inf.length - 1) === 'e') { - return inf + 'd'; - } - - if (inf.substr(-2) === 'ed') { - return inf; - } - - if (hasY.test(inf) === true) { - return inf.slice(0, -1) + 'ied'; - } - - return inf + 'ed'; - } // FutureTense: (o) => { - // return 'will ' + o.Infinitive; - // }, - // - // PerfectTense: (o) => { - // return 'have ' + (o.Participle || o.PastTense); - // }, - // - // Pluperfect: (o) => { - // if (o.PastTense) { - // return 'had ' + o.PastTense; - // } - // return null; - // }, - // FuturePerfect: (o) => { - // if (o.PastTense) { - // return 'will have ' + o.PastTense; - // } - // return null; - // } - -}; -module.exports = generic; - -},{}],81:[function(_dereq_,module,exports){ -'use strict'; - -var conjugate = _dereq_('./conjugate'); - -var toBe = _dereq_('./toBe'); - -var addAdverbs = function addAdverbs(obj, vb) { - if (vb.adverbs.found) { - //does the adverb go at the start or end? - var isFirst = vb.first().match('#Adverb').found; - Object.keys(obj).forEach(function (k) { - if (isFirst) { - obj[k] = vb.adverbs.out() + ' ' + obj[k]; - } else { - obj[k] = obj[k] + vb.adverbs.out(); - } - }); - } - - return obj; -}; //conjugation using auxillaries+adverbs and stuff - - -var multiWordConjugate = function multiWordConjugate(vb, verbose) { - var isNegative = vb.negative.found; - var isPlural = vb.isPlural(); //handle 'to be' verb seperately - - if (vb.verb.tags.Copula || vb.verb.normal === 'be' && vb.auxiliary.match('will').found) { - var isI = false; //account for 'i is' -> 'i am' irregular - - if (vb.parent && vb.parent.has('i #Adverb? #Copula')) { - isI = true; - } - - var copulas = toBe(isPlural, isNegative, isI); - return addAdverbs(copulas, vb); - } - - var obj = conjugate(vb.verb, vb.world, verbose); //apply particles - - if (vb.particle.found) { - Object.keys(obj).forEach(function (k) { - obj[k] = obj[k] + vb.particle.out(); - }); - } //apply negative - - - if (isNegative) { - obj.PastTense = 'did not ' + obj.Infinitive; - obj.PresentTense = 'does not ' + obj.Infinitive; - obj.Gerund = 'not ' + obj.Gerund; - } //future Tense is pretty straightforward - - - if (!obj.FutureTense) { - if (isNegative) { - obj.FutureTense = 'will not ' + obj.Infinitive; - } else { - obj.FutureTense = 'will ' + obj.Infinitive; - } - } //apply adverbs - - - obj = addAdverbs(obj, vb); - return obj; -}; - -module.exports = multiWordConjugate; - -},{"./conjugate":77,"./toBe":85}],82:[function(_dereq_,module,exports){ -'use strict'; // let irregulars = require('../../../../lexicon/uncompressed/irregularVerbs').irregulars; //weeee! - -var fns = _dereq_('../../../../fns'); //weeee! - - -var forms = ['Participle', 'Gerund', 'PastTense', 'PresentTense', 'FuturePerfect', 'PerfectTense', 'Actor']; - -var checkIrregulars = function checkIrregulars(str, world) { - var irregulars = world.conjugations; - var infArr = Object.keys(irregulars); //check irregulars in world - - if (world && world.conjugations && world.conjugations.hasOwnProperty(str) === true) { - return world.conjugations[str]; - } //fast infinitive lookup - - - if (irregulars.hasOwnProperty(str) === true) { - var obj = fns.copy(irregulars[str]); - obj.Infinitive = str; - return obj; - } //longer check of known-verb forms - - - for (var i = 0; i < infArr.length; i++) { - for (var o = 0; o < forms.length; o++) { - var irObj = irregulars[infArr[i]]; - - if (irObj[forms[o]] === str) { - var _obj = fns.copy(irObj); - - _obj.Infinitive = infArr[i]; - return _obj; - } - } - } - - return {}; -}; - -module.exports = checkIrregulars; // console.log(checkIrregulars('bit')); - -},{"../../../../fns":3}],83:[function(_dereq_,module,exports){ -'use strict'; - -var rules = _dereq_('./data/rules'); - -var mapping = { - pr: 'PresentTense', - pa: 'PastTense', - gr: 'Gerund', - prt: 'Participle', - ar: 'Actor' -}; -var keys = Object.keys(mapping); //check suffix rules - -var suffixPass = function suffixPass(inf) { - var found = {}; - - for (var i = 0; i < rules.length; i++) { - if (rules[i].reg.test(inf) === true) { - var obj = rules[i].repl; - - for (var o = 0; o < keys.length; o++) { - if (obj.hasOwnProperty(keys[o]) === true) { - var key = mapping[keys[o]]; // console.log(rules[i]); - - found[key] = inf.replace(rules[i].reg, obj[keys[o]]); - } - } - - return found; - } - } - - return found; -}; - -module.exports = suffixPass; - -},{"./data/rules":78}],84:[function(_dereq_,module,exports){ -'use strict'; //turn 'walk' into 'walker' - -var irregulars = { - 'tie': 'tier', - 'dream': 'dreamer', - 'sail': 'sailer', - 'run': 'runner', - 'rub': 'rubber', - 'begin': 'beginner', - 'win': 'winner', - 'claim': 'claimant', - 'deal': 'dealer', - 'spin': 'spinner' -}; -var dont = { - 'aid': 1, - 'fail': 1, - 'appear': 1, - 'happen': 1, - 'seem': 1, - 'try': 1, - 'say': 1, - 'marry': 1, - 'be': 1, - 'forbid': 1, - 'understand': 1, - 'bet': 1 -}; -var rules = [{ - 'reg': /e$/i, - 'repl': 'er' -}, { - 'reg': /([aeiou])([mlgp])$/i, - 'repl': '$1$2$2er' -}, { - 'reg': /([rlf])y$/i, - 'repl': '$1ier' -}, { - 'reg': /^(.?.[aeiou])t$/i, - 'repl': '$1tter' -}]; - -var toActor = function toActor(inf) { - //check blacklist - if (dont[inf]) { - return null; - } //check irregulars - - - if (irregulars.hasOwnProperty(inf)) { - return irregulars[inf]; - } //try rules - - - for (var i = 0; i < rules.length; i++) { - if (rules[i].reg.test(inf) === true) { - return inf.replace(rules[i].reg, rules[i].repl); - } - } //yup, - - - return inf + 'er'; -}; - -module.exports = toActor; - -},{}],85:[function(_dereq_,module,exports){ -'use strict'; //too many special cases for is/was/will be - -var toBe = function toBe(isPlural, isNegative, isI) { - var obj = { - PastTense: 'was', - PresentTense: 'is', - FutureTense: 'will be', - Infinitive: 'is', - Gerund: 'being', - Actor: '', - PerfectTense: 'been', - Pluperfect: 'been' - }; //"i is" -> "i am" - - if (isI === true) { - obj.PresentTense = 'am'; - obj.Infinitive = 'am'; - } - - if (isPlural) { - obj.PastTense = 'were'; - obj.PresentTense = 'are'; - obj.Infinitive = 'are'; - } - - if (isNegative) { - obj.PastTense += ' not'; - obj.PresentTense += ' not'; - obj.FutureTense = 'will not be'; - obj.Infinitive += ' not'; - obj.PerfectTense = 'not ' + obj.PerfectTense; - obj.Pluperfect = 'not ' + obj.Pluperfect; - obj.Gerund = 'not ' + obj.Gerund; - } - - return obj; -}; - -module.exports = toBe; - -},{}],86:[function(_dereq_,module,exports){ -'use strict'; //sometimes you can tell if a verb is plural/singular, just by the verb -// i am / we were -//othertimes you need its noun 'we walk' vs 'i walk' - -var isPlural = function isPlural(vb) { - if (vb.match('(are|were|does)').found) { - return true; - } - - if (vb.match('(is|am|do|was)').found) { - return false; - } //consider its prior noun - - - var noun = vb.getNoun(); - - if (noun && noun.found) { - if (noun.match('#Plural').found) { - return true; - } - - if (noun.match('#Singular').found) { - return false; - } - } - - return null; -}; - -module.exports = isPlural; - -},{}],87:[function(_dereq_,module,exports){ -'use strict'; - -var suffix_rules = _dereq_('./suffix_rules'); - -var goodTypes = { - Infinitive: true, - Gerund: true, - PastTense: true, - PresentTense: true, - FutureTense: true, - PerfectTense: true, - Pluperfect: true, - FuturePerfect: true, - Participle: true -}; - -var predictForm = function predictForm(term) { - //do we already know the form? - var keys = Object.keys(goodTypes); - - for (var i = 0; i < keys.length; i++) { - if (term.tags[keys[i]]) { - return keys[i]; - } - } //consult our handy suffix rules - - - var arr = Object.keys(suffix_rules); - - for (var _i = 0; _i < arr.length; _i++) { - var substr = term.normal.substr(-arr[_i].length); - - if (substr === arr[_i] && term.normal.length > arr[_i].length) { - return suffix_rules[arr[_i]]; - } - } - - return null; -}; - -module.exports = predictForm; - -},{"./suffix_rules":88}],88:[function(_dereq_,module,exports){ -'use strict'; //suffix signals for verb tense, generated from test data - -var compact = { - 'Gerund': ['ing'], - 'Actor': ['erer'], - 'Infinitive': ['ate', 'ize', 'tion', 'rify', 'then', 'ress', 'ify', 'age', 'nce', 'ect', 'ise', 'ine', 'ish', 'ace', 'ash', 'ure', 'tch', 'end', 'ack', 'and', 'ute', 'ade', 'ock', 'ite', 'ase', 'ose', 'use', 'ive', 'int', 'nge', 'lay', 'est', 'ain', 'ant', 'ent', 'eed', 'er', 'le', 'own', 'unk', 'ung', 'en'], - 'PastTense': ['ed', 'lt', 'nt', 'pt', 'ew', 'ld'], - 'PresentTense': ['rks', 'cks', 'nks', 'ngs', 'mps', 'tes', 'zes', 'ers', 'les', 'acks', 'ends', 'ands', 'ocks', 'lays', 'eads', 'lls', 'els', 'ils', 'ows', 'nds', 'ays', 'ams', 'ars', 'ops', 'ffs', 'als', 'urs', 'lds', 'ews', 'ips', 'es', 'ts', 'ns', 's'] -}; -var suffix_rules = {}; -var keys = Object.keys(compact); -var l = keys.length; - -for (var i = 0; i < l; i++) { - var l2 = compact[keys[i]].length; - - for (var o = 0; o < l2; o++) { - suffix_rules[compact[keys[i]][o]] = keys[i]; - } -} - -module.exports = suffix_rules; - -},{}],89:[function(_dereq_,module,exports){ -'use strict'; //turn a infinitiveVerb, like "walk" into an adjective like "walkable" - -var rules = [[/y$/, 'i'], //relay - reliable -[/([aeiou][n])$/, '$1n']]; //convert - 'convertible' -//http://grammarist.com/usage/able-ible/ -//http://blog.oxforddictionaries.com/2012/10/ibles-and-ables/ - -var ible_suffixes = { - collect: true, - exhaust: true, - convert: true, - digest: true, - discern: true, - dismiss: true, - reverse: true, - access: true, - collapse: true, - express: true -}; -var irregulars = { - eat: 'edible', - hear: 'audible', - see: 'visible', - defend: 'defensible', - write: 'legible', - move: 'movable', - divide: 'divisible', - perceive: 'perceptible' -}; //takes an infitive verb, and returns an adjective form - -var toAdjective = function toAdjective(str) { - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - - for (var i = 0; i < rules.length; i++) { - if (rules[i][0].test(str) === true) { - str = str.replace(rules[i][0], rules[i][1]); - } - } //ible/able - - - var adj = str + 'able'; - - if (ible_suffixes[str]) { - adj = str + 'ible'; - } - - return adj; -}; - -module.exports = toAdjective; - -},{}],90:[function(_dereq_,module,exports){ -'use strict'; //turn any verb into its infinitive form - -var rules = _dereq_('./rules'); - -var predict = _dereq_('../predict'); - -var toInfinitive = function toInfinitive(t, world) { - var irregulars = world.cache.toInfinitive || {}; //verb_mapping(world.conjugations); //TODO: do this at world cache - - if (t.tags.Infinitive) { - return t.normal; - } //check the irregular verb conjugations - - - if (irregulars.hasOwnProperty(t.normal) === true) { - return irregulars[t.normal]; - } //check the suffix rules - - - var form = predict(t); - - if (rules[form]) { - for (var i = 0; i < rules[form].length; i++) { - var rule = rules[form][i]; - - if (t.normal.match(rule.reg)) { - return t.normal.replace(rule.reg, rule.to); - } - } - } - - return t.normal; -}; - -module.exports = toInfinitive; - -},{"../predict":87,"./rules":91}],91:[function(_dereq_,module,exports){ -'use strict'; //rules for turning a verb into infinitive form - -var rules = { - Participle: [{ - reg: /own$/i, - to: 'ow' - }, { - reg: /(.)un([g|k])$/i, - to: '$1in$2' - }], - Actor: [{ - reg: /(er)er$/i, - to: '$1' - }], - PresentTense: [{ - reg: /(..)(ies)$/i, - to: '$1y' - }, { - reg: /(tch|sh)es$/i, - to: '$1' - }, { - reg: /(ss|zz)es$/i, - to: '$1' - }, { - reg: /([tzlshicgrvdnkmu])es$/i, - to: '$1e' - }, { - reg: /(n[dtk]|c[kt]|[eo]n|i[nl]|er|a[ytrl])s$/i, - to: '$1' - }, { - reg: /(ow)s$/i, - to: '$1' - }, { - reg: /(op)s$/i, - to: '$1' - }, { - reg: /([eirs])ts$/i, - to: '$1t' - }, { - reg: /(ll)s$/i, - to: '$1' - }, { - reg: /(el)s$/i, - to: '$1' - }, { - reg: /(ip)es$/i, - to: '$1e' - }, { - reg: /ss$/i, - to: 'ss' - }, { - reg: /s$/i, - to: '' - }], - Gerund: [{ - reg: /pping$/i, - to: 'p' - }, { - reg: /lling$/i, - to: 'll' - }, { - reg: /tting$/i, - to: 't' - }, { - reg: /dding$/i, - to: 'd' - }, { - reg: /ssing$/i, - to: 'ss' - }, { - reg: /(..)gging$/i, - to: '$1g' - }, { - reg: /([^aeiou])ying$/i, - to: '$1y' - }, { - reg: /([^ae]i.)ing$/i, - to: '$1e' - }, { - reg: /(ea.)ing$/i, - to: '$1' - }, { - reg: /(u[rtcb]|[bdtpkg]l|n[cg]|a[gdkvtc]|[ua]s|[dr]g|yz|o[rlsp]|cre)ing$/i, - to: '$1e' - }, { - reg: /(ch|sh)ing$/i, - to: '$1' - }, { - reg: /(..)ing$/i, - to: '$1' - }], - PastTense: [{ - reg: /(ued)$/i, - to: 'ue' - }, { - reg: /a([^aeiouy])ed$/i, - to: 'a$1e' - }, { - reg: /([aeiou]zz)ed$/i, - to: '$1' - }, { - reg: /(e|i)lled$/i, - to: '$1ll' - }, { - reg: /(.)(sh|ch)ed$/i, - to: '$1$2' - }, { - reg: /(tl|gl)ed$/i, - to: '$1e' - }, { - reg: /(um?pt?)ed$/i, - to: '$1' - }, { - reg: /(ss)ed$/i, - to: '$1' - }, { - reg: /pped$/i, - to: 'p' - }, { - reg: /tted$/i, - to: 't' - }, { - reg: /(..)gged$/i, - to: '$1g' - }, { - reg: /(..)lked$/i, - to: '$1lk' - }, { - reg: /([^aeiouy][aeiou])ked$/i, - to: '$1ke' - }, { - reg: /(.[aeiou])led$/i, - to: '$1l' - }, { - reg: /(..)(h|ion|n[dt]|ai.|[cs]t|pp|all|ss|tt|int|ail|ld|en|oo.|er|k|pp|w|ou.|rt|ght|rm)ed$/i, - to: '$1$2' - }, { - reg: /(.ut)ed$/i, - to: '$1e' - }, { - reg: /(.pt)ed$/i, - to: '$1' - }, { - reg: /(us)ed$/i, - to: '$1e' - }, { - reg: /(..[^aeiouy])ed$/i, - to: '$1e' - }, { - reg: /(..)ied$/i, - to: '$1y' - }, { - reg: /(.o)ed$/i, - to: '$1o' - }, { - reg: /(..i)ed$/i, - to: '$1' - }, { - reg: /(.a[^aeiou])ed$/i, - to: '$1' - }, { - reg: /([rl])ew$/i, - to: '$1ow' - }, { - reg: /([pl])t$/i, - to: '$1t' - }] -}; -module.exports = rules; - -},{}],92:[function(_dereq_,module,exports){ -"use strict"; - -//these are contractions with a implicit verb. -var expand = function expand(vb) { - vb.match('#Contraction+').list.forEach(function (ts) { - if (ts.has('#Verb')) { - ts.terms.forEach(function (t) { - if (t.silent_term) { - //this term also needs a space now too - if (!t.text) { - t.whitespace.before = ' '; - } - - t._text = t.silent_term; //handle (some) capitalization - - if (t.tags.TitleCase) { - t.toTitleCase(); - } - - t.normalize(); - t.silent_term = null; - t.unTag('Contraction', 'expanded'); - } - }); - } - }); - return vb; -}; - -module.exports = expand; - -},{}],93:[function(_dereq_,module,exports){ -'use strict'; //turns a verb negative - may not have enough information to do it properly -// (eg 'did not eat' vs 'does not eat') - needs the noun - -var toInfinitive = _dereq_('./methods/toInfinitive'); //this methods operate on parentTerms, so return subset - - -var getVerb = function getVerb(ts) { - ts = ts.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); - ts = ts.splitAfter('#Comma'); - return ts.list[0]; -}; - -var toNegative = function toNegative(ts) { - //would not walk - var modal = ts.match('#Auxiliary').first(); //.notIf('(is|are|was|will|has|had)').first(); //.first(); - - if (modal.found) { - var index = modal.list[0].index(); - var vb = ts.parentTerms.insertAt(index + 1, 'not', 'Verb'); - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } //words that pair easily with a 'not' - 'is not' - - - var copula = ts.match('(#Copula|will|has|had|do)').first(); - - if (copula.found) { - var _index = copula.list[0].index(); - - var _vb = ts.parentTerms.insertAt(_index + 1, 'not', 'Verb'); - - _vb.match('not').tag('Negative', 'tag-not'); - - return getVerb(_vb); - } - - var isPlural = ts.isPlural(); //walked -> did not walk - - var past = ts.match('#PastTense').last(); - - if (past.found) { - // past.debug(); - var first = past.list[0]; - - var _index2 = first.index(); - - first.terms[0].text = toInfinitive(first.terms[0], ts.world); - - var _vb2 = ts.parentTerms.insertAt(_index2, 'did not', 'Verb'); //add 'do not'? - - - _vb2.match('not').tag('Negative', 'tag-not'); - - return getVerb(_vb2); - } //walks -> does not walk - - - var pres = ts.match('#PresentTense').first(); - - if (pres.found) { - var _first = pres.list[0]; - - var _index3 = _first.index(); - - _first.terms[0].text = toInfinitive(_first.terms[0], ts.world); //some things use 'do not', everything else is 'does not' - - var noun = ts.getNoun(); - var _vb3 = null; - - if (noun.match('(i|we|they|you)').found) { - _vb3 = ts.parentTerms.insertAt(_index3, 'do not', 'Verb'); - } else { - _vb3 = ts.parentTerms.insertAt(_index3, 'does not', 'Verb'); - } - - _vb3.match('not').tag('Negative', 'tag-not'); - - return getVerb(_vb3); - } //not walking - - - var gerund = ts.match('#Gerund').last(); - - if (gerund.found) { - var _index4 = gerund.list[0].index(); - - var _vb4 = ts.parentTerms.insertAt(_index4, 'not', 'Verb'); - - _vb4.match('not').tag('Negative', 'tag-not'); - - return getVerb(_vb4); - } //walk -> do not walk - - - var verb = ts.match('#Verb').last(); - - if (verb.found) { - var _first2 = verb.list[0]; - - var _index5 = _first2.index(); - - _first2.terms[0].text = toInfinitive(_first2.terms[0], ts.world); - var _vb5 = ts; - - if (isPlural) { - _vb5 = ts.parentTerms.insertAt(_index5 - 1, 'do not', 'Verb'); - } else { - _vb5 = ts.parentTerms.insertAt(_index5 - 1, 'does not', 'Verb'); - } - - _vb5.match('not').tag('Negative', 'tag-not'); - - return getVerb(_vb5); - } - - return ts; -}; - -module.exports = toNegative; - -},{"./methods/toInfinitive":90}],94:[function(_dereq_,module,exports){ -'use strict'; - -var Terms = _dereq_('../../paths').Terms; - -var _conjugate = _dereq_('./methods/conjugate'); - -var toAdjective = _dereq_('./methods/toAdjective'); - -var interpret = _dereq_('./interpret'); - -var _toNegative = _dereq_('./toNegative'); - -var _isPlural = _dereq_('./methods/isPlural'); - -var expand = _dereq_('./methods/verbContraction'); - -var _parse = function parse(r) { - var original = r; - r.negative = r.match('#Negative'); - r.adverbs = r.match('#Adverb'); - var aux = r.clone().not('(#Adverb|#Negative)'); - r.verb = aux.match('#Verb').not('#Particle').last(); - r.particle = aux.match('#Particle').last(); - - if (r.verb.found) { - var str = r.verb.out('normal'); - r.auxiliary = original.not(str).not('(#Adverb|#Negative)'); - r.verb = r.verb.list[0].terms[0]; // r.auxiliary = aux.match('#Auxiliary+'); - } else { - r.verb = original.terms[0]; - r.auxiliary = aux.not('.'); - } - - return r; -}; - -var methods = { - parse: function parse() { - return _parse(this); - }, - data: function data(verbose) { - return { - text: this.out('text'), - normal: this.out('normal'), - parts: { - negative: this.negative.out('normal'), - auxiliary: this.auxiliary.out('normal'), - verb: this.verb.out('normal'), - particle: this.particle.out('normal'), - adverbs: this.adverbs.out('normal') - }, - interpret: interpret(this, verbose), - conjugations: this.conjugate() - }; - }, - getNoun: function getNoun() { - if (!this.refTerms) { - return null; - } - - var str = '#Adjective? #Noun+ ' + this.out('normal'); - return this.refTerms.match(str).match('#Noun+'); - }, - //which conjugation is this right now? - conjugation: function conjugation() { - return interpret(this, false).tense; - }, - //blast-out all forms - conjugate: function conjugate(verbose) { - return _conjugate(this, verbose); - }, - isPlural: function isPlural() { - return _isPlural(this); - }, - - /** negation **/ - isNegative: function isNegative() { - return this.match('#Negative').list.length === 1; - }, - isPerfect: function isPerfect() { - return this.auxiliary.match('(have|had)').found; - }, - toNegative: function toNegative() { - if (this.isNegative()) { - return this; - } - - return _toNegative(this); - }, - toPositive: function toPositive() { - return this.match('#Negative')["delete"](); - }, - - /** conjugation **/ - toPastTense: function toPastTense() { - if (this.has('#Contraction')) { - this.list = expand(this.parentTerms).list; - } - - var obj = this.conjugate(); - var end = obj.PastTense; - var r = this.replaceWith(end, false); - r.verb.tag('#PastTense'); - return r; - }, - toPresentTense: function toPresentTense() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - - var obj = this.conjugate(); - var r = this.replaceWith(obj.PresentTense, false); - r.verb.tag('#PresentTense'); - return r; - }, - toFutureTense: function toFutureTense() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - - var obj = this.conjugate(); - var r = this.replaceWith(obj.FutureTense, false); - r.verb.tag('#FutureTense'); - return r; - }, - toInfinitive: function toInfinitive() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - - var obj = this.conjugate(); - var r = this.replaceWith(obj.Infinitive, false); - r.verb.tag('#Infinitive'); - return r; - }, - toGerund: function toGerund() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - - var obj = this.conjugate(); - var aux = 'is'; //support 'i am', 'we are', 'he is' - - var noun = this.getNoun().out('normal'); - - if (noun) { - var auxList = { - i: 'am', - we: 'are', - they: 'are' - }; - - if (auxList.hasOwnProperty(noun)) { - aux = auxList[noun]; - } - } - - var end = aux + ' ' + obj.Gerund; //i would go -> i would have be going - // if (this.auxiliary && this.auxiliary.has('#Modal') && !this.auxiliary.has('will')) { - // end = this.auxiliary.match('#Modal').out() + ' have ' + end; - // } - - var r = this.replaceWith(end, false); - r.verb.tag('#Gerund'); - return r; - }, - asAdjective: function asAdjective() { - return toAdjective(this.verb.out('normal')); - } -}; - -var Verb = function Verb(arr, world, refText, parentTerms) { - Terms.call(this, arr, world, refText, parentTerms); //basic verb-phrase parsing: - - return _parse(this); -}; //Terms inheritence - - -Verb.prototype = Object.create(Terms.prototype); //apply methods - -Object.keys(methods).forEach(function (k) { - Verb.prototype[k] = methods[k]; -}); -module.exports = Verb; - -},{"../../paths":8,"./interpret":76,"./methods/conjugate":81,"./methods/isPlural":86,"./methods/toAdjective":89,"./methods/verbContraction":92,"./toNegative":93}],95:[function(_dereq_,module,exports){ -'use strict'; //the steps and processes of pos-tagging - -var step = { - punctuation_step: _dereq_('./steps/01-punctuation_step'), - emoji_step: _dereq_('./steps/02-emoji_step'), - lexicon_step: _dereq_('./steps/03-lexicon_step'), - lexicon_multi: _dereq_('./steps/04-lexicon_multi'), - web_step: _dereq_('./steps/05-web_step'), - suffix_step: _dereq_('./steps/06-suffix_step'), - neighbour_step: _dereq_('./steps/07-neighbour_step'), - capital_step: _dereq_('./steps/08-capital_step'), - noun_fallback: _dereq_('./steps/09-noun_fallback'), - contraction: _dereq_('./steps/10-contraction_step'), - date_step: _dereq_('./steps/11-date_step'), - auxiliary_step: _dereq_('./steps/12-auxiliary_step'), - negation_step: _dereq_('./steps/13-negation_step'), - comma_step: _dereq_('./steps/14-comma_step'), - quotation_step: _dereq_('./steps/15-quotation_step'), - possessive_step: _dereq_('./steps/16-possessive_step'), - acronym_step: _dereq_('./steps/17-acronym_step'), - person_step: _dereq_('./steps/18-person_step'), - organization_step: _dereq_('./steps/19-organization_step'), - parentheses_step: _dereq_('./steps/20-parentheses_step'), - plural_step: _dereq_('./steps/21-plural_step'), - value_step: _dereq_('./steps/22-value_step'), - corrections: _dereq_('./steps/23-corrections'), - properNoun: _dereq_('./steps/24-proper_noun'), - custom: _dereq_('./steps/25-custom') -}; - -var tagPhrase = _dereq_('./phrase'); - -var tagger = function tagger(ts) { - ts = step.punctuation_step(ts); - ts = step.emoji_step(ts); - ts = step.lexicon_step(ts); - ts = step.lexicon_multi(ts); - ts = step.web_step(ts); - ts = step.suffix_step(ts); - ts = step.comma_step(ts); //formerly #14 - - ts = step.neighbour_step(ts); - ts = step.capital_step(ts); - ts = step.noun_fallback(ts); - ts = step.contraction(ts); - ts = step.date_step(ts); //3ms - - ts = step.auxiliary_step(ts); - ts = step.negation_step(ts); - ts = step.quotation_step(ts); - ts = step.possessive_step(ts); - ts = step.acronym_step(ts); - ts = step.person_step(ts); //1ms - - ts = step.organization_step(ts); - ts = step.parentheses_step(ts); - ts = step.plural_step(ts); - ts = step.value_step(ts); - ts = step.corrections(ts); //2ms - - ts = step.properNoun(ts); - ts = tagPhrase(ts); - ts = step.custom(ts); - return ts; -}; - -module.exports = tagger; - -},{"./phrase":98,"./steps/01-punctuation_step":99,"./steps/02-emoji_step":100,"./steps/03-lexicon_step":101,"./steps/04-lexicon_multi":102,"./steps/05-web_step":103,"./steps/06-suffix_step":104,"./steps/07-neighbour_step":105,"./steps/08-capital_step":106,"./steps/09-noun_fallback":107,"./steps/10-contraction_step":108,"./steps/11-date_step":109,"./steps/12-auxiliary_step":110,"./steps/13-negation_step":111,"./steps/14-comma_step":112,"./steps/15-quotation_step":113,"./steps/16-possessive_step":114,"./steps/17-acronym_step":115,"./steps/18-person_step":116,"./steps/19-organization_step":117,"./steps/20-parentheses_step":118,"./steps/21-plural_step":119,"./steps/22-value_step":120,"./steps/23-corrections":121,"./steps/24-proper_noun":122,"./steps/25-custom":123}],96:[function(_dereq_,module,exports){ -'use strict'; // - -var conditionPass = function conditionPass(ts) { - //'if it really goes, I will..' - var m = ts.match('#Condition .{1,7} #ClauseEnd'); //make sure it ends on a comma - - if (m.found && m.match('#Comma$')) { - m.tag('Condition'); - } //'go a bit further, if it then has a pronoun - - - m = ts.match('#Condition .{1,13} #ClauseEnd #Pronoun'); - - if (m.found && m.match('#Comma$')) { - m.not('#Pronoun$').tag('Condition', 'end-pronoun'); - } //if it goes then .. - - - m = ts.match('#Condition .{1,7} then'); - - if (m.found) { - m.not('then$').tag('Condition', 'cond-then'); - } //as long as .. - - - m = ts.match('as long as .{1,7} (then|#ClauseEnd)'); - - if (m.found) { - m.not('then$').tag('Condition', 'as-long-then'); - } //at the end of a sentence: - //'..., if it really goes.' - - - m = ts.match('#Comma #Condition .{1,7} .$'); - - if (m.found) { - m.not('^#Comma').tag('Condition', 'comma-7-end'); - } // '... if so.' - - - m = ts.match('#Condition .{1,4}$'); - - if (m.found) { - m.tag('Condition', 'cond-4-end'); - } - - return ts; -}; - -module.exports = conditionPass; - -},{}],97:[function(_dereq_,module,exports){ -'use strict'; //a verbPhrase is a sequence of axiliaries, adverbs and verbs - -var verbPhrase = function verbPhrase(ts) { - if (ts.has('(#Verb|#Auxiliary)')) { - ts.match('#Verb').tag('VerbPhrase', 'verbphrase-verb'); //quickly was - - ts.match('#Adverb #Verb').tag('VerbPhrase', 'adverb-verb'); //was quickly - - ts.match('#Verb #Adverb').tag('VerbPhrase', 'verb-adverb'); //is not - - ts.match('#Verb #Negative').tag('VerbPhrase', 'verb-not'); //never is - - ts.match('never #Verb').tag('VerbPhrase', 'not-verb'); //'will have had'.. - - ts.match('#Auxiliary+').tag('VerbPhrase', '2'); // 'is' - - ts.match('#Copula').tag('VerbPhrase', '#3'); //'really will'.. - - ts.match('#Adverb #Auxiliary').tag('VerbPhrase', '#4'); //to go - // ts.match('to #Infinitive').tag('VerbPhrase', '#5'); - //work with - // ts.match('#Verb #Preposition').tag('VerbPhrase', '#6'); - } - - return ts; -}; - -module.exports = verbPhrase; - -},{}],98:[function(_dereq_,module,exports){ -'use strict'; - -var conditionPass = _dereq_('./00-conditionPass'); - -var verbPhrase = _dereq_('./01-verbPhrase'); // const nounPhrase = require('./02-nounPhrase'); -// const AdjectivePhrase = require('./03-adjectivePhrase'); -// - - -var phraseTag = function phraseTag(ts) { - ts = conditionPass(ts); - ts = verbPhrase(ts); // ts = nounPhrase(ts); - // ts = AdjectivePhrase(ts); - - return ts; -}; - -module.exports = phraseTag; - -},{"./00-conditionPass":96,"./01-verbPhrase":97}],99:[function(_dereq_,module,exports){ -'use strict'; //regs- - -var titleCase = /^[A-Z][a-z']/; -var romanNum = /^[IVXCM]+$/; //not so smart (right now) - -var isRomanNumeral = function isRomanNumeral(t) { - if (t.text.length > 1 && romanNum.test(t.text) === true) { - return t.canBe('RomanNumeral'); - } - - return false; -}; - -var oneLetters = { - a: true, - i: true, - //internet-slang - u: true, - r: true, - c: true, - k: true -}; - -var punctuation_step = function punctuation_step(ts) { - var rules = ts.world.regex || []; - ts.terms.forEach(function (t, o) { - var str = t.text; //anything can be titlecase - - if (titleCase.test(str) === true) { - t.tag('TitleCase', 'punct-rule'); - } //add hyphenation - - - if (t.whitespace.after === '-' && ts.terms[o + 1] && ts.terms[o + 1].whitespace.before === '') { - t.tag('Hyphenated', 'has-hyphen'); - ts.terms[o + 1].tag('Hyphenated', 'has-hyphen'); - } //look at () parentheses - - - if (t.text[0] === '(') { - t.tag('StartBracket'); - } //look at end-brackets (allow some punctuation after)! - - - if (/\)[,.?!;:]?$/.test(t.text) === true) { - t.tag('EndBracket'); - } //ok, normalise it a little, - - - str = str.replace(/[,\.\?]$/, ''); //do punctuation rules (on t.text) - - for (var i = 0; i < rules.length; i++) { - var r = rules[i]; - - if (r.reg.test(str) === true) { - //don't over-write any other known tags - if (t.canBe(r.tag)) { - t.tag(r.tag, 'punctuation-rule- "' + r.reg.toString() + '"'); - } - - return; - } - } //terms like 'e' - - - if (str.length === 1 && ts.terms[o + 1] && /[A-Z]/.test(str) && !oneLetters[str.toLowerCase()]) { - t.tag('Acronym', 'one-letter-acronym'); - } //roman numerals (weak rn) - - - if (isRomanNumeral(t)) { - t.tag('RomanNumeral', 'is-roman-numeral'); - } //'100+' - - - if (/[0-9]\+$/.test(t.text) === true) { - t.tag('NumericValue', 'number-plus'); - } - }); - return ts; -}; - -module.exports = punctuation_step; - -},{}],100:[function(_dereq_,module,exports){ -'use strict'; - -var emojiReg = _dereq_('./rules/emoji_regex'); - -var emoticon = _dereq_('./rules/emoticon_list'); //for us, there's three types - -// * ;) - emoticons -// * 🌵 - unicode emoji -// * :smiling_face: - asci-represented emoji -//test for forms like ':woman_tone2:‍:ear_of_rice:' -//https://github.com/Kikobeats/emojis-keywords/blob/master/index.js - - -var isColonEmoji = function isColonEmoji(t) { - if (t.text.charAt(0) === ':') { - //end comma can be last or second-last ':haircut_tone3:‍♀️' - if (t.text.match(/:.?$/) === null) { - return false; - } //ensure no spaces - - - if (t.text.match(' ')) { - return false; - } //reasonably sized - - - if (t.text.length > 35) { - return false; - } - - return true; - } - - return false; -}; //check against emoticon whitelist - - -var isEmoticon = function isEmoticon(t) { - //normalize the 'eyes' - var str = t.text.replace(/^[:;]/, ':'); - return emoticon.hasOwnProperty(str) === true; -}; // - - -var emojiStep = function emojiStep(ts) { - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; //test for :keyword: emojis - - if (isColonEmoji(t)) { - t.tag('Emoji', 'colon-emoji'); - } //test for unicode emojis - - - if (t.text.match(emojiReg)) { - t.tag('Emoji', 'unicode-emoji'); - } //test for emoticon ':)' emojis - - - if (isEmoticon(t)) { - t.tag('Emoji', 'emoticon-emoji'); - } - } - - return ts; -}; - -module.exports = emojiStep; - -},{"./rules/emoji_regex":130,"./rules/emoticon_list":131}],101:[function(_dereq_,module,exports){ -'use strict'; - -var split = _dereq_('./contraction/split'); // const l = require('../../lexicon/init'); -// const lexicon = l.lexicon; - - -var lexicon_pass = function lexicon_pass(ts) { - var lexicon = ts.world.words || {}; //loop through each term - - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; //basic term lookup - - if (lexicon.hasOwnProperty(t.normal) === true) { - t.tag(lexicon[t.normal], 'lexicon'); - continue; - } //support silent_term matches - - - if (t.silent_term && lexicon.hasOwnProperty(t.silent_term) === true) { - t.tag(lexicon[t.silent_term], 'silent_term-lexicon'); - continue; - } //check root version too - - - if (t.root && t.normal !== t.root) { - if (lexicon.hasOwnProperty(t.root) === true) { - t.tag(lexicon[t.root], 'lexicon'); - continue; - } - } //support contractions (manually) - - - var parts = split(t); - - if (parts && parts.start) { - var start = parts.start.toLowerCase(); - - if (lexicon.hasOwnProperty(start) === true) { - t.tag(lexicon[start], 'contraction-lexicon'); - continue; - } - } - } - - return ts; -}; - -module.exports = lexicon_pass; - -},{"./contraction/split":129}],102:[function(_dereq_,module,exports){ -'use strict'; - -var MAX = 4; //find terms in the lexicon longer than one word (like 'hong kong') - -var findMultiWords = function findMultiWords(ts, i, world) { - var lex = world.words; - var start = ts.terms[i].root; - var nextTerms = ts.terms.slice(i + 1, i + MAX).map(function (t) { - return t.root; - }); //look for matches, try biggest first - - var max = MAX; - - if (nextTerms.length < max) { - max = nextTerms.length; - } - - for (var k = max; k > 0; k -= 1) { - var howAbout = start + ' ' + nextTerms.slice(0, k).join(' '); - - if (lex.hasOwnProperty(howAbout) === true) { - ts.slice(i, i + k + 1).tag(lex[howAbout], 'multi-lexicon-' + howAbout); - return k; - } - } - - return 0; -}; //try multiple-word matches in the lexicon (users and default) - - -var lexiconMulti = function lexiconMulti(ts) { - ts.world.cache = ts.world.cache || {}; - var firstWords = ts.world.cache.firstWords || {}; - - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; //try multi words from user-lexicon - - if (firstWords.hasOwnProperty(t.root) === true) { - var jump = findMultiWords(ts, i, ts.world); - i += jump; - continue; - } - } - - return ts; -}; - -module.exports = lexiconMulti; - -},{}],103:[function(_dereq_,module,exports){ -'use strict'; //identify urls, hashtags, @mentions, emails -//regs - -var email = /^\w+@\w+\.[a-z]{2,3}$/; //not fancy - -var hashTag = /^#[a-z0-9_]{2,}$/; -var atMention = /^@\w{2,}$/; -var urlA = /^(https?:\/\/|www\.)\w+\.[a-z]{2,3}/; //with http/www - -var urlB = /^[\w\.\/]+\.(com|net|gov|org|ly|edu|info|biz|ru|jp|de|in|uk|br)/; //http://mostpopularwebsites.net/top-level-domain - -var web_pass = function web_pass(terms) { - for (var i = 0; i < terms.length; i++) { - var t = terms.get(i); - var str = t.text.trim().toLowerCase(); - - if (email.test(str) === true) { - t.tag('Email', 'web_pass'); - } - - if (hashTag.test(str) === true) { - t.tag('HashTag', 'web_pass'); - } - - if (atMention.test(str) === true) { - t.tag('AtMention', 'web_pass'); - } - - if (urlA.test(str) === true || urlB.test(str) === true) { - t.tag('Url', 'web_pass'); - } - } - - return terms; -}; - -module.exports = web_pass; - -},{}],104:[function(_dereq_,module,exports){ -'use strict'; - -var regs = _dereq_('./rules/regex_list'); - -var suffixes = _dereq_('./rules/suffix_lookup'); - -var misc = [//slang things -[/^(lol)+[sz]$/, 'Expression'], //lol -[/^ma?cd[aeiou]/, 'LastName'], //macdonell - Last patterns https://en.wikipedia.org/wiki/List_of_family_name_affixes -//starting-ones -[/^[\-\+]?[0-9][0-9,]*(\.[0-9])*$/, 'Cardinal'], //like 5 -[/^(un|de|re)\\-[a-z]../, 'Verb'], [/^[\-\+]?[0-9]+(\.[0-9])*$/, 'NumericValue'], [/^https?\:?\/\/[a-z0-9]/, 'Url'], //the colon is removed in normalisation -[/^www\.[a-z0-9]/, 'Url'], [/^(over|under)[a-z]{2,}/, 'Adjective'], [/^[0-9]{1,4}\.[0-9]{1,2}\.[0-9]{1,4}$/, 'Date'], // 03-02-89 -//ending-ones -[/^[0-9]+([a-z]{1,2})$/, 'Value'], //like 5kg -[/^[0-9][0-9,\.]*(st|nd|rd|r?th)$/, ['NumericValue', 'Ordinal']], //like 5th -//middle (anywhere) -[/[a-z]*\\-[a-z]*\\-/, 'Adjective']]; //straight-up lookup of known-suffixes - -var lookup = function lookup(t) { - var len = t.normal.length; - var max = 7; - - if (len <= max) { - max = len - 1; - } - - for (var i = max; i > 1; i -= 1) { - var str = t.normal.substr(len - i, len); - - if (suffixes[i][str] !== undefined) { - // console.log('suffix-match: ' + str); - return suffixes[i][str]; - } - } - - return null; -}; //word-regexes indexed by last-character - - -var regexFn = function regexFn(t) { - var _char = t.normal.charAt(t.normal.length - 1); - - if (regs[_char] === undefined) { - return null; - } - - var arr = regs[_char]; - - for (var o = 0; o < arr.length; o++) { - if (arr[o][0].test(t.normal) === true) { - return arr[o]; - } - } - - return null; -}; - -var suffix_step = function suffix_step(ts) { - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; //try known suffixes - - var tag = lookup(t); - - if (tag !== null && t.canBe(tag) === true) { - t.tag(tag, 'suffix-lookup'); - continue; - } //apply regexes by final-char - - - tag = regexFn(t); - - if (tag !== null && t.canBe(tag[1]) === true) { - t.tag(tag[1], 'regex-list: ' + String(tag[0])); - continue; - } //apply misc regexes - - - for (var o = 0; o < misc.length; o++) { - if (misc[o][0].test(t.normal) === true) { - tag = misc[o][1]; - - if (t.canBe(tag) === true) { - t.tag(tag, 'misc-regex-' + misc[o][0]); - } - } - } - } - - return ts; -}; - -module.exports = suffix_step; - -},{"./rules/regex_list":133,"./rules/suffix_lookup":134}],105:[function(_dereq_,module,exports){ -'use strict'; - -var markov = _dereq_('./rules/neighbours'); - -var afterThisWord = markov.afterThisWord; -var beforeThisWord = markov.beforeThisWord; -var beforeThisPos = markov.beforeThisPos; -var afterThisPos = markov.afterThisPos; -var nothing = { - TitleCase: true, - UpperCase: true, - CamelCase: true, - Hyphenated: true, - StartBracket: true, - EndBracket: true, - Comma: true, - ClauseEnd: true -}; //basically a last-ditch effort before everything falls back to a noun -//for unknown terms, look left + right first, and hit-up the markov-chain for clues - -var neighbour_step = function neighbour_step(ts) { - ts.terms.forEach(function (t, n) { - //is it still unknown? - var termTags = Object.keys(t.tags); - termTags = termTags.filter(function (tag) { - return nothing.hasOwnProperty(tag) === false; - }); - - if (termTags.length === 0) { - var lastTerm = ts.terms[n - 1]; - var nextTerm = ts.terms[n + 1]; //look at previous word for clues - - if (lastTerm && afterThisWord.hasOwnProperty(lastTerm.normal) && !lastTerm.tags.ClauseEnd) { - t.tag(afterThisWord[lastTerm.normal], 'neighbour-after-"' + lastTerm.normal + '"'); - return; - } //look at next word for clues.. - //(not if there's a comma, though) - - - if (!t.tags.ClauseEnd && nextTerm && beforeThisWord.hasOwnProperty(nextTerm.normal)) { - t.tag(beforeThisWord[nextTerm.normal], 'neighbour-before-"' + nextTerm.normal + '"'); - return; - } //look at the last POS for clues - - - var tags = []; - - if (lastTerm) { - tags = Object.keys(lastTerm.tags); - - for (var i = 0; i < tags.length; i++) { - if (afterThisPos[tags[i]]) { - t.tag(afterThisPos[tags[i]], 'neighbour-after-[' + tags[i] + ']'); - return; - } - } - } //look at the next POS for clues - - - if (nextTerm) { - tags = Object.keys(nextTerm.tags); - - for (var _i = 0; _i < tags.length; _i++) { - if (beforeThisPos[tags[_i]]) { - t.tag(beforeThisPos[tags[_i]], 'neighbour-before-[' + tags[_i] + ']'); - return; - } - } - } - } - }); - return ts; -}; - -module.exports = neighbour_step; - -},{"./rules/neighbours":132}],106:[function(_dereq_,module,exports){ -'use strict'; //titlecase is a signal for a noun - -var capital_logic = function capital_logic(s) { - //(ignore first word) - for (var i = 1; i < s.terms.length; i++) { - var _t = s.terms[i]; //has a capital, but isn't too weird. - - if (_t.tags.TitleCase && _t.isWord()) { - _t.tag('Noun', 'capital-step'); - - _t.tag('TitleCase', 'capital-step'); - } - } //support first-word of sentence as proper titlecase - - - var t = s.terms[0]; - - if (t && t.tags.TitleCase) { - if (t.tags.Person || t.tags.Organization || t.tags.Place) { - t.tag('TitleCase', 'first-term-capital'); - } - } - - return s; -}; - -module.exports = capital_logic; - -},{}],107:[function(_dereq_,module,exports){ -'use strict'; //tag word as noun if we know nothing about it, still. -//tags that dont really count - -var nothing = { - TitleCase: true, - UpperCase: true, - CamelCase: true, - Hyphenated: true, - StartBracket: true, - EndBracket: true, - Comma: true, - ClauseEnd: true -}; //are the tags basically empty - -var gotNothing = function gotNothing(t) { - //fail-fast - if (t.tags.Noun || t.tags.Verb || t.tags.Adjective) { - return false; - } - - var tags = Object.keys(t.tags); - - if (tags.length === 0) { - return true; - } - - if (tags.filter(function (tag) { - return !nothing[tag]; - }).length === 0) { - return true; - } - - return false; -}; //in last-ditch, try to match 'rewatch' -> 'watch' in the lexicon - - -var tryRoot = function tryRoot(t) { - if (/^(re|un)-?[^aeiou]./.test(t.normal) === true) { - var str = t.normal.replace(/^(re|un)-?/, ''); - - if (t.world.words.hasOwnProperty(str) === true) { - var tag = t.world.words[str]; - - if (tag === 'Infinitive' || tag === 'PresentTense' || tag === 'PastTense' || tag === 'Gerund') { - return tag; - } - } - } - - return null; -}; - -var noun_fallback = function noun_fallback(s) { - for (var i = 0; i < s.terms.length; i++) { - var t = s.terms[i]; //fail-fast - - if (t.tags.Noun || t.tags.Verb) { - continue; - } //ensure it only has the tag 'Term' - - - if (gotNothing(t)) { - //ensure it's atleast word-looking - if (t.isWord() === false) { - continue; - } - - var rootTag = tryRoot(t); - - if (rootTag !== null) { - t.tag(rootTag, 'root-tag-match'); - continue; - } - - t.tag('Noun', 'noun-fallback'); - } - } - - return s; -}; - -module.exports = noun_fallback; - -},{}],108:[function(_dereq_,module,exports){ -'use strict'; - -var irregulars = _dereq_('./contraction/01-irregulars'); - -var isWasHas = _dereq_('./contraction/02-isWasHas'); - -var easyOnes = _dereq_('./contraction/03-easyOnes'); - -var numberRange = _dereq_('./contraction/04-numberRange'); //find and pull-apart contractions - - -var interpret = function interpret(ts) { - //check irregulars - ts = irregulars(ts); //guess-at ambiguous "'s" one - - ts = isWasHas(ts); //check easy ones - - ts = easyOnes(ts); //5-7 - - ts = numberRange(ts); - return ts; -}; - -module.exports = interpret; - -},{"./contraction/01-irregulars":124,"./contraction/02-isWasHas":125,"./contraction/03-easyOnes":126,"./contraction/04-numberRange":127}],109:[function(_dereq_,module,exports){ -'use strict'; //ambiguous 'may' and 'march' - -var preps = '(in|by|before|during|on|until|after|of|within|all)'; -var thisNext = '(last|next|this|previous|current|upcoming|coming)'; -var sections = '(start|end|middle|starting|ending|midpoint|beginning)'; -var seasons = '(spring|summer|winter|fall|autumn)'; //ensure a year is approximately typical for common years -//please change in one thousand years - -var tagYear = function tagYear(v, reason) { - if (v.found !== true) { - return; - } - - v.list.forEach(function (ts) { - var num = parseInt(ts.terms[0].normal, 10); - - if (num && num > 1000 && num < 3000) { - ts.terms[0].tag('Year', reason); - } - }); -}; //same, but for less-confident values - - -var tagYearSafer = function tagYearSafer(v, reason) { - if (v.found !== true) { - return; - } - - v.list.forEach(function (ts) { - var num = parseInt(ts.terms[0].normal, 10); - - if (num && num > 1900 && num < 2030) { - ts.terms[0].tag('Year', reason); + // a list of irregular verb conjugations + // used in verbs().conjugate() + // but also added to our lexicon + //use shorter key-names + var mapping = { + g: 'Gerund', + prt: 'Participle', + perf: 'PerfectTense', + pst: 'PastTense', + fut: 'FuturePerfect', + pres: 'PresentTense', + pluperf: 'Pluperfect', + a: 'Actor' + }; // '_' in conjugations is the infinitive form + + var conjugations = { + act: { + a: '_or' + }, + age: { + g: 'ageing', + pst: 'aged', + pres: 'ages' + }, + aim: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + arise: { + prt: '_n', + pst: 'arose' + }, + babysit: { + a: '_ter', + pst: 'babysat' + }, + ban: { + a: '', + g: '_ning', + pst: '_ned' + }, + be: { + a: '', + g: 'am', + prt: 'been', + pst: 'was', + pres: 'is' + }, + beat: { + a: '_er', + g: '_ing', + prt: '_en' + }, + become: { + prt: '_' + }, + begin: { + g: '_ning', + prt: 'begun', + pst: 'began' + }, + being: { + g: 'are', + pst: 'were', + pres: 'are' + }, + bend: { + prt: 'bent' + }, + bet: { + a: '_ter', + prt: '_' + }, + bind: { + pst: 'bound' + }, + bite: { + g: 'biting', + prt: 'bitten', + pst: 'bit' + }, + bleed: { + prt: 'bled', + pst: 'bled' + }, + blow: { + prt: '_n', + pst: 'blew' + }, + boil: { + a: '_er' + }, + brake: { + prt: 'broken' + }, + "break": { + pst: 'broke' + }, + breed: { + pst: 'bred' + }, + bring: { + prt: 'brought', + pst: 'brought' + }, + broadcast: { + pst: '_' + }, + budget: { + pst: '_ed' + }, + build: { + prt: 'built', + pst: 'built' + }, + burn: { + prt: '_ed' + }, + burst: { + prt: '_' + }, + buy: { + prt: 'bought', + pst: 'bought' + }, + can: { + a: '', + fut: '_', + g: '', + pst: 'could', + perf: 'could', + pluperf: 'could', + pres: '_' + }, + "catch": { + pst: 'caught' + }, + choose: { + g: 'choosing', + prt: 'chosen', + pst: 'chose' + }, + cling: { + prt: 'clung' + }, + come: { + prt: '_', + pst: 'came' + }, + compete: { + a: 'competitor', + g: 'competing', + pst: '_d' + }, + cost: { + pst: '_' + }, + creep: { + prt: 'crept' + }, + cut: { + prt: '_' + }, + deal: { + prt: '_t', + pst: '_t' + }, + develop: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + die: { + g: 'dying', + pst: '_d' + }, + dig: { + g: '_ging', + prt: 'dug', + pst: 'dug' + }, + dive: { + prt: '_d' + }, + "do": { + pst: 'did', + pres: '_es' + }, + draw: { + prt: '_n', + pst: 'drew' + }, + dream: { + prt: '_t' + }, + drink: { + prt: 'drunk', + pst: 'drank' + }, + drive: { + g: 'driving', + prt: '_n', + pst: 'drove' + }, + drop: { + g: '_ping', + pst: '_ped' + }, + eat: { + a: '_er', + g: '_ing', + prt: '_en', + pst: 'ate' + }, + edit: { + g: '_ing' + }, + egg: { + pst: '_ed' + }, + fall: { + prt: '_en', + pst: 'fell' + }, + feed: { + prt: 'fed', + pst: 'fed' + }, + feel: { + a: '_er', + pst: 'felt' + }, + fight: { + prt: 'fought', + pst: 'fought' + }, + find: { + pst: 'found' + }, + flee: { + g: '_ing', + prt: 'fled' + }, + fling: { + prt: 'flung' + }, + fly: { + prt: 'flown', + pst: 'flew' + }, + forbid: { + pst: 'forbade' + }, + forget: { + g: '_ing', + prt: 'forgotten', + pst: 'forgot' + }, + forgive: { + g: 'forgiving', + prt: '_n', + pst: 'forgave' + }, + free: { + a: '', + g: '_ing' + }, + freeze: { + g: 'freezing', + prt: 'frozen', + pst: 'froze' + }, + get: { + pst: 'got', + prt: 'gotten' + }, + give: { + g: 'giving', + prt: '_n', + pst: 'gave' + }, + go: { + prt: '_ne', + pst: 'went', + pres: 'goes' + }, + grow: { + prt: '_n' + }, + hang: { + prt: 'hung', + pst: 'hung' + }, + have: { + g: 'having', + prt: 'had', + pst: 'had', + pres: 'has' + }, + hear: { + prt: '_d', + pst: '_d' + }, + hide: { + prt: 'hidden', + pst: 'hid' + }, + hit: { + prt: '_' + }, + hold: { + prt: 'held', + pst: 'held' + }, + hurt: { + prt: '_', + pst: '_' + }, + ice: { + g: 'icing', + pst: '_d' + }, + imply: { + pst: 'implied', + pres: 'implies' + }, + is: { + a: '', + g: 'being', + pst: 'was', + pres: '_' + }, + keep: { + prt: 'kept' + }, + kneel: { + prt: 'knelt' + }, + know: { + prt: '_n' + }, + lay: { + prt: 'laid', + pst: 'laid' + }, + lead: { + prt: 'led', + pst: 'led' + }, + leap: { + prt: '_t' + }, + leave: { + prt: 'left', + pst: 'left' + }, + lend: { + prt: 'lent' + }, + lie: { + g: 'lying', + pst: 'lay' + }, + light: { + prt: 'lit', + pst: 'lit' + }, + log: { + g: '_ging', + pst: '_ged' + }, + loose: { + prt: 'lost' + }, + lose: { + g: 'losing', + pst: 'lost' + }, + make: { + prt: 'made', + pst: 'made' + }, + mean: { + prt: '_t', + pst: '_t' + }, + meet: { + a: '_er', + g: '_ing', + prt: 'met', + pst: 'met' + }, + miss: { + pres: '_' + }, + pay: { + prt: 'paid', + pst: 'paid' + }, + prove: { + prt: '_n' + }, + puke: { + g: 'puking' + }, + put: { + prt: '_' + }, + quit: { + prt: '_' + }, + read: { + prt: '_', + pst: '_' + }, + ride: { + prt: 'ridden' + }, + ring: { + prt: 'rung', + pst: 'rang' + }, + rise: { + fut: 'will have _n', + g: 'rising', + prt: '_n', + pst: 'rose', + pluperf: 'had _n' + }, + rub: { + g: '_bing', + pst: '_bed' + }, + run: { + g: '_ning', + prt: '_', + pst: 'ran' + }, + say: { + prt: 'said', + pst: 'said', + pres: '_s' + }, + seat: { + prt: 'sat' + }, + see: { + g: '_ing', + prt: '_n', + pst: 'saw' + }, + seek: { + prt: 'sought' + }, + sell: { + prt: 'sold', + pst: 'sold' + }, + send: { + prt: 'sent' + }, + set: { + prt: '_' + }, + sew: { + prt: '_n' + }, + shake: { + prt: '_n' + }, + shave: { + prt: '_d' + }, + shed: { + g: '_ding', + pst: '_', + pres: '_s' + }, + shine: { + prt: 'shone', + pst: 'shone' + }, + shoot: { + prt: 'shot', + pst: 'shot' + }, + show: { + pst: '_ed' + }, + shut: { + prt: '_' + }, + sing: { + prt: 'sung', + pst: 'sang' + }, + sink: { + pst: 'sank', + pluperf: 'had sunk' + }, + sit: { + pst: 'sat' + }, + ski: { + pst: '_ied' + }, + slay: { + prt: 'slain' + }, + sleep: { + prt: 'slept' + }, + slide: { + prt: 'slid', + pst: 'slid' + }, + smash: { + pres: '_es' + }, + sneak: { + prt: 'snuck' + }, + speak: { + fut: 'will have spoken', + prt: 'spoken', + pst: 'spoke', + perf: 'have spoken', + pluperf: 'had spoken' + }, + speed: { + prt: 'sped' + }, + spend: { + prt: 'spent' + }, + spill: { + prt: '_ed', + pst: 'spilt' + }, + spin: { + g: '_ning', + prt: 'spun', + pst: 'spun' + }, + spit: { + prt: 'spat' + }, + split: { + prt: '_' + }, + spread: { + pst: '_' + }, + spring: { + prt: 'sprung' + }, + stand: { + pst: 'stood' + }, + steal: { + a: '_er', + pst: 'stole' + }, + stick: { + pst: 'stuck' + }, + sting: { + pst: 'stung' + }, + stink: { + prt: 'stunk', + pst: 'stunk' + }, + stream: { + a: '_er' + }, + strew: { + prt: '_n' + }, + strike: { + g: 'striking', + pst: 'struck' + }, + suit: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + sware: { + prt: 'sworn' + }, + swear: { + pst: 'swore' + }, + sweep: { + prt: 'swept' + }, + swim: { + g: '_ming', + pst: 'swam' + }, + swing: { + pst: 'swung' + }, + take: { + fut: 'will have _n', + pst: 'took', + perf: 'have _n', + pluperf: 'had _n' + }, + teach: { + pst: 'taught', + pres: '_es' + }, + tear: { + pst: 'tore' + }, + tell: { + pst: 'told' + }, + think: { + pst: 'thought' + }, + thrive: { + prt: '_d' + }, + tie: { + g: 'tying', + pst: '_d' + }, + undergo: { + prt: '_ne' + }, + understand: { + pst: 'understood' + }, + upset: { + prt: '_' + }, + wait: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + wake: { + pst: 'woke' + }, + wear: { + pst: 'wore' + }, + weave: { + prt: 'woven' + }, + weep: { + prt: 'wept' + }, + win: { + g: '_ning', + pst: 'won' + }, + wind: { + prt: 'wound' + }, + withdraw: { + pst: 'withdrew' + }, + wring: { + prt: 'wrung' + }, + write: { + g: 'writing', + prt: 'written', + pst: 'wrote' } - }); -}; //non-destructively tag values & prepositions as dates - - -var datePass = function datePass(ts) { - //ambiguous month - person forms - var people = '(january|april|may|june|summer|autumn|jan|sep)'; - - if (ts.has(people)) { - //give to april - ts.match("#Infinitive #Determiner? #Adjective? #Noun? (to|for) ".concat(people)).lastTerm().tag('Person', 'ambig-person'); //remind june + }; //uncompress our ad-hoc compression scheme - ts.match("#Infinitive ".concat(people)).lastTerm().tag('Person', 'infinitive-person'); //may waits for + var keys = Object.keys(conjugations); - ts.match("".concat(people, " #PresentTense (to|for)")).firstTerm().tag('Person', 'ambig-active'); //april will + var _loop = function _loop(i) { + var inf = keys[i]; + var _final = {}; + Object.keys(conjugations[inf]).forEach(function (key) { + var str = conjugations[inf][key]; //swap-in infinitives for '_' - ts.match("".concat(people, " #Modal")).firstTerm().tag('Person', 'ambig-modal'); //would april - - ts.match("#Modal ".concat(people)).lastTerm().tag('Person', 'modal-ambig'); //with april - - ts.match("(that|with|for) ".concat(people)).term(1).tag('Person', 'that-month'); //it is may - - ts.match("#Copula ".concat(people)).term(1).tag('Person', 'is-may'); //may is - - ts.match("".concat(people, " #Copula")).term(0).tag('Person', 'may-is'); //april the 5th - - ts.match("".concat(people, " the? #Value")).term(0).tag('Month', 'person-value'); //wednesday april - - ts.match("#Date ".concat(people)).term(1).tag('Month', 'correction-may'); //may 5th - - ts.match("".concat(people, " the? #Value")).firstTerm().tag('Month', 'may-5th'); //5th of may - - ts.match("#Value of ".concat(people)).lastTerm().tag('Month', '5th-of-may'); //by april - - ts.match("".concat(preps, " ").concat(people)).ifNo('#Holiday').term(1).tag('Month', 'preps-month'); //this april - - ts.match("(next|this|last) ".concat(people)).term(1).tag('Month', 'correction-may'); //maybe not 'this' - } //ambiguous month - verb-forms + str = str.replace('_', inf); + var full = mapping[key]; + _final[full] = str; + }); //over-write original + conjugations[inf] = _final; + }; - var verbs = '(may|march)'; + for (var i = 0; i < keys.length; i++) { + _loop(i); + } + + var conjugations_1 = conjugations; + + var endsWith = { + b: [{ + reg: /([^aeiou][aeiou])b$/i, + repl: { + pr: '$1bs', + pa: '$1bbed', + gr: '$1bbing' + } + }], + d: [{ + reg: /(end)$/i, + repl: { + pr: '$1s', + pa: 'ent', + gr: '$1ing', + ar: '$1er' + } + }, { + reg: /(eed)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + ar: '$1er' + } + }, { + reg: /(ed)$/i, + repl: { + pr: '$1s', + pa: '$1ded', + ar: '$1der', + gr: '$1ding' + } + }, { + reg: /([^aeiou][ou])d$/i, + repl: { + pr: '$1ds', + pa: '$1dded', + gr: '$1dding' + } + }], + e: [{ + reg: /(eave)$/i, + repl: { + pr: '$1s', + pa: '$1d', + gr: 'eaving', + ar: '$1r' + } + }, { + reg: /(ide)$/i, + repl: { + pr: '$1s', + pa: 'ode', + gr: 'iding', + ar: 'ider' + } + }, { + reg: /(ake)$/i, + repl: { + pr: '$1s', + pa: 'ook', + gr: 'aking', + ar: '$1r' + } + }, { + reg: /(a[tg]|i[zn]|ur|nc|gl|is)e$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing', + prt: '$1en' + } + }, { + reg: /([bd]l)e$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /(om)e$/i, + repl: { + pr: '$1es', + pa: 'ame', + gr: '$1ing' + } + }], + g: [{ + reg: /([^aeiou][ou])g$/i, + repl: { + pr: '$1gs', + pa: '$1gged', + gr: '$1gging' + } + }], + h: [{ + reg: /(..)([cs]h)$/i, + repl: { + pr: '$1$2es', + pa: '$1$2ed', + gr: '$1$2ing' + } + }], + k: [{ + reg: /(ink)$/i, + repl: { + pr: '$1s', + pa: 'unk', + gr: '$1ing', + ar: '$1er' + } + }], + m: [{ + reg: /([^aeiou][aeiou])m$/i, + repl: { + pr: '$1ms', + pa: '$1mmed', + gr: '$1mming' + } + }], + n: [{ + reg: /(en)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }], + p: [{ + reg: /(e)(ep)$/i, + repl: { + pr: '$1$2s', + pa: '$1pt', + gr: '$1$2ing', + ar: '$1$2er' + } + }, { + reg: /([^aeiou][aeiou])p$/i, + repl: { + pr: '$1ps', + pa: '$1pped', + gr: '$1pping' + } + }, { + reg: /([aeiu])p$/i, + repl: { + pr: '$1ps', + pa: '$1p', + gr: '$1pping' + } + }], + r: [{ + reg: /([td]er)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /(er)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }], + s: [{ + reg: /(ish|tch|ess)$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing' + } + }], + t: [{ + reg: /(ion|end|e[nc]t)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /(.eat)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /([aeiu])t$/i, + repl: { + pr: '$1ts', + pa: '$1t', + gr: '$1tting' + } + }, { + reg: /([^aeiou][aeiou])t$/i, + repl: { + pr: '$1ts', + pa: '$1tted', + gr: '$1tting' + } + }], + w: [{ + reg: /(..)(ow)$/i, + repl: { + pr: '$1$2s', + pa: '$1ew', + gr: '$1$2ing', + prt: '$1$2n' + } + }], + y: [{ + reg: /([i|f|rr])y$/i, + repl: { + pr: '$1ies', + pa: '$1ied', + gr: '$1ying' + } + }], + z: [{ + reg: /([aeiou]zz)$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing' + } + }] + }; + var suffixes = endsWith; + + var posMap = { + pr: 'PresentTense', + pa: 'PastTense', + gr: 'Gerund', + prt: 'Participle', + ar: 'Actor' + }; - if (ts.has(verbs)) { - //quickly march - ts.match("#Adverb ".concat(verbs)).lastTerm().tag('Infinitive', 'ambig-verb'); - ts.match("".concat(verbs, " #Adverb")).lastTerm().tag('Infinitive', 'ambig-verb'); //all march + var doTransform = function doTransform(str, obj) { + var found = {}; + var keys = Object.keys(obj.repl); - ts.match("".concat(preps, " ").concat(verbs)).lastTerm().tag('Month', 'in-month'); //this march + for (var i = 0; i < keys.length; i += 1) { + var pos = keys[i]; + found[posMap[pos]] = str.replace(obj.reg, obj.repl[pos]); + } - ts.match("(next|this|last) ".concat(verbs)).lastTerm().tag('Month', 'this-month'); //with date + return found; + }; //look at the end of the word for clues - ts.match("".concat(verbs, " the? #Value")).firstTerm().tag('Month', 'march-5th'); - ts.match("#Value of? ".concat(verbs)).lastTerm().tag('Month', '5th-of-march'); //nearby - ts.match("[".concat(verbs, "] .? #Date")).lastTerm().tag('Month', 'march-and-feb'); - ts.match("#Date .? [".concat(verbs, "]")).lastTerm().tag('Month', 'feb-and-march'); + var checkSuffix = function checkSuffix() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var c = str[str.length - 1]; - if (ts.has('march')) { - //march to - ts.match('march (up|down|back|to|toward)').term(0).tag('Infinitive', 'march-to'); //must march + if (suffixes.hasOwnProperty(c) === true) { + for (var r = 0; r < suffixes[c].length; r += 1) { + var reg = suffixes[c][r].reg; - ts.match('#Modal march').term(1).tag('Infinitive', 'must-march'); + if (reg.test(str) === true) { + return doTransform(str, suffixes[c][r]); + } + } } - } //sun 5th - - - if (ts.has('sun')) { - //sun feb 2 - ts.match('sun #Date').firstTerm().tag('WeekDay', 'sun-feb'); //sun the 5th - - ts.match('sun the #Ordinal').tag('Date').firstTerm().tag('WeekDay', 'sun-the-5th'); //the sun - ts.match('#Determiner sun').lastTerm().tag('Singular', 'the-sun'); - } //sat, nov 5th + return {}; + }; + var _01Suffixes = checkSuffix; - if (ts.has('sat')) { - //sat november - ts.match('sat #Date').firstTerm().tag('WeekDay', 'sat-feb'); //this sat + //non-specifc, 'hail-mary' transforms from infinitive, into other forms + var hasY = /[bcdfghjklmnpqrstvwxz]y$/; + var generic = { + Gerund: function Gerund(inf) { + if (inf.charAt(inf.length - 1) === 'e') { + return inf.replace(/e$/, 'ing'); + } - ts.match("".concat(preps, " sat")).lastTerm().tag('WeekDay', 'sat'); - } //months: + return inf + 'ing'; + }, + PresentTense: function PresentTense(inf) { + if (inf.charAt(inf.length - 1) === 's') { + return inf + 'es'; + } + if (hasY.test(inf) === true) { + return inf.slice(0, -1) + 'ies'; + } - if (ts.has('#Month')) { - //June 5-7th - ts.match("#Month #DateRange+").tag('Date', 'correction-numberRange'); //5th of March + return inf + 's'; + }, + PastTense: function PastTense(inf) { + if (inf.charAt(inf.length - 1) === 'e') { + return inf + 'd'; + } - ts.match('#Value of #Month').tag('Date', 'value-of-month'); //5 March + if (inf.substr(-2) === 'ed') { + return inf; + } - ts.match('#Cardinal #Month').tag('Date', 'cardinal-month'); //march 5 to 7 + if (hasY.test(inf) === true) { + return inf.slice(0, -1) + 'ied'; + } - ts.match('#Month #Value to #Value').tag('Date', 'value-to-value'); //march the 12th + return inf + 'ed'; + } + }; + var _02Generic = generic; - ts.match('#Month the #Value').tag('Date', 'month-the-value'); - } + //we assume the input word is a proper infinitive - ts.match('in the (night|evening|morning|afternoon|day|daytime)').tag('Time', 'in-the-night'); - ts.match('(#Value|#Time) (am|pm)').tag('Time', 'value-ampm'); //months: + var conjugate = function conjugate() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var world = arguments.length > 1 ? arguments[1] : undefined; + var found = {}; // 1. look at irregulars + //the lexicon doesn't pass this in - if (ts.has('#Value')) { - //for 4 months - ts.match('for #Value #Duration').tag('Date', 'for-x-duration'); //values + if (world && world.irregulars) { + if (world.irregulars.verbs.hasOwnProperty(str) === true) { + found = Object.assign({}, world.irregulars.verbs[str]); + } + } //2. rule-based regex - ts.match('#Value #Abbreviation').tag('Value', 'value-abbr'); - ts.match('a #Value')["if"]('(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)').tag('Value', 'a-value'); - ts.match('(minus|negative) #Value').tag('Value', 'minus-value'); - ts.match('#Value grand').tag('Value', 'value-grand'); // ts.match('#Ordinal (half|quarter)').tag('Value', 'ordinal-half');//not ready - ts.match('(half|quarter) #Ordinal').tag('Value', 'half-ordinal'); - ts.match('(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion) and #Value').tag('Value', 'magnitude-and-value'); - ts.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value'); //for four days + found = Object.assign({}, _01Suffixes(str), found); //3. generic transformations + //'buzzing' - ts.match("".concat(preps, "? #Value #Duration")).tag('Date', 'value-duration'); - ts.match('(#WeekDay|#Month) #Value').ifNo('#Money').tag('Date', 'date-value'); - ts.match('#Value (#WeekDay|#Month)').ifNo('#Money').tag('Date', 'value-date'); //may twenty five + if (found.Gerund === undefined) { + found.Gerund = _02Generic.Gerund(str); + } //'buzzed' - var vs = ts.match('#TextValue #TextValue'); - if (vs.found && vs.has('#Date')) { - vs.tag('#Date', 'textvalue-date'); - } //two days before + if (found.PastTense === undefined) { + found.PastTense = _02Generic.PastTense(str); + } //'buzzes' - ts.match('#Value #Duration #Conjunction').tag('Date', 'val-duration-conjunction'); //two years old + if (found.PresentTense === undefined) { + found.PresentTense = _02Generic.PresentTense(str); + } - ts.match('#Value #Duration old').unTag('Date', 'val-years-old'); - } //seasons + return found; + }; + var conjugate_1 = conjugate; + + //turn 'quick' into 'quickest' + var do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /oud$/, /...p$/]; + var dont_rules = [/ary$/]; + var irregulars = { + nice: 'nicest', + late: 'latest', + hard: 'hardest', + inner: 'innermost', + outer: 'outermost', + far: 'furthest', + worse: 'worst', + bad: 'worst', + good: 'best', + big: 'biggest', + large: 'largest' + }; + var transforms = [{ + reg: /y$/i, + repl: 'iest' + }, { + reg: /([aeiou])t$/i, + repl: '$1ttest' + }, { + reg: /([aeou])de$/i, + repl: '$1dest' + }, { + reg: /nge$/i, + repl: 'ngest' + }, { + reg: /([aeiou])te$/i, + repl: '$1test' + }]; - if (ts.has(seasons)) { - ts.match("".concat(preps, "? ").concat(thisNext, " ").concat(seasons)).tag('Date', 'thisNext-season'); - ts.match("the? ".concat(sections, " of ").concat(seasons)).tag('Date', 'section-season'); - } //rest-dates + var to_superlative = function to_superlative(str) { + //irregulars + if (irregulars.hasOwnProperty(str)) { + return irregulars[str]; + } //known transforms - if (ts.has('#Date')) { - //june the 5th - ts.match('#Date the? #Ordinal').tag('Date', 'correction-date'); //last month + for (var i = 0; i < transforms.length; i++) { + if (transforms[i].reg.test(str)) { + return str.replace(transforms[i].reg, transforms[i].repl); + } + } //dont-rules - ts.match("".concat(thisNext, " #Date")).tag('Date', 'thisNext-date'); //by 5 March - ts.match('due? (by|before|after|until) #Date').tag('Date', 'by-date'); //tomorrow before 3 + for (var _i = 0; _i < dont_rules.length; _i++) { + if (dont_rules[_i].test(str) === true) { + return null; + } + } //do-rules - ts.match('#Date (by|before|after|at|@|about) #Cardinal').not('^#Date').tag('Time', 'date-before-Cardinal'); //saturday am - ts.match('#Date (am|pm)').term(1).unTag('Verb').unTag('Copula').tag('Time', 'date-am'); - ts.match('(last|next|this|previous|current|upcoming|coming|the) #Date').tag('Date', 'next-feb'); - ts.match('#Date (#Preposition|to) #Date').tag('Date', 'date-prep-date'); //start of june + for (var _i2 = 0; _i2 < do_rules.length; _i2++) { + if (do_rules[_i2].test(str) === true) { + if (str.charAt(str.length - 1) === 'e') { + return str + 'st'; + } - ts.match("the? ".concat(sections, " of #Date")).tag('Date', 'section-of-date'); //fifth week in 1998 + return str + 'est'; + } + } - ts.match('#Ordinal #Duration in #Date').tag('Date', 'duration-in-date'); //early in june + return str + 'est'; + }; - ts.match('(early|late) (at|in)? the? #Date').tag('Time', 'early-evening'); - } //year/cardinal tagging + var toSuperlative = to_superlative; + + //turn 'quick' into 'quickly' + var do_rules$1 = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /old$/, /oud$/, /e[ae]p$/]; + var dont_rules$1 = [/ary$/, /ous$/]; + var irregulars$1 = { + grey: 'greyer', + gray: 'grayer', + green: 'greener', + yellow: 'yellower', + red: 'redder', + good: 'better', + well: 'better', + bad: 'worse', + sad: 'sadder', + big: 'bigger' + }; + var transforms$1 = [{ + reg: /y$/i, + repl: 'ier' + }, { + reg: /([aeiou])t$/i, + repl: '$1tter' + }, { + reg: /([aeou])de$/i, + repl: '$1der' + }, { + reg: /nge$/i, + repl: 'nger' + }]; + var to_comparative = function to_comparative(str) { + //known-irregulars + if (irregulars$1.hasOwnProperty(str)) { + return irregulars$1[str]; + } //known-transforms - if (ts.has('#Cardinal')) { - var v = ts.match("#Date #Value #Cardinal").lastTerm(); - tagYear(v, 'date-value-year'); //scoops up a bunch - v = ts.match("#Date+ #Cardinal").lastTerm(); - tagYear(v, 'date-year'); //feb 8 2018 + for (var i = 0; i < transforms$1.length; i++) { + if (transforms$1[i].reg.test(str) === true) { + return str.replace(transforms$1[i].reg, transforms$1[i].repl); + } + } //dont-patterns - v = ts.match("#Month #Value #Cardinal").lastTerm(); - tagYear(v, 'month-value-year'); //feb 8 to 10th 2018 - v = ts.match("#Month #Value to #Value #Cardinal").lastTerm(); - tagYear(v, 'month-range-year'); //in 1998 + for (var _i = 0; _i < dont_rules$1.length; _i++) { + if (dont_rules$1[_i].test(str) === true) { + return null; + } + } //do-patterns - v = ts.match("(in|of|by|during|before|starting|ending|for|year) #Cardinal").lastTerm(); - tagYear(v, 'in-year'); //q2 2009 - v = ts.match('(q1|q2|q3|q4) [#Cardinal]'); - tagYear(v, 'in-year'); //2nd quarter 2009 + for (var _i2 = 0; _i2 < do_rules$1.length; _i2++) { + if (do_rules$1[_i2].test(str) === true) { + return str + 'er'; + } + } //easy-one - v = ts.match('#Ordinal quarter [#Cardinal]'); - tagYear(v, 'in-year'); //in the year 1998 - v = ts.match('the year [#Cardinal]'); - tagYear(v, 'in-year'); //it was 1998 + if (/e$/.test(str) === true) { + return str + 'r'; + } - v = ts.match('it (is|was) [#Cardinal]'); - tagYearSafer(v, 'in-year'); //was 1998 and... + return str + 'er'; + }; - v = ts.match("#Cardinal !#Plural").firstTerm(); - tagYearSafer(v, 'year-unsafe'); - } //another pass at dates.. + var toComparative = to_comparative; + var fns$1 = { + toSuperlative: toSuperlative, + toComparative: toComparative + }; + /** conjugate an adjective into other forms */ - if (ts.has('#Date')) { - //time: - if (ts.has('#Time')) { - ts.match('#Cardinal #Time').not('#Year').tag('Time', 'value-time'); - ts.match('(by|before|after|at|@|about) #Time').tag('Time', 'preposition-time'); //2pm est + var conjugate$1 = function conjugate(w) { + var res = {}; // 'greatest' - ts.match('#Time (eastern|pacific|central|mountain)').term(1).tag('Time', 'timezone'); - ts.match('#Time (est|pst|gmt)').term(1).tag('Time', 'timezone abbr'); - } //fix over-greedy + var sup = fns$1.toSuperlative(w); + if (sup) { + res.Superlative = sup; + } // 'greater' - var date = ts.match('#Date+').splitOn('Clause'); - if (date.has('(#Year|#Time)') === false) { - //12 february 12 - date.match('#Value (#Month|#Weekday) #Value').lastTerm().unTag('Date'); - } - } + var comp = fns$1.toComparative(w); - return ts; -}; - -module.exports = datePass; - -},{}],110:[function(_dereq_,module,exports){ -'use strict'; //auxiliary verbs are extra verbs beside the main ones -// "[will be] going" - etc. - -var Auxiliary = { - 'do': true, - 'don\'t': true, - 'does': true, - 'doesn\'t': true, - 'will': true, - 'wont': true, - 'won\'t': true, - 'have': true, - 'haven\'t': true, - 'had': true, - 'hadn\'t': true, - 'not': true -}; - -var corrections = function corrections(ts) { - //set verbs as auxillaries - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; - - if (Auxiliary[t.normal] || Auxiliary[t.silent_term]) { - var next = ts.terms[i + 1]; //if next word is a verb - - if (next && (next.tags.Verb || next.tags.Adverb || next.tags.Negative)) { - t.tag('Auxiliary', 'corrections-Auxiliary'); - continue; - } + if (comp) { + res.Comparative = comp; } - } - return ts; -}; + return res; + }; -module.exports = corrections; + var adjectives = conjugate$1; + + /** patterns for turning 'bus' to 'buses'*/ + var suffixes$1 = { + a: [[/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae'], [/([ti])a$/i, '$1a']], + e: [[/(kn|l|w)ife$/i, '$1ives'], [/(hive)$/i, '$1s'], [/([m|l])ouse$/i, '$1ice'], [/([m|l])ice$/i, '$1ice']], + f: [[/^(dwar|handkerchie|hoo|scar|whar)f$/i, '$1ves'], [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)f$/i, '$1ves']], + i: [[/(octop|vir)i$/i, '$1i']], + m: [[/([ti])um$/i, '$1a']], + n: [[/^(oxen)$/i, '$1']], + o: [[/(al|ad|at|er|et|ed|ad)o$/i, '$1oes']], + s: [[/(ax|test)is$/i, '$1es'], [/(alias|status)$/i, '$1es'], [/sis$/i, 'ses'], [/(bu)s$/i, '$1ses'], [/(sis)$/i, 'ses'], [/^(?!talis|.*hu)(.*)man$/i, '$1men'], [/(octop|vir|radi|nucle|fung|cact|stimul)us$/i, '$1i']], + x: [[/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices'], [/^(ox)$/i, '$1en']], + y: [[/([^aeiouy]|qu)y$/i, '$1ies']], + z: [[/(quiz)$/i, '$1zes']] + }; + var _rules = suffixes$1; -},{}],111:[function(_dereq_,module,exports){ -'use strict'; // 'not' is sometimes a verb, sometimes an adjective + var addE = /(x|ch|sh|s|z)$/; -var negation_step = function negation_step(ts) { - for (var i = 0; i < ts.length; i++) { - var t = ts.get(i); + var trySuffix = function trySuffix(str) { + var c = str[str.length - 1]; - if (t.normal === 'not' || t.silent_term === 'not') { - //find the next verb/adjective - for (var o = i + 1; o < ts.length; o++) { - if (ts.get(o).tags.Verb) { - t.tag('VerbPhrase', 'negate-verb'); - break; - } + if (_rules.hasOwnProperty(c) === true) { + for (var i = 0; i < _rules[c].length; i += 1) { + var reg = _rules[c][i][0]; - if (ts.get(o).tags.Adjective) { - t.tag('AdjectivePhrase', 'negate-adj'); - break; + if (reg.test(str) === true) { + return str.replace(reg, _rules[c][i][1]); } } } - } - return ts; -}; - -module.exports = negation_step; - -},{}],112:[function(_dereq_,module,exports){ -'use strict'; //-types of comma-use- -// PlaceComma - Hollywood, California -// List - cool, fun, and great. -// ClauseEnd - if so, we do. -//like Toronto, Canada + return null; + }; + /** Turn a singular noun into a plural + * assume the given string is singular + */ -var isPlaceComma = function isPlaceComma(ts, i) { - var t = ts.terms[i]; - var nextTerm = ts.terms[i + 1]; //'australia, canada' is a list - if (nextTerm && t.tags.Place && !t.tags.Country && nextTerm.tags.Country) { - return true; - } + var pluralize = function pluralize() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var world = arguments.length > 1 ? arguments[1] : undefined; + var irregulars = world.irregulars.nouns; // check irregulars list - return false; -}; //adj, noun, or verb + if (irregulars.hasOwnProperty(str)) { + return irregulars[str]; + } //we have some rules to try-out -var mainTag = function mainTag(t) { - if (t.tags.Adjective) { - return 'Adjective'; - } + var plural = trySuffix(str); - if (t.tags.Noun) { - return 'Noun'; - } + if (plural !== null) { + return plural; + } //like 'church' - if (t.tags.Verb) { - return 'Verb'; - } - if (t.tags.Value) { - return 'Value'; - } + if (addE.test(str)) { + return str + 'es'; + } // ¯\_(ツ)_/¯ - return null; -}; //take the first term with a comma, and test to the right. -//the words with a comma must be the same pos. + return str + 's'; + }; -var isList = function isList(ts, i) { - var start = i; - var tag = mainTag(ts.terms[i]); //ensure there's a following comma, and its the same pos - //then a Conjunction + var toPlural = pluralize; - var sinceComma = 0; - var count = 0; - var hasConjunction = false; + //patterns for turning 'dwarves' to 'dwarf' + var _rules$1 = [[/([^v])ies$/i, '$1y'], [/ises$/i, 'isis'], [/(kn|[^o]l|w)ives$/i, '$1ife'], [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i, '$1f'], [/^(dwar|handkerchie|hoo|scar|whar)ves$/i, '$1f'], [/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a'], [/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i, '$1us'], [/(buffal|tomat|tornad)(oes)$/i, '$1o'], // [/(analy|diagno|parenthe|progno|synop|the)ses$/i, '$1sis'], + [/(..[aeiou]s)es$/i, '$1'], [/(vert|ind|cort)(ices)$/i, '$1ex'], [/(matr|append)(ices)$/i, '$1ix'], [/(x|ch|ss|sh|z|o)es$/i, '$1'], [/men$/i, 'man'], [/(n)ews$/i, '$1ews'], [/([ti])a$/i, '$1um'], [/([^aeiouy]|qu)ies$/i, '$1y'], [/(s)eries$/i, '$1eries'], [/(m)ovies$/i, '$1ovie'], [/([m|l])ice$/i, '$1ouse'], [/(cris|ax|test)es$/i, '$1is'], [/(alias|status)es$/i, '$1'], [/(ss)$/i, '$1'], [/(ics)$/i, '$1'], [/s$/i, '']]; - for (i = i + 1; i < ts.terms.length; i++) { - var t = ts.terms[i]; //are we approaching the end + var invertObj = function invertObj(obj) { + return Object.keys(obj).reduce(function (h, k) { + h[obj[k]] = k; + return h; + }, {}); + }; - if (count > 0 && t.tags.Conjunction) { - hasConjunction = true; - continue; - } //found one, + var toSingular = function toSingular(str, world) { + var irregulars = world.irregulars.nouns; + var invert = invertObj(irregulars); // check irregulars list + if (invert.hasOwnProperty(str)) { + return invert[str]; + } // go through our regexes - if (t.tags[tag]) { - //looks good. keep it going - if (t.tags.Comma) { - count += 1; - sinceComma = 0; - continue; - } - if (count > 0 && hasConjunction) { - //is this the end of the list? - ts.slice(start, i).tag('List'); - return true; + for (var i = 0; i < _rules$1.length; i++) { + if (_rules$1[i][0].test(str) === true) { + str = str.replace(_rules$1[i][0], _rules$1[i][1]); + return str; } } - sinceComma += 1; //have we gone too far without a comma? + return str; + }; - if (sinceComma > 5) { - return false; - } //this one, not a clause.. + var toSingular_1 = toSingular; + + //rules for turning a verb into infinitive form + var rules = { + Participle: [{ + reg: /own$/i, + to: 'ow' + }, { + reg: /(.)un([g|k])$/i, + to: '$1in$2' + }], + Actor: [{ + reg: /(er)er$/i, + to: '$1' + }], + PresentTense: [{ + reg: /(..)(ies)$/i, + to: '$1y' + }, { + reg: /(tch|sh)es$/i, + to: '$1' + }, { + reg: /(ss|zz)es$/i, + to: '$1' + }, { + reg: /([tzlshicgrvdnkmu])es$/i, + to: '$1e' + }, { + reg: /(n[dtk]|c[kt]|[eo]n|i[nl]|er|a[ytrl])s$/i, + to: '$1' + }, { + reg: /(ow)s$/i, + to: '$1' + }, { + reg: /(op)s$/i, + to: '$1' + }, { + reg: /([eirs])ts$/i, + to: '$1t' + }, { + reg: /(ll)s$/i, + to: '$1' + }, { + reg: /(el)s$/i, + to: '$1' + }, { + reg: /(ip)es$/i, + to: '$1e' + }, { + reg: /ss$/i, + to: 'ss' + }, { + reg: /s$/i, + to: '' + }], + Gerund: [{ + reg: /pping$/i, + to: 'p' + }, { + reg: /lling$/i, + to: 'll' + }, { + reg: /tting$/i, + to: 't' + }, { + reg: /dding$/i, + to: 'd' + }, { + reg: /ssing$/i, + to: 'ss' + }, { + reg: /(..)gging$/i, + to: '$1g' + }, { + reg: /([^aeiou])ying$/i, + to: '$1y' + }, { + reg: /([^ae]i.)ing$/i, + to: '$1e' + }, { + reg: /(ea.)ing$/i, + to: '$1' + }, { + reg: /(u[rtcb]|[bdtpkg]l|n[cg]|a[gdkvtc]|[ua]s|[dr]g|yz|o[rlsp]|cre)ing$/i, + to: '$1e' + }, { + reg: /(ch|sh)ing$/i, + to: '$1' + }, { + reg: /(..)ing$/i, + to: '$1' + }], + PastTense: [{ + reg: /(ued)$/i, + to: 'ue' + }, { + reg: /a([^aeiouy])ed$/i, + to: 'a$1e' + }, { + reg: /([aeiou]zz)ed$/i, + to: '$1' + }, { + reg: /(e|i)lled$/i, + to: '$1ll' + }, { + reg: /(.)(sh|ch)ed$/i, + to: '$1$2' + }, { + reg: /(tl|gl)ed$/i, + to: '$1e' + }, { + reg: /(um?pt?)ed$/i, + to: '$1' + }, { + reg: /(ss)ed$/i, + to: '$1' + }, { + reg: /pped$/i, + to: 'p' + }, { + reg: /tted$/i, + to: 't' + }, { + reg: /(..)gged$/i, + to: '$1g' + }, { + reg: /(..)lked$/i, + to: '$1lk' + }, { + reg: /([^aeiouy][aeiou])ked$/i, + to: '$1ke' + }, { + reg: /(.[aeiou])led$/i, + to: '$1l' + }, { + reg: /(..)(h|ion|n[dt]|ai.|[cs]t|pp|all|ss|tt|int|ail|ld|en|oo.|er|k|pp|w|ou.|rt|ght|rm)ed$/i, + to: '$1$2' + }, { + reg: /(.ut)ed$/i, + to: '$1e' + }, { + reg: /(.pt)ed$/i, + to: '$1' + }, { + reg: /(us)ed$/i, + to: '$1e' + }, { + reg: /(..[^aeiouy])ed$/i, + to: '$1e' + }, { + reg: /(..)ied$/i, + to: '$1y' + }, { + reg: /(.o)ed$/i, + to: '$1o' + }, { + reg: /(..i)ed$/i, + to: '$1' + }, { + reg: /(.a[^aeiou])ed$/i, + to: '$1' + }, { + reg: /([rl])ew$/i, + to: '$1ow' + }, { + reg: /([pl])t$/i, + to: '$1t' + }] + }; + var _transform = rules; + + var guessVerb = { + Gerund: ['ing'], + Actor: ['erer'], + Infinitive: ['ate', 'ize', 'tion', 'rify', 'then', 'ress', 'ify', 'age', 'nce', 'ect', 'ise', 'ine', 'ish', 'ace', 'ash', 'ure', 'tch', 'end', 'ack', 'and', 'ute', 'ade', 'ock', 'ite', 'ase', 'ose', 'use', 'ive', 'int', 'nge', 'lay', 'est', 'ain', 'ant', 'ent', 'eed', 'er', 'le', 'own', 'unk', 'ung', 'en'], + PastTense: ['ed', 'lt', 'nt', 'pt', 'ew', 'ld'], + PresentTense: ['rks', 'cks', 'nks', 'ngs', 'mps', 'tes', 'zes', 'ers', 'les', 'acks', 'ends', 'ands', 'ocks', 'lays', 'eads', 'lls', 'els', 'ils', 'ows', 'nds', 'ays', 'ams', 'ars', 'ops', 'ffs', 'als', 'urs', 'lds', 'ews', 'ips', 'es', 'ts', 'ns'] + }; //flip it into a lookup object + + guessVerb = Object.keys(guessVerb).reduce(function (h, k) { + guessVerb[k].forEach(function (a) { + return h[a] = k; + }); + return h; + }, {}); + var _guess = guessVerb; + /** it helps to know what we're conjugating from */ - if (tag === 'Value') { - return true; - } - } + var guessTense = function guessTense(str) { + var three = str.substr(str.length - 3); - return false; -}; + if (_guess.hasOwnProperty(three) === true) { + return _guess[three]; + } -var commaStep = function commaStep(ts) { - //tag the correct punctuation forms - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; - var punct = t.getPunctuation(); + var two = str.substr(str.length - 2); - if (punct === ',') { - t.tag('Comma', 'comma-step'); - continue; + if (_guess.hasOwnProperty(two) === true) { + return _guess[two]; } - if (punct === ';' || punct === ':') { - t.tag('ClauseEnd', 'clause-punt'); - continue; - } //support elipses + var one = str.substr(str.length - 1); + if (one === 's') { + return 'PresentTense'; + } - if (t.whitespace.after.match(/^\.\./)) { - t.tag('ClauseEnd', 'clause-elipses'); - continue; - } //support ' - ' clause - + return null; + }; - if (ts.terms[i + 1] && ts.terms[i + 1].whitespace.before.match(/ - /)) { - t.tag('ClauseEnd', 'hypen-clause'); - continue; - } - } //disambiguate the commas now + var toInfinitive = function toInfinitive(str, world, tense) { + if (!str) { + return ''; + } //1. look at known irregulars - for (var _i = 0; _i < ts.terms.length; _i++) { - var _t = ts.terms[_i]; + if (world.words.hasOwnProperty(str) === true) { + var irregs = world.irregulars.verbs; + var keys = Object.keys(irregs); - if (_t.tags.Comma) { - //if we already got it - if (_t.tags.List) { - continue; - } //like 'Hollywood, California' + for (var i = 0; i < keys.length; i++) { + var forms = Object.keys(irregs[keys[i]]); + for (var o = 0; o < forms.length; o++) { + if (str === irregs[keys[i]][forms[o]]) { + return keys[i]; + } + } + } + } // give'r! - if (isPlaceComma(ts, _i)) { - continue; - } //like 'cold, wet hands' + tense = tense || guessTense(str); - var found = isList(ts, _i); //otherwise, it's a phrasal comma, like 'you must, if you think so' + if (tense && _transform[tense]) { + for (var _i = 0; _i < _transform[tense].length; _i++) { + var rule = _transform[tense][_i]; - if (!found) { - _t.tag('ClauseEnd', 'phrasal-comma'); + if (rule.reg.test(str) === true) { + return str.replace(rule.reg, rule.to); + } } } - } - return ts; -}; - -module.exports = commaStep; - -},{}],113:[function(_dereq_,module,exports){ -'use strict'; - -var quotemarks = { - "\"": { - close: "\"", - tag: 'StraightDoubleQuotes' - }, - "\uFF02": { - close: "\uFF02", - tag: 'StraightDoubleQuotesWide' - }, - "'": { - close: "'", - tag: 'StraightSingleQuotes' - }, - "\u201C": { - close: "\u201D", - tag: 'CommaDoubleQuotes' - }, - "\u2018": { - close: "\u2019", - tag: 'CommaSingleQuotes' - }, - "\u201F": { - close: "\u201D", - tag: 'CurlyDoubleQuotesReversed' - }, - "\u201B": { - close: "\u2019", - tag: 'CurlySingleQuotesReversed' - }, - "\u201E": { - close: "\u201D", - tag: 'LowCurlyDoubleQuotes' - }, - "\u2E42": { - close: "\u201D", - tag: 'LowCurlyDoubleQuotesReversed' - }, - "\u201A": { - close: "\u2019", - tag: 'LowCurlySingleQuotes' - }, - "\xAB": { - close: "\xBB", - tag: 'AngleDoubleQuotes' - }, - "\u2039": { - close: "\u203A", - tag: 'AngleSingleQuotes' - }, - // Prime 'non quotation' - "\u2035": { - close: "\u2032", - tag: 'PrimeSingleQuotes' - }, - "\u2036": { - close: "\u2033", - tag: 'PrimeDoubleQuotes' - }, - "\u2037": { - close: "\u2034", - tag: 'PrimeTripleQuotes' - }, - // Prime 'quotation' variation - "\u301D": { - close: "\u301E", - tag: 'PrimeDoubleQuotes' - }, - "`": { - close: "\xB4", - tag: 'PrimeSingleQuotes' - }, - "\u301F": { - close: "\u301E", - tag: 'LowPrimeDoubleQuotesReversed' - } -}; // Convert the close quote to a regex. + return str; + }; -Object.keys(quotemarks).forEach(function (open) { - quotemarks[open].regex = new RegExp(quotemarks[open].close + '[;:,.]*'); - quotemarks[open].open = open; -}); // Improve open match detection. + var toInfinitive_1 = toInfinitive; -var startQuote = new RegExp('[' + Object.keys(quotemarks).join('') + ']'); //tag a inline quotation as such + var irregulars$2 = { + nouns: plurals, + verbs: conjugations_1 + }; //these behaviours are configurable & shared across some plugins -var quotation_step = function quotation_step(ts) { - // Isolate the text so it doesn't change. - var terms = ts.terms.slice(0); //.map(e => e.text); + var transforms$2 = { + conjugate: conjugate_1, + adjectives: adjectives, + toPlural: toPlural, + toSingular: toSingular_1, + toInfinitive: toInfinitive_1 + }; + var _isVerbose = false; + /** all configurable linguistic data */ + + var World = + /*#__PURE__*/ + function () { + function World() { + _classCallCheck(this, World); + + // quiet these properties from a console.log + Object.defineProperty(this, 'words', { + enumerable: false, + value: misc$1, + writable: true + }); + Object.defineProperty(this, 'hasCompound', { + enumerable: false, + value: {}, + writable: true + }); + Object.defineProperty(this, 'irregulars', { + enumerable: false, + value: irregulars$2, + writable: true + }); + Object.defineProperty(this, 'tags', { + enumerable: false, + value: Object.assign({}, tags), + writable: true + }); + Object.defineProperty(this, 'transforms', { + enumerable: false, + value: transforms$2, + writable: true + }); + Object.defineProperty(this, 'taggers', { + enumerable: false, + value: [], + writable: true + }); // add our compressed data to lexicon - for (var i = 0; i < terms.length; i++) { - var t = ts.terms[i]; + this.unpackWords(_data); // add our irregulars to lexicon - if (startQuote.test(t.whitespace.before)) { - // Get the match and split it into groups - var quotes = t.whitespace.before.match(startQuote).shift().split(''); // Get close and tag info. + this.addIrregulars(); // cache our abbreviations for our sentence-parser - quotes = quotes.map(function (mark) { - return quotemarks[mark]; - }); // Look for the ending + Object.defineProperty(this, 'cache', { + enumerable: false, + value: { + abbreviations: this.getByTag('Abbreviation') + } + }); + } + /** more logs for debugging */ - for (var o = 0; o < ts.terms.length; o++) { - // max-length don't go-on forever - if (!terms[i + o] || o > 28) { - break; - } // Find the close. + _createClass(World, [{ + key: "verbose", + value: function verbose(bool) { + _isVerbose = bool; + return this; + } + }, { + key: "isVerbose", + value: function isVerbose() { + return _isVerbose; + } + /** get all terms in our lexicon with this tag */ - var index = -1; + }, { + key: "getByTag", + value: function getByTag(tag) { + var lex = this.words; + var res = {}; + var words = Object.keys(lex); - for (var qi = 0; qi < quotes.length; qi += 1) { - if (quotes[qi].regex.test(terms[i + o].whitespace.after) === true) { - index = qi; - break; + for (var i = 0; i < words.length; i++) { + if (typeof lex[words[i]] === 'string') { + if (lex[words[i]] === tag) { + res[words[i]] = true; + } + } else if (lex[words[i]].some(function (t) { + return t === tag; + })) { + res[words[i]] = true; } } - if (index !== -1) { - // Remove the found - var quote = quotes.splice(index, 1).pop(); - - if (quote.regex.test(ts.terms[i + o].normal)) { - ts.terms[i + o].whitespace.after.replace(quote.regex, ''); - } // Tag the things. + return res; + } + /** augment our lingustic data with new data */ + }, { + key: "unpackWords", + value: function unpackWords(lex) { + var tags = Object.keys(lex); - t.tag('StartQuotation', 'quotation_open'); - ts.terms[i + o].tag('EndQuotation', 'quotation_close'); - ts.slice(i, i + o + 1).tag('Quotation', 'quotation_step'); // Compensate for multiple close quotes ('"Really"') + for (var i = 0; i < tags.length; i++) { + var words = Object.keys(efrtUnpack_min(lex[tags[i]])); - o -= 1; + for (var w = 0; w < words.length; w++) { + addWords.addWord(words[w], tags[i], this.words); // do some fancier stuff - if (!quotes.length) { - break; + addWords.addMore(words[w], tags[i], this); } } } - } - } + /** put new words into our lexicon, properly */ - return ts; -}; - -module.exports = quotation_step; - -},{}],114:[function(_dereq_,module,exports){ -'use strict'; //decide if an apostrophe s is a contraction or not -// 'spencer's nice' -> 'spencer is nice' -// 'spencer's house' -> 'spencer's house' - -var singleQuotes = [["'", "'"], // Straight Single Quotes -["\u2018", "\u2019"], // Comma Single Quotes -["\u201B", "\u2019"], // Curly Single Quotes Reversed -["\u201A", "\u2019"], // Low Curly Single Quotes -["\u2035", "\u2032"], // Prime Single Quotes Alt -["`", "\xB4"] // Prime Single Quotes -]; //these are always contractions - -var blacklist = ['it\'s', 'that\'s']; // Get all types of single quote. - -var apostrophes = '\'‘’‛‚‵′`´'; -var afterWord = new RegExp('([a-z]s[' + apostrophes + '])\\W*$'); // [^\w]* match 0 or more of any char that is NOT alphanumeric - -var hasApostrophe = new RegExp('[' + apostrophes + ']'); -var trailers = new RegExp('[^' + apostrophes + '\\w]+$'); -var quoteRegex = {}; -singleQuotes.forEach(function (quote) { - quoteRegex[quote[0]] = new RegExp(quote[1] + '[^' + quote[1] + '\\w]*$'); -}); // Compensate for different `'`s in the blacklist - -blacklist.map(function (item) { - return new RegExp(item.replace('\'', '[' + apostrophes + ']')); -}); // A possessive means `'s` describes ownership -// Not a contraction, like it's -> `it is` - -var is_possessive = function is_possessive(terms, text, index) { - var thisWord = terms.get(index); - var nextWord = terms.get(index + 1); - var stepWord = terms.get(index + 2); //our booleans: - // `blacklist` are always contractions, not possessive - - var inBlacklist = blacklist.map(function (r) { - return text.match(r); - }).find(function (m) { - return m; - }); // If no apostrophe s or s apostrophe + }, { + key: "addWords", + value: function addWords$1(obj) { + var keys = Object.keys(obj); - var endTick = hasApostrophe.test(thisWord.whitespace.after); // "spencers'" - this is always possessive - eg "flanders'" + for (var i = 0; i < keys.length; i++) { + var word = keys[i].toLowerCase(); + addWords.addWord(word, obj[keys[i]], this.words); // do some fancier stuff - var hasPronoun = thisWord.tags.Pronoun; + addWords.addMore(word, obj[keys[i]], this); + } + } + }, { + key: "addIrregulars", + value: function addIrregulars() { + addIrregulars_1(this); - if (inBlacklist || hasPronoun || !endTick) { - return false; - } + return this; + } + /** extend the compromise tagset */ - if (afterWord.test(text) || nextWord === undefined) { - return true; - } // Next word is 'house' + }, { + key: "addTags", + value: function addTags(tags) { + tags = Object.assign({}, tags); + this.tags = Object.assign(this.tags, tags); // calculate graph implications for the new tags + this.tags = inference(this.tags); + return this; + } + /** call methods after tagger runs */ - if (nextWord.tags.Noun === true || thisWord.tags.ClauseEnd === true) { - return true; - } //rocket's red glare + }, { + key: "postProcess", + value: function postProcess(fn) { + this.taggers.push(fn); + return this; + } + /** helper method for logging + debugging */ + + }, { + key: "stats", + value: function stats() { + return { + words: Object.keys(this.words).length, + plurals: Object.keys(this.irregular.plurals).length, + conjugations: Object.keys(this.irregular.conjugations).length, + compounds: Object.keys(this.hasCompound).length, + postProcessors: this.taggers.length + }; + } + }]); + return World; + }(); // ¯\_(:/)_/¯ + + + var clone$1 = function clone(obj) { + return JSON.parse(JSON.stringify(obj)); + }; + /** produce a deep-copy of all lingustic data */ - if (stepWord !== undefined && nextWord.tags.Adjective && stepWord.tags.Noun) { - return true; - } - return false; -}; // Tag each term as possessive, if it should + World.prototype.clone = function () { + var w2 = new World(); // these are simple to copy: + w2.words = Object.assign({}, this.words); + w2.hasCompound = Object.assign({}, this.hasCompound); //these ones are nested: -var possessiveStep = function possessiveStep(ts) { - var expectingClosers = []; + w2.irregulars = clone$1(this.irregulars); + w2.tags = clone$1(this.tags); // these are functions - for (var i = 0; i < ts.length; i++) { - var term = ts.get(i); - var text = term.text; // First detect open quotes before detecting apostrophes + w2.transforms = this.transforms; + w2.taggers = this.taggers; + return w2; + }; - if (typeof quoteRegex[text[0]] !== 'undefined') { - // Add the expected closing quotes to our inspection array. - expectingClosers[expectingClosers.length] = quoteRegex[text[0]]; - text = text.slice(1); - } // Pre checking for quotes. e.g: Carlos'.’. -> Carlos'.’ + var World_1 = World; + var _01Utils$1 = createCommonjsModule(function (module, exports) { + // const cache = require('./_setCache') - text = text.replace(trailers, ''); // If the string ends with an expected closer. + /** return the root, first document */ + exports.all = function () { + return this.parents()[0] || this; + }; + /** return the previous result */ - var closer = -1; - for (var qi = 0; qi < expectingClosers.length; qi += 1) { - if (expectingClosers[qi].test(text) === true) { - closer = qi; - break; + exports.parent = function () { + if (this.from) { + return this.from; } - } - if (closer !== -1) { - text = text.replace(expectingClosers[closer], ''); - delete expectingClosers[closer]; - } // Post checking for quotes. e.g: Carlos'. -> Carlos' + return this; + }; + /** return a list of all previous results */ - text = text.replace(trailers, ''); + exports.parents = function (n) { + var arr = []; - if (is_possessive(ts, text, i)) { - // If it's not already a noun, co-erce it to one - if (!term.tags['Noun']) { - term.tag('Noun', 'possessive_pass'); - } + var addParent = function addParent(doc) { + if (doc.from) { + arr.push(doc.from); + addParent(doc.from); + } + }; - term.tag('Possessive', 'possessive_pass'); // If it's been detected as a `Contraction` + addParent(this); + arr = arr.reverse(); - if (term.tags.Contraction === true) { - // Remove the `Contraction` tag and silent_terms - term.unTag('Contraction'); - ts.terms.splice(i + 1, 1); - term.silent_term = ''; + if (typeof n === 'number') { + return arr[n]; } - } - } - return ts; -}; + return arr; + }; + /** deep-copy the document, so that no references remain */ -module.exports = possessiveStep; -},{}],115:[function(_dereq_,module,exports){ -'use strict'; //tag 'FBI' as letters-representing-words. -//we guess if letters are an acronym in the Term class. + exports.clone = function (doShallow) { + var list = this.list.map(function (ts) { + return ts.clone(doShallow); + }); + var tmp = this.buildFrom(list); + return tmp; + }; + /** how many seperate terms does the document have? */ -var acronym_step = function acronym_step(ts) { - ts.terms.forEach(function (t) { - if (t.isAcronym()) { - t.tag('Acronym', 'acronym-step'); - } - }); - return ts; -}; -module.exports = acronym_step; + exports.wordCount = function () { + return this.list.reduce(function (count, p) { + count += p.wordCount(); + return count; + }, 0); + }; -},{}],116:[function(_dereq_,module,exports){ -'use strict'; //sort-out things like 'theresa may', or 'will jones'. + exports.wordcount = exports.wordCount; + /** turn on logging for decision-debugging */ + // exports.verbose = function(bool) { + // if (bool === undefined) { + // bool = true + // } + // this.world.verbose = bool + // } -var person_step = function person_step(ts) { - //mr Putin - ts.match('(mr|mrs|ms|dr) (#TitleCase|#Possessive)+').tag('#Person', 'mr-putin'); //a bunch of ambiguous first names + /** freeze the current state of the document, for speed-purposes*/ - var maybeNoun = '(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)'; + exports.cache = function (options) { + var _this = this; - if (ts.has(maybeNoun)) { - ts.match('(#Determiner|#Adverb|#Pronoun|#Possessive) [' + maybeNoun + ']').tag('Noun', 'the-ray'); - ts.match(maybeNoun + ' (#Person|#Acronym|#TitleCase)').canBe('#Person').tag('Person', 'ray-smith'); - } //verbs or people-names + options = options || {}; + this.list.forEach(function (p) { + var words = {}; + p.cache = p.cache || {}; + p.cache.terms = p.cache.terms || p.terms(); // cache all the terms + p.cache.terms.forEach(function (t) { + words[t.clean] = true; + words[t.reduced] = true; + words[t.text.toLowerCase()] = true; - var maybeVerb = '(pat|wade|ollie|will|rob|buck|bob|mark|jack)'; + if (t.implicit) { + words[t.implicit] = true; + } - if (ts.has(maybeVerb)) { - ts.match('(#Modal|#Adverb) [' + maybeVerb + ']').tag('Verb', 'would-mark'); - ts.match(maybeVerb + ' (#Person|#TitleCase)').tag('Person', 'rob-smith'); - } //adjectives or people-names + if (t.root) { + words[t.root] = true; + } + if (t.alias !== undefined) { + words = Object.assign(words, t.alias); + } - var maybeAdj = '(misty|rusty|dusty|rich|randy)'; + if (options.root) { + t.setRoot(_this.world); + words[t.root] = true; + } + }); + delete words['']; + p.cache.words = words; + }); + return this; + }; + /** un-freezes the current state of the document, so it may be transformed */ - if (ts.has(maybeAdj)) { - ts.match('#Adverb [' + maybeAdj + ']').tag('Adjective', 'really-rich'); - ts.match(maybeAdj + ' (#Person|#TitleCase)').tag('Person', 'randy-smith'); - } //dates as people names + exports.uncache = function () { + this.list.forEach(function (p) { + p.cache = {}; + }); // do parents too? - var maybeDate = '(april|june|may|jan|august|eve)'; + this.parents().forEach(function (doc) { + doc.list.forEach(function (p) { + p.cache = {}; + }); + }); + return this; + }; + }); + var _01Utils_1 = _01Utils$1.all; + var _01Utils_2 = _01Utils$1.parent; + var _01Utils_3 = _01Utils$1.parents; + var _01Utils_4 = _01Utils$1.clone; + var _01Utils_5 = _01Utils$1.wordCount; + var _01Utils_6 = _01Utils$1.wordcount; + var _01Utils_7 = _01Utils$1.cache; + var _01Utils_8 = _01Utils$1.uncache; + + var _02Accessors = createCommonjsModule(function (module, exports) { + /** use only the first result(s) */ + exports.first = function (n) { + if (n === undefined) { + return this.get(0); + } - if (ts.has(maybeDate)) { - ts.match(String(maybeDate) + ' (#Person|#TitleCase)').canBe('#Person').tag('Person', 'june-smith'); - ts.match('(in|during|on|by|before|#Date) [' + maybeDate + ']').canBe('#Date').tag('Date', 'in-june'); - ts.match(maybeDate + ' (#Date|#Value)').canBe('#Date').tag('Date', 'june-5th'); - } //place-names as people-names + return this.slice(0, n); + }; + /** use only the last result(s) */ - var maybePlace = '(paris|alexandria|houston|kobe|salvador|sydney)'; + exports.last = function (n) { + if (n === undefined) { + return this.get(this.list.length - 1); + } - if (ts.has(maybePlace)) { - ts.match('(in|near|at|from|to|#Place) [' + maybePlace + ']').canBe('#Place').tag('Place', 'in-paris'); - ts.match('[' + maybePlace + '] #Place').canBe('#Place').tag('Place', 'paris-france'); - ts.match('[' + maybePlace + '] #Person').canBe('#Person').tag('Person', 'paris-hilton'); - } //this one is tricky - - - if (ts.match('al')) { - ts.match('al (#Person|#TitleCase)').canBe('#Person').tag('#Person', 'al-borlen'); - ts.match('#TitleCase al #TitleCase').canBe('#Person').tag('#Person', 'arabic-al-arabic'); - } //ambiguous honorifics - - - ts.match('(private|general|major|corporal|lord|lady|secretary|premier) #Honorific? #Person').terms(0).tag('Honorific', 'ambg-honorifics'); //first general.. - - ts.match('(1st|2nd|first|second) #Honorific').terms(0).tag('Honorific', 'ordinal-honorific'); // let firstNames = '()'; - // let names = ts.match(firstNames); - // if (names.found) { - // //prolly not a name: - // if (ts.has('(#Determiner|#Adverb|#Pronoun|#Possessive) ' + firstNames)) { - // names.unTag('Person', 'the-bill'); - // } else { - // //probably a name here: - // let name = ts.match('(#Honorific|#Person) ' + firstNames); - // if (!name.found) { - // name = ts.match(firstNames + ' (#Person|#Honorific|#TitleCase)'); - // } - // if (name.found && name.has('(#Place|#Date|#Organization)') === false) { - // name.tag('Person', 'dr-bill'); - // names.tag('FirstName', 'ambiguous-name'); - // } - // } - // } - //tighter-matches for other ambiguous names: - // ts.match('(al|) #Acronym? #LastName').firstTerm().tag('#FirstName', 'ambig-lastname'); - //methods requiring a firstname match + var end = this.list.length; + return this.slice(end - n, end); + }; + /** grab a given subset of the results*/ - if (ts.has('#FirstName')) { - // Firstname x (dangerous) - var tmp = ts.match('#FirstName #Noun').ifNo('^#Possessive').ifNo('#ClauseEnd .'); - tmp.lastTerm().canBe('#LastName').tag('#LastName', 'firstname-noun'); //ferdinand de almar - ts.match('#FirstName de #Noun').canBe('#Person').tag('#Person', 'firstname-de-noun'); //Osama bin Laden + exports.slice = function (start, end) { + var list = this.list.slice(start, end); + return this.buildFrom(list); + }; + /* grab nth result */ - ts.match('#FirstName (bin|al) #Noun').canBe('#Person').tag('#Person', 'firstname-al-noun'); //John L. Foo - ts.match('#FirstName #Acronym #TitleCase').tag('Person', 'firstname-acronym-titlecase'); //Andrew Lloyd Webber + exports.eq = function (n) { + var p = this.list[n]; - ts.match('#FirstName #FirstName #TitleCase').tag('Person', 'firstname-firstname-titlecase'); //Mr Foo + if (p === undefined) { + return this.buildFrom([]); + } - ts.match('#Honorific #FirstName? #TitleCase').tag('Person', 'Honorific-TitleCase'); //John Foo + return this.buildFrom([p]); + }; - ts.match('#FirstName #TitleCase #TitleCase?').match('#Noun+').tag('Person', 'firstname-titlecase'); //peter the great + exports.get = exports.eq; + /** grab term[0] for every match */ - ts.match('#FirstName the #Adjective').tag('Person', 'correction-determiner5'); //very common-but-ambiguous lastnames + exports.firstTerm = function () { + return this.match('^.'); + }; + /** grab the last term for every match */ - ts.match('#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)').tag('#Person', 'firstname-maybe'); //Joe K. Sombrero - ts.match('#FirstName #Acronym #Noun').ifNo('#Date').tag('#Person', 'n-acro-noun').lastTerm().tag('#LastName', 'n-acro-noun'); // Dwayne 'the rock' Johnson + exports.lastTerm = function () { + return this.match('.$'); + }; + /** return a flat array of term objects */ - ts.match('#FirstName [#Determiner? #Noun] #LastName').tag('#NickName', 'first-noun-last').tag('#Person', 'first-noun-last'); //john bodego's - ts.match('#FirstName (#Singular|#Possessive)').ifNo('#Date').ifNo('#NickName').tag('#Person', 'first-possessive').lastTerm().tag('#LastName', 'first-possessive'); - } //methods requiring a lastname match + exports.termList = function (num) { + var arr = []; //'reduce' but faster + for (var i = 0; i < this.list.length; i++) { + var terms = this.list[i].terms(); - if (ts.has('#LastName')) { - // x Lastname - ts.match('#Noun #LastName').firstTerm().canBe('#FirstName').tag('#FirstName', 'noun-lastname'); //ambiguous-but-common firstnames + for (var o = 0; o < terms.length; o++) { + arr.push(terms[o]); //support .termList(4) - ts.match('(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill) #LastName').firstTerm().tag('#FirstName', 'maybe-lastname'); //Jani K. Smith + if (num !== undefined && arr[num] !== undefined) { + return arr[num]; + } + } + } - ts.match('#TitleCase #Acronym? #LastName').ifNo('#Date').tag('#Person', 'title-acro-noun').lastTerm().tag('#LastName', 'title-acro-noun'); //is foo Smith + return arr; + }; + }); + var _02Accessors_1 = _02Accessors.first; + var _02Accessors_2 = _02Accessors.last; + var _02Accessors_3 = _02Accessors.slice; + var _02Accessors_4 = _02Accessors.eq; + var _02Accessors_5 = _02Accessors.get; + var _02Accessors_6 = _02Accessors.firstTerm; + var _02Accessors_7 = _02Accessors.lastTerm; + var _02Accessors_8 = _02Accessors.termList; + + var _03Match = createCommonjsModule(function (module, exports) { + /** return a new Doc, with this one as a parent */ + exports.match = function (reg) { + //parse-up the input expression + var regs = syntax_1(reg); + + if (regs.length === 0) { + return this.buildFrom([]); + } //try expression on each phrase + + + var matches = this.list.reduce(function (arr, p) { + return arr.concat(p.match(regs)); + }, []); + return this.buildFrom(matches); + }; + /** return all results except for this */ - ts.match('#Copula (#Noun|#PresentTense) #LastName').term(1).tag('#FirstName', 'copula-noun-lastname'); - } //methods requiring a titlecase + exports.not = function (reg) { + //parse-up the input expression + var regs = syntax_1(reg); //if it's empty, return them all! - if (ts.has('#TitleCase')) { - ts.match('#Acronym #TitleCase').canBe('#Person').tag('#Person', 'acronym-titlecase'); //ludwig van beethovan + if (regs.length === 0) { + return this; + } //try expression on each phrase - ts.match('#TitleCase (van|al|bin) #TitleCase').canBe('#Person').tag('Person', 'correction-titlecase-van-titlecase'); - ts.match('#TitleCase (de|du) la? #TitleCase').canBe('#Person').tag('Person', 'correction-titlecase-van-titlecase'); //Morgan Shlkjsfne - ts.match('#Person #TitleCase').match('#TitleCase #Noun').canBe('#Person').tag('Person', 'correction-person-titlecase'); //pope francis + var matches = this.list.reduce(function (arr, p) { + return arr.concat(p.not(regs)); + }, []); + return this.buildFrom(matches); + }; + /** return only the first match */ - ts.match('(lady|queen|sister) #TitleCase').ifNo('#Date').ifNo('#Honorific').tag('#FemaleName', 'lady-titlecase'); - ts.match('(king|pope|father) #TitleCase').ifNo('#Date').tag('#MaleName', 'correction-poe'); - } //j.k Rowling + exports.matchOne = function (reg) { + var regs = syntax_1(reg); - ts.match('#Noun van der? #Noun').canBe('#Person').tag('#Person', 'von der noun'); //king of spain + for (var i = 0; i < this.list.length; i++) { + var match = this.list[i].match(regs); + return this.buildFrom(match); + } - ts.match('(king|queen|prince|saint|lady) of? #Noun').canBe('#Person').tag('#Person', 'king-of-noun'); //mr X + return this.buildFrom([]); + }; + /** return each current phrase, only if it contains this match */ - ts.match('#Honorific #Acronym').tag('Person', 'Honorific-TitleCase'); //peter II - ts.match('#Person #Person the? #RomanNumeral').tag('Person', 'correction-roman-numeral'); //'Professor Fink', 'General McCarthy' + exports["if"] = function (reg) { + var regs = syntax_1(reg); + var found = this.list.filter(function (p) { + return p.match(regs).length > 0; + }); + return this.buildFrom(found); + }; + /** Filter-out any current phrases that have this match*/ - ts.match('#Honorific #Person').tag('Person', 'Honorific-Person'); //remove single 'mr' - ts.match('^#Honorific$').unTag('Person', 'single-honorific'); - return ts; -}; + exports.ifNo = function (reg) { + var regs = syntax_1(reg); + var found = this.list.filter(function (p) { + return p.match(regs).length === 0; + }); + return this.buildFrom(found); + }; + /**Return a boolean if this match exists */ -module.exports = person_step; -},{}],117:[function(_dereq_,module,exports){ -'use strict'; //orgwords like 'bank' in 'Foo Bank' + exports.has = function (reg) { + var regs = syntax_1(reg); + return this.list.some(function (p) { + return p.has(regs) === true; + }); + }; + /** match any terms after our matches, within the sentence */ -var orgWords = _dereq_('../../world/more-data/orgWords'); //could this word be an organization + exports.lookAhead = function (reg) { + // find everything afterwards, by default + if (!reg) { + reg = '.*'; + } -var maybeOrg = function maybeOrg(t) { - //must be a noun - if (!t.tags.Noun) { - return false; - } //can't be these things + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + matches = matches.concat(p.lookAhead(regs)); + }); + matches = matches.filter(function (p) { + return p; + }); + return this.buildFrom(matches); + }; + exports.lookAfter = exports.lookAhead; + /** match any terms before our matches, within the sentence */ - if (t.tags.Pronoun || t.tags.Comma || t.tags.Possessive || t.tags.Place) { - return false; - } //must be one of these + exports.lookBehind = function (reg) { + // find everything afterwards, by default + if (!reg) { + reg = '.*'; + } + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + matches = matches.concat(p.lookBehind(regs)); + }); + matches = matches.filter(function (p) { + return p; + }); + return this.buildFrom(matches); + }; - if (t.tags.TitleCase || t.tags.Organization || t.tags.Acronym) { - return true; - } + exports.lookBefore = exports.lookBehind; + /** return all terms before a match, in each phrase */ - return false; -}; + exports.before = function (reg) { + var regs = syntax_1(reg); //only the phrases we care about -var organization_step = function organization_step(ts) { - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; + var phrases = this["if"](regs).list; + var befores = phrases.map(function (p) { + var ids = p.terms().map(function (t) { + return t.id; + }); //run the search again - if (orgWords.hasOwnProperty(t.root) === true) { - //eg. Toronto University - var lastTerm = ts.terms[i - 1]; + var m = p.match(regs)[0]; + var index = ids.indexOf(m.start); //nothing is before a first-term match - if (lastTerm && maybeOrg(lastTerm)) { - lastTerm.tag('Organization', 'org-word-1'); - t.tag('Organization', 'org-word-2'); - continue; - } //eg. University of Toronto + if (index === 0 || index === -1) { + return null; + } + return p.buildFrom(p.start, index); + }); + befores = befores.filter(function (p) { + return p !== null; + }); + return this.buildFrom(befores); + }; + /** return all terms after a match, in each phrase */ - var nextTerm = ts.terms[i + 1]; - if (nextTerm && nextTerm.normal === 'of') { - if (ts.terms[i + 2] && maybeOrg(ts.terms[i + 2])) { - t.tag('Organization', 'org-of-word-1'); - nextTerm.tag('Organization', 'org-of-word-2'); - ts.terms[i + 2].tag('Organization', 'org-of-word-3'); - continue; - } - } - } - } + exports.after = function (reg) { + var regs = syntax_1(reg); //only the phrases we care about - if (ts.has('#Acronym')) { - ts.match('the #Acronym').not('(iou|fomo|yolo|diy|dui|nimby)').lastTerm().tag('Organization', 'the-acronym'); - ts.match('#Acronym').match('#Possessive').tag('Organization', 'possessive-acronym'); - } + var phrases = this["if"](regs).list; + var befores = phrases.map(function (p) { + var terms = p.terms(); + var ids = terms.map(function (t) { + return t.id; + }); //run the search again - return ts; -}; + var m = p.match(regs)[0]; + var index = ids.indexOf(m.start); //skip if nothing is after it -module.exports = organization_step; + if (index === -1 || !terms[index + m.length]) { + return null; + } //create the new phrase, after our match. -},{"../../world/more-data/orgWords":221}],118:[function(_dereq_,module,exports){ -'use strict'; //tag the words between '(' and ')' as #Parentheses -var parenthesesStep = function parenthesesStep(ts) { - ts.terms.forEach(function (t, i) { - if (t.tags.StartBracket) { - for (var o = i; o < ts.terms.length; o += 1) { - if (ts.terms[o].tags.EndBracket === true) { - ts.slice(i, o + 1).tag('Parentheses'); - break; - } - } - } + var id = terms[index + m.length].id; + var len = p.length - index - m.length; + return p.buildFrom(id, len); + }); + befores = befores.filter(function (p) { + return p !== null; + }); + return this.buildFrom(befores); + }; }); - return ts; -}; - -module.exports = parenthesesStep; + var _03Match_1 = _03Match.match; + var _03Match_2 = _03Match.not; + var _03Match_3 = _03Match.matchOne; + var _03Match_4 = _03Match.ifNo; + var _03Match_5 = _03Match.has; + var _03Match_6 = _03Match.lookAhead; + var _03Match_7 = _03Match.lookAfter; + var _03Match_8 = _03Match.lookBehind; + var _03Match_9 = _03Match.lookBefore; + var _03Match_10 = _03Match.before; + var _03Match_11 = _03Match.after; + + /** apply a tag, or tags to all terms */ + var tagTerms = function tagTerms(tag, doc, safe, reason) { + var tagList = []; + + if (typeof tag === 'string') { + tagList = tag.split(' '); + } // console.log(doc.parents().length) + //do indepenent tags for each term: + + + doc.list.forEach(function (p) { + var terms = p.terms(); // tagSafe - apply only to fitting terms + + if (safe === true) { + terms = terms.filter(function (t) { + return t.canBe(tag, doc.world); + }); + } -},{}],119:[function(_dereq_,module,exports){ -'use strict'; + terms.forEach(function (t, i) { + //fancy version: + if (tagList.length > 1) { + if (tagList[i] && tagList[i] !== '.') { + t.tag(tagList[i], reason, doc.world); + } + } else { + //non-fancy version (same tag for all terms) + t.tag(tag, reason, doc.world); + } + }); + }); + return; + }; -var isPlural = _dereq_('../../subset/nouns/isPlural'); + var _setTag = tagTerms; -var pluralStep = function pluralStep(ts) { - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; + /** Give all terms the given tag */ - if (t.tags.Noun) { - //skip existing fast - if (t.tags.Singular || t.tags.Plural) { - continue; - } //check if it's plural + var tag$1 = function tag(tags, why) { + if (!tags) { + return this; + } + _setTag(tags, this, false, why); + return this; + }; + /** Only apply tag to terms if it is consistent with current tags */ - var plural = isPlural(t, t.world); //can be null if unknown - if (plural === true) { - t.tag('Plural', 'pluralStep'); - } else if (plural === false) { - t.tag('Singular', 'pluralStep'); - } + var tagSafe$1 = function tagSafe(tags, why) { + if (!tags) { + return this; } - } - return ts; -}; + _setTag(tags, this, true, why); + return this; + }; + /** Remove this term from the given terms */ -module.exports = pluralStep; -},{"../../subset/nouns/isPlural":39}],120:[function(_dereq_,module,exports){ -'use strict'; //regs- + var unTag$1 = function unTag(tags, why) { + var _this = this; -var numericCardinal = /^\$?[0-9,](\.[0-9])?/; -var isOrdinal = /[0-9](st|nd|rd|th)$/; // const hasText = /^[a-z]/; + this.list.forEach(function (p) { + p.terms().forEach(function (t) { + return t.unTag(tags, why, _this.world); + }); + }); + return this; + }; + /** return only the terms that can be this tag*/ -var value_step = function value_step(ts) { - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; - if (t.tags.Value === true) { - //ordinal/cardinal - if (t.tags.Ordinal === undefined && t.tags.Cardinal === undefined) { - if (numericCardinal.test(t.normal) === true) { - t.tag('Cardinal', 'cardinal-val-regex'); - t.tag('NumericValue', 'NumericValue-regex'); - } else if (isOrdinal.test(t.normal) === true) { - t.tag('Ordinal', 'ordinal-value-regex'); - t.tag('NumericValue', 'NumericValue-regex'); - } - } + var canBe$2 = function canBe(tag) { + if (!tag) { + return this; } - } //5 books + var world = this.world; + var matches = this.list.reduce(function (arr, p) { + return arr.concat(p.canBe(tag, world)); + }, []); + return this.buildFrom(matches); + }; - ts.match('#Cardinal [#Plural]').tag('Unit', 'cardinal-plural'); //5th book - - ts.match('#Ordinal [#Singular]').tag('Unit', 'ordinal-singular'); //1 book + var _04Tag = { + tag: tag$1, + tagSafe: tagSafe$1, + unTag: unTag$1, + canBe: canBe$2 + }; - ts.match('(one|first|1|1st) [#Singular]').tag('Unit', 'one-singular'); - return ts; -}; + /* run each phrase through a function, and create a new document */ + var map = function map(fn) { + var _this = this; -module.exports = value_step; + if (!fn) { + return this; + } -},{}],121:[function(_dereq_,module,exports){ -'use strict'; //mostly pos-corections here + var list = this.list.map(function (p, i) { + var doc = _this.buildFrom([p]); -var corrections = function corrections(ts) { - //ambig prepositions/conjunctions - if (ts.has('so')) { - //so funny - ts.match('so #Adjective').match('so').tag('Adverb', 'so-adv'); //so the + doc.from = null; //it's not a child/parent - ts.match('so #Noun').match('so').tag('Conjunction', 'so-conj'); //do so + var res = fn(doc, i); - ts.match('do so').match('so').tag('Noun', 'so-noun'); - } + if (res.list && res.list[0]) { + return res.list[0]; + } - if (ts.has('all')) { - //all students - ts.match('[all] #Determiner? #Noun').tag('Adjective', 'all-noun'); //it all fell apart + return res; + }); - ts.match('[all] #Verb').tag('Adverb', 'all-verb'); - } //the ambiguous word 'that' and 'which' + if (list.length === 0) { + return this.buildFrom(list); + } // if it is not a list of Phrase objects, then don't try to make a Doc object - if (ts.has('(that|which)')) { - //remind john that - ts.match('#Verb #Adverb? #Noun (that|which)').lastTerm().tag('Preposition', 'that-prep'); //that car goes + if (_typeof(list[0]) !== 'object' || list[0].isA !== 'Phrase') { + return list; + } - ts.match('that #Noun #Verb').firstTerm().tag('Determiner', 'that-determiner'); //work, which has been done. + return this.buildFrom(list); + }; + /** run a function on each phrase */ - ts.match('#Comma [which] (#Pronoun|#Verb)').tag('Preposition', 'which-copula'); //things that provide - // ts.match('#Plural (that|which) #Adverb? #Verb').term(1).tag('Preposition', 'noun-that'); - } //Determiner-signals + var forEach = function forEach(fn, detachParent) { + var _this2 = this; - if (ts.has('#Determiner')) { - //the wait to vote - ts.match('(the|this) [#Verb] #Preposition .').tag('Noun', 'correction-determiner1'); //the swim + if (!fn) { + return this; + } - ts.match('(the|those|these) (#Infinitive|#PresentTense|#PastTense)').term(1).tag('Noun', 'correction-determiner2'); //a staggering cost + this.list.forEach(function (p, i) { + var sub = _this2.buildFrom([p]); // if we're doing fancy insertions, we may want to skip updating the parent each time. - ts.match('(a|an) [#Gerund]').tag('Adjective', 'correction-a|an'); - ts.match('(a|an) #Adjective (#Infinitive|#PresentTense)').term(2).tag('Noun', 'correction-a|an2'); //some pressing issues - ts.match('some [#Verb] #Plural').tag('Noun', 'correction-determiner6'); //the test string + if (detachParent === true) { + sub.from = null; // + } // let len + // console.log(sub.from.list[0].text()) - ts.match('#Determiner [#Infinitive] #Noun').tag('Noun', 'correction-determiner7'); //the orange. - ts.match('#Determiner #Adjective$').not('(#Comparative|#Superlative)').term(1).tag('Noun', 'the-adj-1'); //the orange is + fn(sub, i); // console.log(sub.from.list[0].text()) + }); + return this; + }; + /** return only the phrases that return true */ - ts.match('#Determiner [#Adjective] (#Copula|#PastTense|#Auxiliary)').tag('Noun', 'the-adj-2'); //the nice swim - ts.match('(the|this|those|these) #Adjective [#Verb]').tag('Noun', 'the-adj-verb'); //the truly nice swim + var filter = function filter(fn) { + var _this3 = this; - ts.match('(the|this|those|these) #Adverb #Adjective [#Verb]').tag('Noun', 'correction-determiner4'); //a stream runs + if (!fn) { + return this; + } - ts.match('(the|this|a|an) [#Infinitive] #Adverb? #Verb').tag('Noun', 'correction-determiner5'); //a sense of + var list = this.list.filter(function (p, i) { + var doc = _this3.buildFrom([p]); - ts.match('#Determiner [#Verb] of').tag('Noun', 'the-verb-of'); //the threat of force + doc.from = null; //it's not a child/parent - ts.match('#Determiner #Noun of [#Verb]').tag('Noun', 'noun-of-noun'); //a close + return fn(doc, i); + }); + return this.buildFrom(list); + }; + /** return a document with only the first phrase that matches */ - ts.match('#Determiner #Adverb? [close]').tag('Adjective', 'a-close'); //did a 900, paid a 20 - ts.match('#Verb (a|an) [#Value]').tag('Singular', 'a-value'); //a tv show + var find = function find(fn) { + var _this4 = this; - ts.match('(a|an) #Noun [#Infinitive]').tag('Noun', 'a-noun-inf'); - } //like + if (!fn) { + return this; + } + var phrase = this.list.find(function (p, i) { + var doc = _this4.buildFrom([p]); - if (ts.has('like')) { - ts.match('just [like]').tag('Preposition', 'like-preposition'); //folks like her + doc.from = null; //it's not a child/parent - ts.match('#Noun [like] #Noun').tag('Preposition', 'noun-like'); //look like + return fn(doc, i); + }); - ts.match('#Verb [like]').tag('Adverb', 'verb-like'); //exactly like + if (phrase) { + return this.buildFrom([phrase]); + } - ts.match('#Adverb like').not('(really|generally|typically|usually|sometimes|often) like').lastTerm().tag('Adverb', 'adverb-like'); - } + return undefined; + }; + /** return true or false if there is one matching phrase */ - if (ts.has('#Value')) { - //half a million - ts.match('half a? #Value').tag('Value', 'half-a-value'); //quarter not ready - ts.match('#Value and a (half|quarter)').tag('Value', 'value-and-a-half'); //all values are either ordinal or cardinal - // ts.match('#Value').match('!#Ordinal').tag('#Cardinal', 'not-ordinal'); - //money + var some = function some(fn) { + var _this5 = this; - ts.match('#Value+ #Currency').tag('Money', 'value-currency').lastTerm().tag('Unit', 'money-unit'); - ts.match('#Money and #Money #Currency?').tag('Money', 'money-and-money'); //1 800 PhoneNumber + if (!fn) { + return this; + } - ts.match('1 #Value #PhoneNumber').tag('PhoneNumber', '1-800-Value'); //(454) 232-9873 + return this.list.some(function (p, i) { + var doc = _this5.buildFrom([p]); - ts.match('#NumericValue #PhoneNumber').tag('PhoneNumber', '(800) PhoneNumber'); //two hundredth + doc.from = null; //it's not a child/parent - ts.match('#TextValue+').match('#Cardinal+ #Ordinal').tag('Ordinal', 'two-hundredth'); - } + return fn(doc, i); + }); + }; + /** sample a subset of the results */ - if (ts.has('#Noun')) { - //'more' is not always an adverb - ts.match('more #Noun').tag('Noun', 'more-noun'); //the word 'second' - ts.match('[second] #Noun').not('#Honorific').unTag('Unit').tag('Ordinal', 'second-noun'); //he quickly foo + var random = function random(n) { + if (!this.found) { + return this; + } - ts.match('#Noun #Adverb [#Noun]').tag('Verb', 'correction'); //fix for busted-up phrasalVerbs + var r = Math.floor(Math.random() * this.list.length); - ts.match('#Noun [#Particle]').tag('Preposition', 'repair-noPhrasal'); //John & Joe's + if (n === undefined) { + var list = [this.list[r]]; + return this.buildFrom(list); + } //prevent it from going over the end - ts.match('#Noun (&|n) #Noun').tag('Organization', 'Noun-&-Noun'); //Aircraft designer - ts.match('#Noun #Actor').tag('Actor', 'thing-doer'); //this rocks + if (r + n > this.length) { + r = this.length - n; + r = r < 0 ? 0 : r; + } - ts.match('(this|that) [#Plural]').tag('PresentTense', 'this-verbs'); //by a bear. + return this.slice(r, r + n); + }; + /** combine each phrase into a new data-structure */ + // exports.reduce = function(fn, h) { + // let list = this.list.reduce((_h, ts) => { + // let doc = this.buildFrom([ts]) + // doc.from = null //it's not a child/parent + // return fn(_h, doc) + // }, h) + // return this.buildFrom(list) + // } - ts.match('#Determiner #Infinitive$').lastTerm().tag('Noun', 'a-inf'); //the western line - ts.match('#Determiner [(western|eastern|northern|southern|central)] #Noun').tag('Noun', 'western-line'); - ts.match('(#Determiner|#Value) [(linear|binary|mobile|lexical|technical|computer|scientific|formal)] #Noun').tag('Noun', 'technical-noun'); //organization + var _05Loops = { + map: map, + forEach: forEach, + filter: filter, + find: find, + some: some, + random: random + }; - if (ts.has('#Organization')) { - ts.match('#Organization of the? #TitleCase').tag('Organization', 'org-of-place'); - ts.match('#Organization #Country').tag('Organization', 'org-country'); - ts.match('(world|global|international|national|#Demonym) #Organization').tag('Organization', 'global-org'); + var doesMatch$1 = function doesMatch(term, str) { + if (str === '') { + return false; } - if (ts.has('#Possessive')) { - //my buddy - ts.match('#Possessive [#FirstName]').unTag('Person', 'possessive-name'); //spencer kelly's - - ts.match('#FirstName #Acronym? #Possessive').notIf('#Comma').match('#FirstName #Acronym? #LastName').tag('Possessive'); //Super Corp's fundraiser + return term.reduced === str || term.implicit === str || term.root === str || term.text.toLowerCase() === str; + }; // is this lookup found in these terms? - ts.match('#Organization+ #Possessive').notIf('#Comma').tag('Possessive'); //Los Angeles's fundraiser - - ts.match('#Place+ #Possessive').notIf('#Comma').tag('Possessive'); - } - } - if (ts.has('#Verb')) { - //still make - ts.match('[still] #Verb').tag('Adverb', 'still-verb'); //'u' as pronoun + var findStart = function findStart(arr, terms) { + var _loop = function _loop(i) { + if (doesMatch$1(terms[i], arr[0])) { + if (arr.every(function (a, n) { + return doesMatch$1(terms[i + n], a) === true; + })) { + return { + v: terms[i].id + }; + } + } + }; - ts.match('[u] #Verb').tag('Pronoun', 'u-pronoun-1'); //is no walk + //find the start + for (var i = 0; i < terms.length; i++) { + var _ret = _loop(i); - ts.match('is no [#Verb]').tag('Noun', 'is-no-verb'); //different views than + if (_typeof(_ret) === "object") return _ret.v; + } - ts.match('[#Verb] than').tag('Noun', 'correction'); //her polling + return false; + }; + /** lookup an array of words or phrases */ - ts.match('#Possessive [#Verb]').tag('Noun', 'correction-possessive'); //there are reasons - ts.match('there (are|were) #Adjective? [#PresentTense]').tag('Plural', 'there-are'); //jack seems guarded + var lookup = function lookup(arr) { + var _this = this; - ts.match('#Singular (seems|appears) #Adverb? [#PastTense$]').tag('Adjective', 'seems-filled'); + if (typeof arr === 'string') { + arr = [arr]; + } - if (ts.has('(who|what|where|why|how|when)')) { - //the word 'how' - ts.match('^how').tag('QuestionWord', 'how-question').tag('QuestionWord', 'how-question'); - ts.match('how (#Determiner|#Copula|#Modal|#PastTense)').term(0).tag('QuestionWord', 'how-is'); // //the word 'which' + var lookups = arr.map(function (str) { + str = str.toLowerCase(); + var words = _02Words(str); + words = words.map(function (s) { + return s.trim(); + }); + return words; + }); + this.cache(); + var found = []; // try each lookup + + lookups.forEach(function (a) { + //try each phrase + _this.list.forEach(function (p) { + // cache-miss, skip. + if (p.cache.words[a[0]] !== true) { + return; + } //we found a potential match + + + var terms = p.terms(); + var id = findStart(a, terms); + + if (id !== false) { + // create the actual phrase + var phrase = p.buildFrom(id, a.length); + found.push(phrase); + return; + } + }); + }); + return this.buildFrom(found); + }; - ts.match('^which').tag('QuestionWord', 'which-question').tag('QuestionWord', 'which-question'); - ts.match('which . (#Noun)+ #Pronoun').term(0).tag('QuestionWord', 'which-question2'); - ts.match('which').tag('QuestionWord', 'which-question3'); //where - //how he is driving + var _06Lookup = { + lookup: lookup + }; - var word = ts.match('#QuestionWord #Noun #Copula #Adverb? (#Verb|#Adjective)').firstTerm(); - word.unTag('QuestionWord').tag('Conjunction', 'how-he-is-x'); //when i go fishing + var titleCase$2 = function titleCase(str) { + return str.charAt(0).toUpperCase() + str.substr(1); + }; + /** substitute-in new content */ - word = ts.match('#QuestionWord #Noun #Adverb? #Infinitive not? #Gerund').firstTerm(); - word.unTag('QuestionWord').tag('Conjunction', 'when i go fishing'); - } - if (ts.has('#Copula')) { - //is eager to go - ts.match('#Copula #Adjective to #Verb').match('#Adjective to').tag('Verb', 'correction'); //is mark hughes + var replaceWith = function replaceWith(replace, keepTags, keepCase) { + var _this = this; - ts.match('#Copula [#Infinitive] #Noun').tag('Noun', 'is-pres-noun'); - ts.match('[#Infinitive] #Copula').tag('Noun', 'infinitive-copula'); //sometimes adverbs - 'pretty good','well above' + if (!replace) { + return this["delete"](); + } // clear the cache - ts.match('#Copula (pretty|dead|full|well) (#Adjective|#Noun)').notIf('#Comma').tag('#Copula #Adverb #Adjective', 'sometimes-adverb'); //sometimes not-adverbs - ts.match('#Copula [(just|alone)$]').tag('Adjective', 'not-adverb'); //jack is guarded + this.uncache(); // return this - ts.match('#Singular is #Adverb? [#PastTense$]').tag('Adjective', 'is-filled'); - } //went to sleep - // ts.match('#Verb to #Verb').lastTerm().tag('Noun', 'verb-to-verb'); - //support a splattering of auxillaries before a verb + this.list.forEach(function (p) { + var input = replace; // accept a function for replace + if (typeof replace === 'function') { + input = replace(p); + } - var advb = '(#Adverb|not)+?'; + var newPhrases; // accept a Doc object to replace - if (ts.has(advb)) { - //had walked - ts.match("(has|had) ".concat(advb, " #PastTense")).not('#Verb$').tag('Auxiliary', 'had-walked'); //was walking + if (input && _typeof(input) === 'object' && input.isA === 'Doc') { + newPhrases = input.list; - ts.match("#Copula ".concat(advb, " #Gerund")).not('#Verb$').tag('Auxiliary', 'copula-walking'); //been walking + _this.pool().merge(input.pool()); + } else if (typeof input === 'string') { + //input is a string + if (keepCase === true && p.terms(0).isTitleCase()) { + input = titleCase$2(input); + } - ts.match("(be|been) ".concat(advb, " #Gerund")).not('#Verb$').tag('Auxiliary', 'be-walking'); //would walk + newPhrases = _01Tokenizer.fromText(input, _this.world, _this.pool()); //tag the new phrases - ts.match("(#Modal|did) ".concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'modal-verb'); //would have had + var tmpDoc = _this.buildFrom(newPhrases); - ts.match("#Modal ".concat(advb, " have ").concat(advb, " had ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-have'); //would be walking + tmpDoc.tagger(); + } else { + return; //don't even bother + } // try to keep its old tags, if appropriate - ts.match("(#Modal) ".concat(advb, " be ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-be'); //would been walking - ts.match("(#Modal|had|has) ".concat(advb, " been ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-be'); //infinitive verbs suggest plural nouns - 'XYZ walk to the store' - // r.match(`#Singular+ #Infinitive`).match('#Singular+').tag('Plural', 'infinitive-make-plural'); - } //fall over + if (keepTags === true) { + var oldTags = p.json({ + terms: { + tags: true + } + }).terms; + newPhrases[0].terms().forEach(function (t, i) { + if (oldTags[i]) { + t.tagSafe(oldTags[i].tags, 'keptTag', _this.world); + } + }); + } + p.replace(newPhrases[0], _this); //Oneday: support multi-sentence replacements + }); + return this; + }; + /** search and replace match with new content */ - ts.match('#PhrasalVerb #PhrasalVerb').lastTerm().tag('Particle', 'phrasal-particle'); - if (ts.has('#Gerund')) { - //walking is cool - ts.match('#Gerund #Adverb? not? #Copula').firstTerm().tag('Activity', 'gerund-copula'); //walking should be fun + var replace$1 = function replace(match, _replace, keepTags, keepCase) { + // if there's no 2nd param, use replaceWith + if (_replace === undefined) { + return this.replaceWith(match); + } - ts.match('#Gerund #Modal').firstTerm().tag('Activity', 'gerund-modal'); //running-a-show + this.match(match).replaceWith(_replace, keepTags, keepCase); + return this; + }; - ts.match('#Gerund #Determiner [#Infinitive]').tag('Noun', 'running-a-show'); //setting records - // ts.match('#Gerund [#PresentTense]').tag('Plural', 'setting-records'); - } //will be cool -> Copula + var _01Replace = { + replaceWith: replaceWith, + replace: replace$1 + }; + var _02Insert = createCommonjsModule(function (module, exports) { + /** add these new terms to the end*/ + exports.append = function (str) { + var _this = this; - if (ts.has('will #Adverb? not? #Adverb? be')) { - //will be running (not copula - if (ts.has('will #Adverb? not? #Adverb? be #Gerund') === false) { - //tag it all - ts.match('will not? be').tag('Copula', 'will-be-copula'); //for more complex forms, just tag 'be' + if (!str) { + return this; + } // clear the cache - ts.match('will #Adverb? not? #Adverb? be #Adjective').match('be').tag('Copula', 'be-copula'); - } - } - } - if (ts.has('#Adjective')) { - //still good - ts.match('still #Adjective').match('still').tag('Adverb', 'still-advb'); //big dreams, critical thinking + this.uncache(); //add it to end of every phrase - ts.match('#Adjective [#PresentTense]').tag('Noun', 'adj-presentTense'); //will secure our + this.list.forEach(function (p) { + //build it + var phrase = _01Tokenizer.fromText(str, _this.world, _this.pool())[0]; //assume it's one sentence, for now + //tag it - ts.match('will [#Adjective]').tag('Verb', 'will-adj'); //cheering hard - dropped -ly's + var tmpDoc = _this.buildFrom([phrase]); - ts.match('#PresentTense (hard|quick|long|bright|slow)').lastTerm().tag('Adverb', 'lazy-ly'); //his fine + tmpDoc.tagger(); // push it onto the end - ts.match('(his|her|its) [#Adjective]').tag('Noun', 'his-fine'); // + p.append(phrase, _this); + }); + return this; + }; - ts.match('#Noun #Adverb? [left]').tag('PastTense', 'left-verb'); - } + exports.insertAfter = exports.append; + exports.insertAt = exports.append; + /** add these new terms to the front*/ - if (ts.has('#TitleCase')) { - //FitBit Inc - ts.match('#TitleCase (ltd|co|inc|dept|assn|bros)').tag('Organization', 'org-abbrv'); //Foo District + exports.prepend = function (str) { + var _this2 = this; - ts.match('#TitleCase+ (district|region|province|county|prefecture|municipality|territory|burough|reservation)').tag('Region', 'foo-district'); //District of Foo + if (!str) { + return this; + } // clear the cache - ts.match('(district|region|province|municipality|territory|burough|state) of #TitleCase').tag('Region', 'district-of-Foo'); - } - if (ts.has('#Hyphenated')) { - //air-flow - ts.match('#Hyphenated #Hyphenated').match('#Noun #Verb').tag('Noun', 'hyphen-verb'); - var hyphen = ts.match('#Hyphenated+'); + this.uncache(); //add it to start of every phrase - if (hyphen.has('#Expression')) { - //ooh-wee - hyphen.tag('Expression', 'ooh-wee'); - } - } + this.list.forEach(function (p) { + //build it + var phrase = _01Tokenizer.fromText(str, _this2.world, _this2.pool())[0]; //assume it's one sentence, for now + //tag it - if (ts.has('#Place')) { - //West Norforlk - ts.match('(west|north|south|east|western|northern|southern|eastern)+ #Place').tag('Region', 'west-norfolk'); //some us-state acronyms (exlude: al, in, la, mo, hi, me, md, ok..) + var tmpDoc = _this2.buildFrom([phrase]); - ts.match('#City [#Acronym]').match('(al|ak|az|ar|ca|ct|dc|fl|ga|id|il|nv|nh|nj|ny|oh|or|pa|sc|tn|tx|ut|vt|pr)').tag('Region', 'us-state'); - } //misc: - //foot/feet + tmpDoc.tagger(); // add it to the start + p.prepend(phrase, _this2); + }); + return this; + }; - ts.match('(foot|feet)').tag('Noun', 'foot-noun'); - ts.match('#Value (foot|feet)').term(1).tag('Unit', 'foot-unit'); //'u' as pronoun + exports.insertBefore = exports.prepend; + /** add these new things to the end*/ - ts.match('#Conjunction [u]').tag('Pronoun', 'u-pronoun-2'); //'a/an' can mean 1 - "a hour" + exports.concat = function () { + // clear the cache + this.uncache(); + var list = this.list.slice(0); //repeat for any number of params - ts.match('(a|an) (#Duration|hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)').ifNo('#Plural').term(0).tag('Value', 'a-is-one'); //swear-words as non-expression POS - //nsfw + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; //support a fresh string - ts.match('holy (shit|fuck|hell)').tag('Expression', 'swears-expression'); - ts.match('#Determiner (shit|damn|hell)').term(1).tag('Noun', 'swears-noun'); - ts.match('(shit|damn|fuck) (#Determiner|#Possessive|them)').term(0).tag('Verb', 'swears-verb'); - ts.match('#Copula fucked up?').not('#Copula').tag('Adjective', 'swears-adjective'); //6 am + if (typeof arg === 'string') { + var arr = _01Tokenizer.fromText(arg, this.world); //TODO: phrase.tagger()? - ts.match('#Holiday (day|eve)').tag('Holiday', 'holiday-day'); //timezones + list = list.concat(arr); + } else if (arg.isA === 'Doc') { + list = list.concat(arg.list); + } else if (arg.isA === 'Phrase') { + list.push(arg); + } + } - ts.match('(standard|daylight|summer|eastern|pacific|central|mountain) standard? time').tag('Time', 'timezone'); //canadian dollar, Brazilian pesos + return this.buildFrom(list); + }; + /** fully remove these terms from the document */ - ts.match('#Demonym #Currency').tag('Currency', 'demonym-currency'); //about to go - ts.match('about to #Adverb? #Verb').match('about to').tag(['Auxiliary', 'Verb'], 'about-to'); //Doctor john smith jr + exports["delete"] = function (match) { + var _this3 = this; - ts.match('#Honorific #Person').tag('Person', 'honorific-person'); - ts.match('#Person (jr|sr|md)').tag('Person', 'person-honorific'); //right of way + // clear the cache + this.uncache(); + var toRemove = this; - ts.match('(right|rights) of .').tag('Noun', 'right-of'); - return ts; -}; + if (match) { + toRemove = this.match(match); + } -module.exports = corrections; + toRemove.list.forEach(function (phrase) { + return phrase["delete"](_this3); + }); + return this; + }; // aliases -},{}],122:[function(_dereq_,module,exports){ -"use strict"; -//a specificly-named thing, that should be capitalized -var properNoun = function properNoun(ts) { - if (ts.has('#Person') === true) { - ts.match('#FirstName #Person+').tag('ProperNoun'); - ts.match('#Person+ #LastName').tag('ProperNoun'); - } + exports.remove = exports["delete"]; + }); + var _02Insert_1 = _02Insert.append; + var _02Insert_2 = _02Insert.insertAfter; + var _02Insert_3 = _02Insert.insertAt; + var _02Insert_4 = _02Insert.prepend; + var _02Insert_5 = _02Insert.insertBefore; + var _02Insert_6 = _02Insert.concat; + var _02Insert_7 = _02Insert.remove; + + /** return the document as text */ + var text$1 = function text(options) { + var _this = this; - if (ts.has('#Place') === true) { - ts.match('(#City|#Region|#Country)').tag('ProperNoun'); - } + options = options || {}; //are we showing every phrase? - ts.match('#Organization').tag('ProperNoun'); - ts.match('#Month').tag('ProperNoun'); - return ts; -}; + var showFull = false; -module.exports = properNoun; + if (this.parents().length === 0) { + showFull = true; + } // cache roots, if necessary -},{}],123:[function(_dereq_,module,exports){ -"use strict"; -//patterns are .match() statements to be run after the tagger -var posthoc = function posthoc(ts) { - var patterns = ts.world.patterns; - Object.keys(patterns).forEach(function (k) { - ts.match(k).tag(patterns[k], 'post-hoc: ' + k); - }); - return ts; -}; - -module.exports = posthoc; - -},{}],124:[function(_dereq_,module,exports){ -'use strict'; - -var fixContraction = _dereq_('./fix'); - -var irregulars = { - wanna: ['want', 'to'], - gonna: ['going', 'to'], - im: ['i', 'am'], - alot: ['a', 'lot'], - dont: ['do', 'not'], - dun: ['do', 'not'], - ive: ['i', 'have'], - "won't": ['will', 'not'], - wont: ['will', 'not'], - "can't": ['can', 'not'], - cant: ['can', 'not'], - cannot: ['can', 'not'], - // aint: ['is', 'not'], //or 'are' - // "ain't": ['is', 'not'], - "shan't": ['should', 'not'], - imma: ['I', 'will'], - "where'd": ['where', 'did'], - whered: ['where', 'did'], - "when'd": ['when', 'did'], - whend: ['when', 'did'], - "how'd": ['how', 'did'], - howd: ['how', 'did'], - "what'd": ['what', 'did'], - whatd: ['what', 'did'], - "let's": ['let', 'us'], - //multiple word contractions - dunno: ['do', 'not', 'know'], - brb: ['be', 'right', 'back'], - gtg: ['got', 'to', 'go'], - irl: ['in', 'real', 'life'], - tbh: ['to', 'be', 'honest'], - imo: ['in', 'my', 'opinion'], - til: ['today', 'i', 'learned'], - rn: ['right', 'now'], - twas: ['it', 'was'], - '@': ['at'] -}; //check irregulars - -var checkIrregulars = function checkIrregulars(ts) { - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; - - if (irregulars[t.normal]) { - var fix = irregulars[t.normal]; - ts = fixContraction(ts, fix, i); - i += fix.length - 1; + if (options === 'root' || _typeof(options) === 'object' && options.root) { + this.list.forEach(function (p) { + p.terms().forEach(function (t) { + if (t.root === null) { + t.setRoot(_this.world); + } + }); + }); } - } - return ts; -}; + return this.list.reduce(function (str, p, i) { + var trimPre = !showFull && i === 0; + var trimPost = !showFull && i === _this.list.length - 1; + return str + p.text(options, trimPre, trimPost); + }, ''); + }; -module.exports = checkIrregulars; + var _01Text = { + text: text$1 + }; -},{"./fix":128}],125:[function(_dereq_,module,exports){ -'use strict'; + var _02Json = createCommonjsModule(function (module, exports) { + var jsonDefaults = { + text: true, + terms: true, + trim: true + }; // get all character startings in doc + + var termOffsets = function termOffsets(doc) { + var elapsed = 0; + var index = 0; + var offsets = {}; + doc.termList().forEach(function (term) { + offsets[term.id] = { + index: index, + start: elapsed + term.pre.length, + length: term.text.length + }; + elapsed += term.pre.length + term.text.length + term.post.length; + index += 1; + }); + return offsets; + }; + /** pull out desired metadata from the document */ -var fixContraction = _dereq_('./fix'); -var splitContraction = _dereq_('./split'); //these are always contractions + exports.json = function () { + var _this = this; + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; -var blacklist = { - 'that\'s': true, - 'there\'s': true -}; -var are = { - we: true, - they: true, - you: true -}; // "'s" may be a contraction or a possessive -// 'spencer's house' vs 'spencer's good' + //support json(3) format + if (typeof options === 'number' && this.list[options]) { + return this.list[options].json(jsonDefaults); + } -var isPossessive = function isPossessive(ts, i) { - var t = ts.terms[i]; - var next_t = ts.terms[i + 1]; //a pronoun can't be possessive - "he's house" + options = Object.assign({}, jsonDefaults, options); // cache roots, if necessary - if (t.tags.Pronoun || t.tags.QuestionWord) { - return false; - } + if (options === 'root' || _typeof(options) === 'object' && options.root) { + this.list.forEach(function (p) { + p.terms().forEach(function (t) { + if (t.root === null) { + t.setRoot(_this.world); + } + }); + }); + } - if (blacklist[t.normal]) { - return false; - } //if end of sentence, it is possessive - "was spencer's" + if (options.unique) { + options.reduced = true; + } + if (options.offset) { + options.terms = options.terms === true ? {} : options.terms; + options.terms.offset = true; + } - if (!next_t) { - return true; - } //an infinitive is probably mis-tagged - 'jamie's bite' + if (options.index || options.terms.index) { + options.terms = options.terms === true ? {} : options.terms; + options.terms.id = true; + } + var result = this.list.map(function (p) { + return p.json(options, _this.world); + }); // add offset and index data for each term - if (next_t.tags.Infinitive) { - return true; - } //a gerund suggests 'is walking' + if (options.terms.offset || options.offset || options.terms.index || options.index) { + // calculate them, (from beginning of doc) + var offsets = termOffsets(this.all()); // add index values + if (options.terms.index || options.index) { + result.forEach(function (o) { + o.terms.forEach(function (t) { + t.index = offsets[t.id].index; + }); + o.index = o.terms[0].index; + }); + } // add offset values - if (next_t.tags.VerbPhrase) { - return false; - } //spencer's house + if (options.terms.offset || options.offset) { + result.forEach(function (o) { + o.terms.forEach(function (t) { + t.offset = offsets[t.id] || {}; + }); + var len = o.terms.reduce(function (n, t) { + n += t.offset.length || 0; + return n; + }, 0); + o.offset = o.terms[0].offset; + o.offset.length = len; + }); + } + } // add frequency #s - if (next_t.tags.Noun) { - return true; - } //rocket's red glare + if (options.frequency || options.freq || options.count) { + var obj = {}; + this.list.forEach(function (p) { + var str = p.text('reduced'); + obj[str] = obj[str] || 0; + obj[str] += 1; + }); + this.list.forEach(function (p, i) { + result[i].count = obj[p.text('reduced')]; + }); + } // remove duplicates - if (next_t.tags.Adjective && ts.terms[i + 2] && ts.terms[i + 2].tags.Noun) { - return true; - } //an adjective suggests 'is good' + if (options.unique) { + var already = {}; + result = result.filter(function (o) { + if (already[o.reduced] === true) { + return false; + } - if (next_t.tags.Adjective || next_t.tags.Adverb || next_t.tags.Verb) { - return false; - } + already[o.reduced] = true; + return true; + }); + } - return false; -}; // you ain't / i ain't. + return result; + }; //aliases -var isAre = function isAre(ts, i) { - var arr = ['is', 'not']; //default - //get what's it 'about' + exports.data = exports.json; + }); + var _02Json_1 = _02Json.json; + var _02Json_2 = _02Json.data; + + var entity$1 = ['Person', 'Place', 'Organization']; + var nouns$1 = { + Noun: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + // - singular + Singular: { + isA: 'Noun', + notA: 'Plural' + }, + //a specific thing that's capitalized + ProperNoun: { + isA: 'Noun' + }, + // -- people + Person: { + isA: ['ProperNoun', 'Singular'], + notA: ['Place', 'Organization'] + }, + FirstName: { + isA: 'Person' + }, + MaleName: { + isA: 'FirstName', + notA: ['FemaleName', 'LastName'] + }, + FemaleName: { + isA: 'FirstName', + notA: ['MaleName', 'LastName'] + }, + LastName: { + isA: 'Person', + notA: ['FirstName'] + }, + Honorific: { + isA: 'Noun', + notA: ['FirstName', 'LastName'] + }, + // -- places + Place: { + isA: 'Singular', + notA: ['Person', 'Organization'] + }, + Country: { + isA: ['Place', 'ProperNoun'], + notA: ['City'] + }, + City: { + isA: ['Place', 'ProperNoun'], + notA: ['Country'] + }, + Region: { + isA: ['Place', 'ProperNoun'] + }, + Address: { + isA: 'Place' + }, + //---Orgs--- + Organization: { + isA: ['Singular', 'ProperNoun'], + notA: ['Person', 'Place'] + }, + SportsTeam: { + isA: 'Organization' + }, + School: { + isA: 'Organization' + }, + Company: { + isA: 'Organization' + }, + // - plural + Plural: { + isA: 'Noun', + notA: ['Singular'] + }, + //(not plural or singular) + Uncountable: { + isA: 'Noun' + }, + Pronoun: { + isA: 'Noun', + notA: entity$1 + }, + //a word for someone doing something -'plumber' + Actor: { + isA: 'Noun', + notA: entity$1 + }, + //a gerund-as-noun - 'swimming' + Activity: { + isA: 'Noun', + notA: ['Person', 'Place'] + }, + //'kilograms' + Unit: { + isA: 'Noun', + notA: entity$1 + }, + //'Canadians' + Demonym: { + isA: ['Noun', 'ProperNoun'], + notA: entity$1 + }, + //`john's` + Possessive: { + isA: 'Noun' // notA: 'Pronoun', - if (ts.terms[i - 1]) { - var about = ts.terms[i - 1]; //go back one more.. + } + }; - if (about.tags.Adverb && ts.terms[i - 2]) { - about = ts.terms[i - 2]; + var verbs$1 = { + Verb: { + notA: ['Noun', 'Adjective', 'Adverb', 'Value'] + }, + // walks + PresentTense: { + isA: 'Verb', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // neutral form - 'walk' + Infinitive: { + isA: 'PresentTense', + notA: ['PastTense', 'Gerund'] + }, + // walking + Gerund: { + isA: 'PresentTense', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // walked + PastTense: { + isA: 'Verb', + notA: ['FutureTense'] + }, + // will walk + FutureTense: { + isA: 'Verb' + }, + // is + Copula: { + isA: 'Verb' + }, + // would have + Modal: { + isA: 'Verb', + notA: ['Infinitive'] + }, + // had walked + PerfectTense: { + isA: 'Verb', + notA: 'Gerund' + }, + Pluperfect: { + isA: 'Verb' + }, + // shown + Participle: { + isA: 'Verb' + }, + // show up + PhrasalVerb: { + isA: 'Verb' + }, + //'up' part + Particle: { + isA: 'PhrasalVerb' } + }; - if (about.tags.Plural || are[about.normal] === true) { - arr[0] = 'are'; + var values$1 = { + Value: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + Ordinal: { + isA: 'Value', + notA: ['Cardinal'] + }, + Cardinal: { + isA: 'Value', + notA: ['Ordinal'] + }, + RomanNumeral: { + isA: 'Cardinal', + //can be a person, too + notA: ['Ordinal', 'TextValue'] + }, + TextValue: { + isA: 'Value', + notA: ['NumericValue'] + }, + NumericValue: { + isA: 'Value', + notA: ['TextValue'] + }, + Money: { + isA: 'Cardinal' + }, + Percent: { + isA: 'Value' } - } - - return arr; -}; //handle ambigous contraction "'s" - + }; -var hardOne = function hardOne(ts) { - for (var i = 0; i < ts.terms.length; i++) { - //skip existing - if (ts.terms[i].silent_term) { - continue; + var anything$1 = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Value']; + var misc$2 = { + //--Adjectives-- + Adjective: { + notA: ['Noun', 'Verb', 'Adverb', 'Value'] + }, + // adjectives that can conjugate + Comparable: { + isA: ['Adjective'] + }, + // better + Comparative: { + isA: ['Adjective'] + }, + // best + Superlative: { + isA: ['Adjective'], + notA: ['Comparative'] + }, + NumberRange: { + isA: ['Contraction'] + }, + Adverb: { + notA: ['Noun', 'Verb', 'Adjective', 'Value'] + }, + // Dates: + //not a noun, but usually is + Date: { + notA: ['Verb', 'Conjunction', 'Adverb', 'Preposition', 'Adjective'] + }, + Month: { + isA: ['Date', 'Singular'], + notA: ['Year', 'WeekDay', 'Time'] + }, + WeekDay: { + isA: ['Date', 'Noun'] + }, + //glue + Determiner: { + notA: anything$1 + }, + Conjunction: { + notA: anything$1 + }, + Preposition: { + notA: anything$1 + }, + // what, who, why + QuestionWord: { + notA: ['Determiner'] + }, + // peso, euro + Currency: {}, + // ughh + Expression: { + notA: ['Noun', 'Adjective', 'Verb', 'Adverb'] + }, + // dr. + Abbreviation: {}, + // internet tags + Url: { + notA: ['HashTag', 'PhoneNumber', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + PhoneNumber: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + HashTag: {}, + AtMention: { + isA: ['Noun'], + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'Email'] + }, + Emoji: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Emoticon: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Email: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + //non-exclusive + Auxiliary: { + notA: ['Noun', 'Adjective', 'Value'] + }, + Acronym: { + notA: ['Plural', 'RomanNumeral'] + }, + Negative: { + notA: ['Noun', 'Adjective', 'Value'] + }, + // if, unless, were + Condition: { + notA: ['Verb', 'Adjective', 'Noun', 'Value'] } + }; - if (ts.terms[i].normal === 'ain\'t' || ts.terms[i].normal === 'aint') { - var arr = isAre(ts, i); - ts = fixContraction(ts, arr, i); - i += 1; - continue; - } + // i just made these up + var colorMap$1 = { + Noun: 'blue', + Verb: 'green', + Negative: 'green', + Date: 'red', + Value: 'red', + Adjective: 'magenta', + Preposition: 'cyan', + Conjunction: 'cyan', + Determiner: 'cyan', + Adverb: 'cyan' + }; + /** add a debug color to some tags */ - var parts = splitContraction(ts.terms[i]); + var addColors$1 = function addColors(tags) { + Object.keys(tags).forEach(function (k) { + if (colorMap$1[k]) { + tags[k].color = colorMap$1[k]; + return; + } - if (parts) { - //have we found a hard one - if (parts.end === 's') { - //spencer's house - if (isPossessive(ts, i)) { - ts.terms[i].tag('#Possessive', 'hard-contraction'); - continue; + tags[k].isA.some(function (t) { + if (colorMap$1[t]) { + tags[k].color = colorMap$1[t]; + return true; } - var _arr = [parts.start, 'is']; - - if (ts.terms[i + 1]) { - var str = ts.terms[i].normal; //he's walking -> is/was + return false; + }); + }); + return tags; + }; - if (ts.match(str + ' (#Negative|#Adverb|#Auxiliary)+? #Gerund').found) { - _arr = [parts.start, 'is']; - } else if (ts.match(str + ' (#Negative|#Adverb|#Auxiliary)+? #Verb').found) { - //is vs has ('he's got milk') - _arr = [parts.start, 'has']; - } - } + var _color$1 = addColors$1; - ts = fixContraction(ts, _arr, i); - i += 1; - } - } - } + var unique$4 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); + }; //add 'downward' tags (that immediately depend on this one) - return ts; -}; -module.exports = hardOne; + var inferIsA$1 = function inferIsA(tags) { + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; + var len = tag.isA.length; -},{"./fix":128,"./split":129}],126:[function(_dereq_,module,exports){ -'use strict'; + for (var i = 0; i < len; i++) { + var down = tag.isA[i]; -var fixContraction = _dereq_('./fix'); + if (tags[down]) { + tag.isA = tag.isA.concat(tags[down].isA); + } + } // clean it up -var split = _dereq_('./split'); //the formulaic contraction types: + tag.isA = unique$4(tag.isA); + }); + return tags; + }; -var easy_ends = { - ll: 'will', - // 'd': 'would', - ve: 'have', - re: 'are', - m: 'am', - 'n\'t': 'not' //these ones are a bit tricksier: - // 't': 'not', - // 's': 'is' //or was + var _isA$1 = inferIsA$1; -}; //unambiguous contractions, like "'ll" + var unique$5 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); + }; // crawl the tag-graph and infer any conflicts + // faster than doing this at tag-time -var easyOnes = function easyOnes(ts) { - for (var i = 0; i < ts.terms.length; i++) { - //skip existing - if (ts.terms[i].silent_term) { - continue; - } - var parts = split(ts.terms[i]); + var inferNotA$1 = function inferNotA(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.notA = tag.notA || []; + tag.isA.forEach(function (down) { + if (tags[down] && tags[down].notA) { + // borrow its conflicts + var notA = typeof tags[down].notA === 'string' ? [tags[down].isA] : tags[down].notA || []; + tag.notA = tag.notA.concat(notA); + } + }); // any tag that lists us as a conflict, we conflict it back. - if (parts) { - parts.start = parts.start.toLowerCase(); //make sure its an easy one + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; - if (easy_ends[parts.end]) { - var arr = [parts.start, easy_ends[parts.end]]; - ts = fixContraction(ts, arr, i); - i += 1; - } //handle i'd -> 'i would' vs 'i had' + if (tags[key].notA.indexOf(k) !== -1) { + tag.notA.push(key); + } + } // clean it up - if (parts.end === 'd') { - //assume 'would' - var _arr = [parts.start, 'would']; //if next verb is past-tense, choose 'had' + tag.notA = unique$5(tag.notA); + }); + return tags; + }; - if (ts.terms[i + 1] && ts.terms[i + 1].tags.PastTense) { - _arr[1] = 'had'; - } //also support '#Adverb #PastTense' + var _notA$1 = inferNotA$1; + // a lineage is all 'incoming' tags that have this as 'isA' + var inferLineage$1 = function inferLineage(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.lineage = []; // find all tags with it in their 'isA' set - if (ts.terms[i + 2] && ts.terms[i + 2].tags.PastTense && ts.terms[i + 1].tags.Adverb) { - _arr[1] = 'had'; + for (var i = 0; i < keys.length; i++) { + if (tags[keys[i]].isA.indexOf(k) !== -1) { + tag.lineage.push(keys[i]); } - - ts = fixContraction(ts, _arr, i); - i += 1; } - } - } - - return ts; -}; - -module.exports = easyOnes; - -},{"./fix":128,"./split":129}],127:[function(_dereq_,module,exports){ -'use strict'; - -var fixContraction = _dereq_('./fix'); - -var Term = _dereq_('../../../term'); + }); + return tags; + }; -var hasDash = function hasDash(t) { - var dashes = /(-|–|—)/; - return dashes.test(t.whitespace.before) || dashes.test(t.whitespace.after); -}; + var _lineage$1 = inferLineage$1; -var numberRange = function numberRange(ts) { - //try to support number range, like 5-9, this way: - ts.match('#Hyphenated #Hyphenated').match('#NumericValue #NumericValue').tag('NumberRange'); //otherwise, loop through and find them + var validate$1 = function validate(tags) { + // cleanup format + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; // ensure isA is an array - for (var i = 0; i < ts.terms.length; i++) { - var t = ts.terms[i]; //skip existing + tag.isA = tag.isA || []; - if (t.silent_term) { - continue; - } + if (typeof tag.isA === 'string') { + tag.isA = [tag.isA]; + } // ensure notA is an array - if (t.tags.TextValue) { - continue; - } //hyphens found in whitespace - '5 - 7' + tag.notA = tag.notA || []; - if (t.tags.Value && ts.terms[i + 1] && i > 0 && (hasDash(t) || hasDash(ts.terms[i - 1])) && ts.terms[i - 1].tags.Value) { - var to = new Term('', ts.world); - to.silent_term = 'to'; - ts.insertAt(i, to); - ts.terms[i - 1].tag('NumberRange', 'number-number1'); - ts.terms[i].tag('NumberRange', 'number-number2'); - ts.terms[i].whitespace.before = ''; - ts.terms[i].whitespace.after = ''; - ts.terms[i + 1].tag('NumberRange', 'number-number3'); - return ts; - } //add a silent term + if (typeof tag.notA === 'string') { + tag.notA = [tag.notA]; + } + }); + return tags; + }; // build-out the tag-graph structure - if (t.tags.NumberRange) { - var arr = t.text.split(/(-|–|—)/); - arr[1] = 'to'; - ts = fixContraction(ts, arr, i); - ts.terms[i].tag(['NumberRange', 'NumericValue'], 'numRange-1'); - ts.terms[i + 1].tag(['NumberRange', 'Preposition'], 'numRange-silent'); - ts.terms[i + 2].tag(['NumberRange', 'NumericValue'], 'numRange-3'); - i += 2; - } - } + var inferTags$1 = function inferTags(tags) { + // validate data + tags = validate$1(tags); // build its 'down tags' - return ts; -}; + tags = _isA$1(tags); // infer the conflicts -module.exports = numberRange; + tags = _notA$1(tags); // debug tag color -},{"../../../term":143,"./fix":128}],128:[function(_dereq_,module,exports){ -'use strict'; + tags = _color$1(tags); // find incoming links -var Term = _dereq_('../../../term'); + tags = _lineage$1(tags); + return tags; + }; -var tags = { - not: 'Negative', - will: 'Verb', - would: 'Modal', - have: 'Verb', - are: 'Copula', - is: 'Copula', - am: 'Verb' -}; //make sure the newly created term gets the easy tags + var inference$1 = inferTags$1; -var easyTag = function easyTag(t) { - if (tags[t.silent_term]) { - t.tag(tags[t.silent_term]); - } -}; //add a silent term + var addIn$1 = function addIn(obj, tags) { + Object.keys(obj).forEach(function (k) { + tags[k] = obj[k]; + }); + }; + var build$1 = function build() { + var tags = {}; + addIn$1(nouns$1, tags); + addIn$1(verbs$1, tags); + addIn$1(values$1, tags); + addIn$1(misc$2, tags); // do the graph-stuff -var fixContraction = function fixContraction(ts, parts, i) { - //add the interpretation to the contracted term - var one = ts.terms[i]; - one.silent_term = parts[0]; //tag it as a contraction + tags = inference$1(tags); + return tags; + }; - one.tag('Contraction', 'tagger-contraction'); //add a new empty term + var tags$1 = build$1(); - if (parts[1]) { - var two = new Term('', ts.world); - two.silent_term = parts[1]; - two.tag('Contraction', 'tagger-contraction'); - ts.insertAt(i + 1, two); //ensure new term has no auto-whitspace + var _debug = createCommonjsModule(function (module) { + // https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color + var reset = '\x1b[0m'; - two.whitespace.before = ''; - two.whitespace.after = ''; - easyTag(two); - } //potentially it's three-contracted-terms, like 'dunno' + var padEnd = function padEnd(str, width) { + str = str.toString(); + while (str.length < width) { + str += ' '; + } - if (parts[2]) { - var three = new Term('', ts.world); - three.silent_term = parts[2]; // ts.terms.push(three); + return str; + }; //cheaper than requiring chalk - ts.insertAt(i + 2, three); - three.tag('Contraction', 'tagger-contraction'); - easyTag(three); - } - return ts; -}; - -module.exports = fixContraction; - -},{"../../../term":143}],129:[function(_dereq_,module,exports){ -'use strict'; - -var contraction = /^([a-z]+)'([a-z][a-z]?)$/i; -var possessive = /[a-z]s'$/i; -var allowed = { - re: 1, - ve: 1, - ll: 1, - t: 1, - s: 1, - d: 1, - m: 1 -}; -/** interpret a terms' contraction */ - -var splitContraction = function splitContraction(t) { - //handle this irregular one (shared trailing n) - if (t.normal === 'can\'t') { - return { - start: 'can', - end: 'n\'t' + var cli = { + green: function green(str) { + return '\x1b[32m' + str + reset; + }, + red: function red(str) { + return '\x1b[31m' + str + reset; + }, + blue: function blue(str) { + return '\x1b[34m' + str + reset; + }, + magenta: function magenta(str) { + return '\x1b[35m' + str + reset; + }, + cyan: function cyan(str) { + return '\x1b[36m' + str + reset; + }, + yellow: function yellow(str) { + return '\x1b[33m' + str + reset; + }, + black: function black(str) { + return '\x1b[30m' + str + reset; + } }; - } - - var parts = t.normal.match(contraction); - - if (parts && parts[1] && allowed[parts[2]] === 1) { - //handle n't - if (parts[2] === 't' && parts[1].match(/[a-z]n$/)) { - parts[1] = parts[1].replace(/n$/, ''); - parts[2] = 'n\'t'; //dunno.. - } //fix titlecase + var tagString = function tagString(tags) { + tags = tags.map(function (tag) { + if (!tags$1.hasOwnProperty(tag)) { + return tag; + } - if (t.tags.TitleCase === true) { - parts[1] = parts[1].replace(/^[a-z]/, function (x) { - return x.toUpperCase(); + var c = tags$1[tag].color || 'blue'; + return cli[c](tag); }); - } - - return { - start: parts[1], - end: parts[2] - }; - } // "flanders' house" - - - if (possessive.test(t.text) === true) { - return { - start: t.normal.replace(/s'?$/, ''), - end: '' - }; - } + return tags.join(', '); + }; //output some helpful stuff to the console - return null; -}; - -module.exports = splitContraction; - -},{}],130:[function(_dereq_,module,exports){ -"use strict"; - -//yep, -//https://github.com/mathiasbynens/emoji-regex/blob/master/index.js -module.exports = /(?:0\u20E3\n1\u20E3|2\u20E3|3\u20E3|4\u20E3|5\u20E3|6\u20E3|7\u20E3|8\u20E3|9\u20E3|#\u20E3|\*\u20E3|\uD83C(?:\uDDE6\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF2|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFD|\uDDFF)|\uDDE7\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFC|\uDDFE|\uDDFF)|\uDDE8\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDE9\uD83C(?:\uDDEA|\uDDEC|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDFF)|\uDDEA\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDED|\uDDF7|\uDDF8|\uDDF9|\uDDFA)|\uDDEB\uD83C(?:\uDDEE|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDF7)|\uDDEC\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF1|\uDDF2|\uDDF3|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFE)|\uDDED\uD83C(?:\uDDF0|\uDDF2|\uDDF3|\uDDF7|\uDDF9|\uDDFA)|\uDDEE\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9)|\uDDEF\uD83C(?:\uDDEA|\uDDF2|\uDDF4|\uDDF5)|\uDDF0\uD83C(?:\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDF2|\uDDF3|\uDDF5|\uDDF7|\uDDFC|\uDDFE|\uDDFF)|\uDDF1\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDEE|\uDDF0|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFE)|\uDDF2\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDF3\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFF)|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C(?:\uDDE6|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF7|\uDDF8|\uDDF9|\uDDFC|\uDDFE)|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C(?:\uDDEA|\uDDF4|\uDDF8|\uDDFA|\uDDFC)|\uDDF8\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDE9|\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFD|\uDDFE|\uDDFF)|\uDDF9\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF9|\uDDFB|\uDDFC|\uDDFF)|\uDDFA\uD83C(?:\uDDE6|\uDDEC|\uDDF2|\uDDF8|\uDDFE|\uDDFF)|\uDDFB\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDEE|\uDDF3|\uDDFA)|\uDDFC\uD83C(?:\uDDEB|\uDDF8)|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C(?:\uDDEA|\uDDF9)|\uDDFF\uD83C(?:\uDDE6|\uDDF2|\uDDFC)))|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD79\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED0\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3]|\uD83E[\uDD10-\uDD18\uDD80-\uDD84\uDDC0]/g; - -},{}],131:[function(_dereq_,module,exports){ -"use strict"; - -//just some of the most common emoticons -//faster than -//http://stackoverflow.com/questions/28077049/regex-matching-emoticons -module.exports = { - ':(': true, - ':)': true, - ':P': true, - ':p': true, - ':O': true, - ':3': true, - ':|': true, - ':/': true, - ':\\': true, - ':$': true, - ':*': true, - ':@': true, - ':-(': true, - ':-)': true, - ':-P': true, - ':-p': true, - ':-O': true, - ':-3': true, - ':-|': true, - ':-/': true, - ':-\\': true, - ':-$': true, - ':-*': true, - ':-@': true, - ':^(': true, - ':^)': true, - ':^P': true, - ':^p': true, - ':^O': true, - ':^3': true, - ':^|': true, - ':^/': true, - ':^\\': true, - ':^$': true, - ':^*': true, - ':^@': true, - '):': true, - '(:': true, - '$:': true, - '*:': true, - ')-:': true, - '(-:': true, - '$-:': true, - '*-:': true, - ')^:': true, - '(^:': true, - '$^:': true, - '*^:': true, - '<3': true, - ' 1 -['Value', 'Determiner'], ['Url', 'Value', 'HashTag', 'PhoneNumber', 'Emoji'], //roman numerals -['RomanNumeral', 'Fraction', 'NiceNumber'], ['RomanNumeral', 'Money'], //cases -['UpperCase', 'TitleCase', 'CamelCase'], //phrases -['VerbPhrase', 'Noun', 'Adjective', 'Value'], //QuestionWord -['QuestionWord', 'VerbPhrase'], //acronyms -['Acronym', 'VerbPhrase']]; - -},{}],137:[function(_dereq_,module,exports){ -'use strict'; - -var conflicts = _dereq_('./conflicts'); - -var nouns = _dereq_('./tags/nouns'); - -var verbs = _dereq_('./tags/verbs'); - -var values = _dereq_('./tags/values'); - -var dates = _dereq_('./tags/dates'); - -var misc = _dereq_('./tags/misc'); - -var addDownward = _dereq_('./addDownward'); //used for pretty-printing on the server-side - - -var colors = { - Noun: 'blue', - Date: 'red', - Value: 'red', - Verb: 'green', - Auxiliary: 'green', - Negative: 'green', - VerbPhrase: 'green', - Preposition: 'cyan', - Condition: 'cyan', - Conjunction: 'cyan', - Determiner: 'cyan', - Adjective: 'magenta', - Adverb: 'cyan' -}; //extend tagset with new tags - -var addIn = function addIn(obj, tags) { - Object.keys(obj).forEach(function (k) { - tags[k] = obj[k]; - }); -}; //add tags to remove when tagging this one + var debug = function debug(doc) { + console.log(cli.blue('=====')); + doc.list.forEach(function (p) { + console.log(cli.blue(' -----')); + p.terms().forEach(function (t) { + var tags = Object.keys(t.tags); + var text = t.text || '-'; -var addConflicts = function addConflicts(tags) { - Object.keys(tags).forEach(function (k) { - tags[k].notA = {}; + if (t.implicit) { + text = '[' + t.implicit + ']'; + } - for (var i = 0; i < conflicts.length; i++) { - var arr = conflicts[i]; + { + text = cli.yellow(text); + } - if (arr.indexOf(k) !== -1) { - arr = arr.filter(function (a) { - return a !== k; + var word = "'" + text + "'"; + word = padEnd(word, 18); + var str = cli.blue(' | ') + word + ' - ' + tagString(tags); + console.log(str); }); - arr.forEach(function (e) { - tags[k].notA[e] = true; - }); - } - } - - tags[k].notA = Object.keys(tags[k].notA); - }); -}; - -var addColors = function addColors(tags) { - Object.keys(tags).forEach(function (k) { - if (colors[k]) { - tags[k].color = colors[k]; - return; - } - - if (tags[k].isA && colors[tags[k].isA]) { - tags[k].color = colors[tags[k].isA]; - return; - } + }); + console.log(''); + return doc; + }; - if (tags[k].isA && tags[tags[k].isA].color) { - tags[k].color = tags[tags[k].isA].color; - } + module.exports = debug; }); -}; - -var build = function build() { - var tags = {}; - addIn(nouns, tags); - addIn(verbs, tags); - addIn(values, tags); - addIn(dates, tags); - addIn(misc, tags); //downstream - - addDownward(tags); //add enemies - - addConflicts(tags); //for nice-logging - - addColors(tags); - return tags; -}; - -module.exports = build(); - -},{"./addDownward":135,"./conflicts":136,"./tags/dates":138,"./tags/misc":139,"./tags/nouns":140,"./tags/values":141,"./tags/verbs":142}],138:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = { - Date: {}, - //not a noun, but usually is - Month: { - isA: 'Date', - also: 'Singular' - }, - WeekDay: { - isA: 'Date', - also: 'Noun' - }, - RelativeDay: { - isA: 'Date' - }, - Year: { - isA: 'Date' - }, - Duration: { - isA: 'Date', - also: 'Noun' - }, - Time: { - isA: 'Date', - also: 'Noun' - }, - Holiday: { - isA: 'Date', - also: 'Noun' - } -}; - -},{}],139:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = { - Adjective: {}, - Comparable: { - isA: 'Adjective' - }, - Comparative: { - isA: 'Adjective' - }, - Superlative: { - isA: 'Adjective' - }, - NumberRange: { - isA: 'Contraction' - }, - Adverb: {}, - Currency: {}, - //glue - Determiner: {}, - Conjunction: {}, - Preposition: {}, - QuestionWord: {}, - RelativeProunoun: { - isA: 'Pronoun' - }, - Expression: {}, - Abbreviation: {}, - Url: {}, - PhoneNumber: {}, - HashTag: {}, - AtMention: { - is: 'Noun' - }, - Emoji: {}, - Email: {}, - //non-exclusive - Condition: {}, - VerbPhrase: {}, - Auxiliary: {}, - Negative: {}, - Contraction: {}, - TitleCase: {}, - CamelCase: {}, - UpperCase: {}, - Hyphenated: {}, - Acronym: {}, - ClauseEnd: {}, - // Quotes - Quotation: {}, - StartQuotation: { - isA: 'Quotation' - }, - EndQuotation: { - isA: 'Quotation' - }, - //parentheses - Parentheses: {}, - EndBracket: { - isA: 'Parentheses' - }, - StartBracket: { - isA: 'Parentheses' - } -}; - -},{}],140:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = { - Noun: {}, - // - singular - Singular: { - isA: 'Noun' - }, - //a specific thing that's capitalized - ProperNoun: { - isA: 'Noun' - }, - // -- people - Person: { - isA: 'Singular' - }, - FirstName: { - isA: 'Person' - }, - MaleName: { - isA: 'FirstName' - }, - FemaleName: { - isA: 'FirstName' - }, - LastName: { - isA: 'Person' - }, - Honorific: { - isA: 'Noun' - }, - Place: { - isA: 'Singular' - }, - // -- places - Country: { - isA: 'Place' - }, - City: { - isA: 'Place' - }, - Region: { - isA: 'Place' - }, - Address: { - isA: 'Place' - }, - Organization: { - isA: 'Singular' - }, - SportsTeam: { - isA: 'Organization' - }, - Company: { - isA: 'Organization' - }, - School: { - isA: 'Organization' - }, - // - plural - Plural: { - isA: 'Noun' - }, - Uncountable: { - //(not plural or singular) - isA: 'Noun' - }, - Pronoun: { - isA: 'Noun' - }, - //a word for someone doing something -'plumber' - Actor: { - isA: 'Noun' - }, - //a gerund-as-noun - 'swimming' - Activity: { - isA: 'Noun' - }, - //'kilograms' - Unit: { - isA: 'Noun' - }, - //'Canadians' - Demonym: { - isA: 'Noun' - }, - //`john's` - Possessive: { - isA: 'Noun' - } -}; - -},{}],141:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = { - Value: {}, - Ordinal: { - isA: 'Value' - }, - Cardinal: { - isA: 'Value' - }, - Multiple: { - isA: 'Value' - }, - RomanNumeral: { - isA: 'Cardinal' - }, - Fraction: { - isA: 'Value' - }, - TextValue: { - isA: 'Value' - }, - NumericValue: { - isA: 'Value' - }, - NiceNumber: { - isA: 'Value' - }, - Money: {//isA: 'Cardinal' - }, - Percent: { - isA: 'Value' - } -}; - -},{}],142:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = { - Verb: { - isA: 'VerbPhrase' - }, - PresentTense: { - isA: 'Verb' - }, - Infinitive: { - isA: 'PresentTense' - }, - Gerund: { - isA: 'PresentTense' - }, - PastTense: { - isA: 'Verb' - }, - PerfectTense: { - isA: 'Verb' - }, - FuturePerfect: { - isA: 'Verb' - }, - Pluperfect: { - isA: 'Verb' - }, - Copula: { - isA: 'Verb' - }, - Modal: { - isA: 'Verb' - }, - Participle: { - isA: 'Verb' - }, - Particle: { - isA: 'Verb' - }, - PhrasalVerb: { - isA: 'Verb' - } -}; - -},{}],143:[function(_dereq_,module,exports){ -'use strict'; - -var fns = _dereq_('./paths').fns; - -var build_whitespace = _dereq_('./whitespace'); -var makeUID = _dereq_('./makeUID'); //normalization + var topk = function topk(doc) { + var list = doc.json({ + text: false, + terms: false, + reduced: true + }); // combine them + var obj = {}; + list.forEach(function (o) { + if (!obj[o.reduced]) { + o.count = 0; + obj[o.reduced] = o; + } -var addNormal = _dereq_('./methods/normalize/normalize').addNormal; + obj[o.reduced].count += 1; + }); + var arr = Object.keys(obj).map(function (k) { + return obj[k]; + }); // sort them -var addRoot = _dereq_('./methods/normalize/root'); + arr.sort(function (a, b) { + if (a.count > b.count) { + return -1; + } else if (a.count < b.count) { + return 1; + } -var Term = function Term(str, world) { - this.tags = {}; - this._text = fns.ensureString(str); // this.world = world; + return 0; + }); + return arr; + }; - Object.defineProperty(this, 'world', { - enumerable: false, - // hide it from for..in - value: world - }); // this.world = function() { - // return world; - // }; - //seperate whitespace from the text + var _topk = topk; - var parsed = build_whitespace(this._text); - this.whitespace = parsed.whitespace; - this._text = parsed.text; - this.parent = null; - this.silent_term = ''; - this.lumped = false; //normalize the _text + /** pretty-print the current document and its tags */ - addNormal(this); - addRoot(this); //has this term been modified + var debug_1 = function debug_1() { + _debug(this); + return this; + }; + /** some named output formats */ - this.dirty = false; //make a unique id for this term - this.uid = makeUID(this.normal); //getters/setters + var out = function out(method) { + if (method === 'text') { + return this.text(); + } - Object.defineProperty(this, 'text', { - get: function get() { - return this._text; - }, - set: function set(txt) { - txt = txt || ''; - this._text = txt.trim(); - this.dirty = true; // if (this._text !== txt) { - // console.log('|' + txt + '|'); - // console.log(build_whitespace(txt)); - // this.whitespace = build_whitespace(txt); - // console.log(this.whitespace); - // } + if (method === 'normal') { + return this.text('normal'); + } - this.normalize(); + if (method === 'json') { + return this.json(); } - }); //bit faster than .constructor.name or w/e - Object.defineProperty(this, 'isA', { - get: function get() { - return 'Term'; + if (method === 'offset' || method === 'offsets') { + return this.json({ + offset: true + }); } - }); -}; -/**run each time a new text is set */ + if (method === 'array') { + return this.json({ + terms: false + }).map(function (obj) { + return obj.text; + }); + } -Term.prototype.normalize = function () { - addNormal(this); - addRoot(this); - return this; -}; -/** where in the sentence is it? zero-based. */ + if (method === 'freq' || method === 'frequency') { + return _topk(this); + } + if (method === 'terms') { + var list = []; + this.json({ + text: false, + terms: { + text: true + } + }).forEach(function (obj) { + var terms = obj.terms.map(function (t) { + return t.text; + }); + terms = terms.filter(function (t) { + return t; + }); + list = list.concat(terms); + }); + return list; + } -Term.prototype.index = function () { - var ts = this.parentTerms; + if (method === 'tags') { + return this.list.map(function (p) { + return p.terms().reduce(function (h, t) { + h[t.clean || t.implicit] = Object.keys(t.tags); + return h; + }, {}); + }); + } - if (!ts) { - return null; - } + if (method === 'debug') { + _debug(this); + return this; + } - return ts.terms.indexOf(this); -}; -/** make a copy with no originals to the original */ + return this.text(); + }; + var _03Out = { + debug: debug_1, + out: out + }; -Term.prototype.clone = function () { - var term = new Term(this._text, this.world); - term.tags = fns.copy(this.tags); - term.whitespace = fns.copy(this.whitespace); - term.silent_term = this.silent_term; - return term; -}; + // compress a list of things by frequency + var topk$1 = function topk(list) { + var counts = {}; + list.forEach(function (a) { + counts[a] = counts[a] || 0; + counts[a] += 1; + }); + var arr = Object.keys(counts); + arr = arr.sort(function (a, b) { + if (counts[a] > counts[b]) { + return -1; + } else { + return 1; + } + }); // arr = arr.filter(a => counts[a] > 1) -_dereq_('./methods/misc')(Term); + return arr.map(function (a) { + return [a, counts[a]]; + }); + }; // remove implied tags, like 'Noun' when we have 'Plural' -_dereq_('./methods/out')(Term); -_dereq_('./methods/tag')(Term); + var reduceTags = function reduceTags(tags, world) { + var tagset = world.tags; + var implied = []; + tags.forEach(function (tag) { + if (tagset[tag] && tagset[tag].isA) { + implied = implied.concat(tagset[tag].isA); + } + }); + implied = implied.reduce(function (h, tag) { + h[tag] = true; + return h; + }, {}); + tags = tags.filter(function (tag) { + return !implied[tag]; + }); // tags -_dereq_('./methods/case')(Term); + return tags; + }; + /** store a parsed document for later use */ -_dereq_('./methods/punctuation')(Term); -module.exports = Term; + var export_1 = function export_1() { + var _this = this; -},{"./makeUID":144,"./methods/case":146,"./methods/misc":147,"./methods/normalize/normalize":149,"./methods/normalize/root":150,"./methods/out":153,"./methods/punctuation":156,"./methods/tag":158,"./paths":161,"./whitespace":162}],144:[function(_dereq_,module,exports){ -'use strict'; //this is a not-well-thought-out way to reduce our dependence on `object===object` original stuff -//generates a unique id for this term -//may need to change when the term really-transforms? not sure. + var phraseList = this.json({ + text: true, + trim: false, + terms: { + tags: true, + whitespace: true + } + }); // let phraseList = json.map(p => p.terms) + + var allTags = []; + phraseList.forEach(function (p) { + p.terms.forEach(function (t) { + // reduce redundant tags + var tags = reduceTags(t.tags, _this.world); + allTags = allTags.concat(tags); + }); + }); // compress the top tags + + allTags = topk$1(allTags); + var tagMap = {}; + allTags.forEach(function (a, i) { + tagMap[a[0]] = i; + }); //use index numbers instead of redundant tag-names + + phraseList = phraseList.map(function (p) { + var terms = p.terms.map(function (term) { + var tags = term.tags; + tags = reduceTags(tags, _this.world); + tags = tags.map(function (tag) { + return tagMap[tag]; + }); + tags = tags.join(','); + return tags; + }); + terms = terms.join('|'); + return [p.text, terms]; + }); + return { + tags: Object.keys(tagMap), + // words: {}, + list: phraseList + }; + }; -var uid = function uid(str) { - var nums = ''; + var _04Export = { + "export": export_1 + }; - for (var i = 0; i < 5; i++) { - nums += parseInt(Math.random() * 9, 10); - } + var methods$2 = { + /** alphabetical order */ + alpha: function alpha(a, b) { + var left = a.text('clean'); + var right = b.text('clean'); - return str + '-' + nums; -}; - -module.exports = uid; - -},{}],145:[function(_dereq_,module,exports){ -'use strict'; // const tagSet = require('../paths').tags; - -var boringTags = { - Auxiliary: 1, - Possessive: 1, - TitleCase: 1, - ClauseEnd: 1, - Comma: 1, - CamelCase: 1, - UpperCase: 1, - Hyphenated: 1, - VerbPhrase: 1, - EndBracket: 1, - StartBracket: 1, - Parentheses: 1, - Quotation: 1 -}; - -var bestTag = function bestTag(t) { - var tagSet = t.world.tags; - var tags = Object.keys(t.tags); - tags = tags.sort(); //alphabetical, first - //then sort by #of parent tags - - tags = tags.sort(function (a, b) { - //bury the tags we dont want - if (!tagSet[a]) { - return 1; - } + if (left < right) { + return -1; + } - if (boringTags[b] || !tagSet[b]) { - return -1; - } + if (left > right) { + return 1; + } - if (tagSet[a].downward.length > tagSet[b].downward.length) { - return 1; - } + return 0; + }, - return 1; - }); - return tags[0]; -}; + /** count the # of characters of each match */ + length: function length(a, b) { + var left = a.text().trim().length; + var right = b.text().trim().length; -module.exports = bestTag; + if (left < right) { + return 1; + } -},{}],146:[function(_dereq_,module,exports){ -'use strict'; + if (left > right) { + return -1; + } -var addMethods = function addMethods(Term) { - var methods = { - toUpperCase: function toUpperCase() { - this.text = this._text.toUpperCase(); - this.tag('#UpperCase', 'toUpperCase'); - return this; - }, - toLowerCase: function toLowerCase() { - this.text = this._text.toLowerCase(); - this.unTag('#TitleCase'); - this.unTag('#UpperCase'); - return this; - }, - toTitleCase: function toTitleCase() { - this.text = this._text.replace(/^ *[a-z]/, function (x) { - return x.toUpperCase(); - }); - this.tag('#TitleCase', 'toTitleCase'); - return this; + return 0; }, - //(camelCase() is handled in `./terms` ) - /** is it titlecased because it deserves it? Like a person's name? */ - needsTitleCase: function needsTitleCase() { - var titleCases = ['Person', 'Place', 'Organization', 'Acronym', 'UpperCase', 'Currency', 'RomanNumeral', 'Month', 'WeekDay', 'Holiday', 'Demonym']; + /** count the # of terms in each match */ + wordCount: function wordCount(a, b) { + var left = a.wordCount(); + var right = b.wordCount(); - for (var i = 0; i < titleCases.length; i++) { - if (this.tags[titleCases[i]]) { - return true; - } - } //specific words that keep their titlecase - //https://en.wikipedia.org/wiki/Capitonym + if (left < right) { + return 1; + } + + if (left > right) { + return -1; + } + return 0; + } + }; + /** sort by # of duplicates in the document*/ + + var byFreq = function byFreq(doc) { + var counts = {}; + var options = { + "case": true, + punctuation: false, + whitespace: true, + unicode: true + }; + doc.list.forEach(function (p) { + var str = p.text(options); + counts[str] = counts[str] || 0; + counts[str] += 1; + }); // sort by freq - var irregulars = ['i', 'god', 'allah']; + doc.list.sort(function (a, b) { + var left = counts[a.text(options)]; + var right = counts[b.text(options)]; - for (var _i = 0; _i < irregulars.length; _i++) { - if (this.normal === irregulars[_i]) { - return true; - } + if (left < right) { + return 1; } - return false; - } - }; //hook them into result.proto + if (left > right) { + return -1; + } - Object.keys(methods).forEach(function (k) { - Term.prototype[k] = methods[k]; - }); - return Term; -}; + return 0; + }); + return doc; + }; // order results 'chronologically', or document-order -module.exports = addMethods; -},{}],147:[function(_dereq_,module,exports){ -'use strict'; + var sortSequential = function sortSequential(doc) { + var order = {}; + doc.json({ + terms: { + offset: true + } + }).forEach(function (o) { + order[o.terms[0].id] = o.terms[0].offset.start; + }); + doc.list = doc.list.sort(function (a, b) { + if (order[a.start] > order[b.start]) { + return 1; + } else if (order[a.start] < order[b.start]) { + return -1; + } -var _isAcronym = _dereq_('./normalize/isAcronym'); + return 0; + }); + return doc; + }; //aliases -var _bestTag = _dereq_('./bestTag'); //regs- + methods$2.alphabetical = methods$2.alpha; + methods$2.wordcount = methods$2.wordCount; // aliases for sequential ordering -var hasVowel = /[aeiouy]/i; -var hasLetter = /[a-z]/; -var hasNumber = /[0-9]/; + var seqNames = { + index: true, + sequence: true, + seq: true, + sequential: true, + chron: true, + chronological: true + }; + /** re-arrange the order of the matches (in place) */ -var addMethods = function addMethods(Term) { - var methods = { - /** which tag best-represents this term?*/ - bestTag: function bestTag() { - return _bestTag(this); - }, + var sort = function sort(input) { + input = input || 'alpha'; //do this one up-front - /** is this term like F.B.I. or NBA */ - isAcronym: function isAcronym() { - return _isAcronym(this._text); - }, + if (input === 'freq' || input === 'frequency' || input === 'topk') { + return byFreq(this); + } - /** check if it is word-like in english */ - isWord: function isWord() { - var t = this; //assume a contraction produces a word-word + if (seqNames.hasOwnProperty(input)) { + return sortSequential(this); + } - if (t.silent_term) { - return true; - } //no letters or numbers + input = methods$2[input] || input; // apply sort method on each phrase + if (typeof input === 'function') { + this.list = this.list.sort(input); + return this; + } - if (/[a-z|A-Z|0-9]/.test(t.text) === false) { - return false; - } //has letters, but with no vowels + return this; + }; + /** reverse the order of the matches, but not the words */ - if (t.normal.length > 3 && hasLetter.test(t.normal) === true && hasVowel.test(t.normal) === false && t.isAcronym() === false) { - return false; - } //has numbers but not a 'value' + var reverse = function reverse() { + var list = [].concat(this.list); + list = list.reverse(); + return this.buildFrom(list); + }; + /** remove any duplicate matches */ - if (hasNumber.test(t.normal) === true && t.tags.hasOwnProperty('Value') === false) { - //s4e - if (/[a-z][0-9][a-z]/.test(t.normal) === true) { - return false; - } //ensure it looks like a 'value' eg '-$4,231.00' - // if (/^([$-])*?([0-9,\.])*?([s\$%])*?$/.test(t.normal) === false) { - // return false; - // } + var unique$6 = function unique() { + var list = [].concat(this.list); + var obj = {}; + list = list.filter(function (p) { + var str = p.text('reduced').trim(); + if (obj.hasOwnProperty(str) === true) { + return false; } + obj[str] = true; return true; - } - }; //hook them into result.proto - - Object.keys(methods).forEach(function (k) { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; + }); + return this.buildFrom(list); + }; -},{"./bestTag":145,"./normalize/isAcronym":148}],148:[function(_dereq_,module,exports){ -'use strict'; //regs - + var _01Sort = { + sort: sort, + reverse: reverse, + unique: unique$6 + }; -var periodAcronym = /([A-Z]\.)+[A-Z]?,?$/; -var oneLetterAcronym = /^[A-Z]\.,?$/; -var noPeriodAcronym = /[A-Z]{2}('s|,)?$/; -/** does it appear to be an acronym, like FBI or M.L.B. */ + var isPunct = /[\[\]{}⟨⟩:,،、‒–—―…‹›«»‐\-;\/⁄·*\•^†‡°¡¿※№÷׺ª%‰=‱¶§~|‖¦©℗®℠™¤₳฿]/g; + var quotes = /['‘’“”"′″‴]+/g; + var methods$3 = { + // cleanup newlines and extra spaces + whitespace: function whitespace(doc) { + var termArr = doc.list.map(function (ts) { + return ts.terms(); + }); + termArr.forEach(function (terms, o) { + terms.forEach(function (t, i) { + // keep dashes between words + if (t.hasDash() === true) { + t.post = ' - '; + return; + } // remove existing spaces -var isAcronym = function isAcronym(str) { - //like N.D.A - if (periodAcronym.test(str) === true) { - return true; - } //like 'F.' + t.pre = t.pre.replace(/\s/g, ''); + t.post = t.post.replace(/\s/g, ''); //last word? ensure there's a next sentence. - if (oneLetterAcronym.test(str) === true) { - return true; - } //like NDA + if (terms.length - 1 === i && !termArr[o + 1]) { + return; + } // no extra spaces for contractions - if (noPeriodAcronym.test(str) === true) { - return true; - } + if (t.implicit && Boolean(t.text) === true) { + return; + } // no extra spaces for hyphenated words - return false; -}; -module.exports = isAcronym; + if (t.hasHyphen() === true) { + return; + } -},{}],149:[function(_dereq_,module,exports){ -'use strict'; + t.post += ' '; + }); + }); + }, + punctuation: function punctuation(termList) { + termList.forEach(function (t) { + // space between hyphenated words + if (t.hasHyphen() === true) { + t.post = ' '; + } -var killUnicode = _dereq_('./unicode'); + t.pre = t.pre.replace(isPunct, ''); + t.post = t.post.replace(isPunct, ''); // elipses -var isAcronym = _dereq_('./isAcronym'); //some basic operations on a string to reduce noise + t.post = t.post.replace(/\.\.\./, ''); // only allow one exclamation + if (/!/.test(t.post) === true) { + t.post = t.post.replace(/!/g, ''); + t.post = '!' + t.post; + } // only allow one question mark -exports.normalize = function (str) { - str = str || ''; - str = str.toLowerCase(); - str = str.trim(); - var original = str; //(very) rough ASCII transliteration - bjŏrk -> bjork - str = killUnicode(str); //#tags, @mentions + if (/\?/.test(t.post) === true) { + t.post = t.post.replace(/[\?!]*/, ''); + t.post = '?' + t.post; + } + }); + }, + unicode: function unicode(termList) { + termList.forEach(function (t) { + if (t.isImplicit() === true) { + return; + } - str = str.replace(/^[#@]/, ''); //punctuation + t.text = unicode_1(t.text); + }); + }, + quotations: function quotations(termList) { + termList.forEach(function (t) { + t.post = t.post.replace(quotes, ''); + t.pre = t.pre.replace(quotes, ''); + }); + }, + adverbs: function adverbs(doc) { + doc.match('#Adverb').not('(not|nary|seldom|never|barely|almost|basically|so)').remove(); + }, + // remove the '.' from 'Mrs.' (safely) + abbreviations: function abbreviations(doc) { + doc.list.forEach(function (ts) { + var terms = ts.terms(); + terms.forEach(function (t, i) { + if (t.tags.Abbreviation === true && terms[i + 1]) { + t.post = t.post.replace(/^\./, ''); + } + }); + }); + } + }; + var _methods = methods$3; + + var defaults = { + // light + whitespace: true, + unicode: true, + punctuation: true, + emoji: true, + acronyms: true, + abbreviations: true, + // medium + "case": false, + contractions: false, + parentheses: false, + quotations: false, + adverbs: false, + // heavy (loose legibility) + possessives: false, + verbs: false, + nouns: false, + honorifics: false // pronouns: true, - str = str.replace(/[,;.!?]+$/, ''); // coerce single curly quotes + }; + var mapping$1 = { + light: {}, + medium: { + "case": true, + contractions: true, + parentheses: true, + quotations: true, + adverbs: true + } + }; + mapping$1.heavy = Object.assign({}, mapping$1.medium, { + possessives: true, + verbs: true, + nouns: true, + honorifics: true + }); + /** common ways to clean-up the document, and reduce noise */ - str = str.replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g, '\''); // coerce double curly quotes + var normalize = function normalize(options) { + options = options || {}; // support named forms - str = str.replace(/[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g, '"'); //coerce Unicode ellipses + if (typeof options === 'string') { + options = mapping$1[options] || {}; + } // set defaults - str = str.replace(/\u2026/g, '...'); //en-dash - str = str.replace(/\u2013/g, '-'); //lookin'->looking (make it easier for conjugation) + options = Object.assign({}, defaults, options); // clear the cache - if (/[a-z][^aeiou]in['’]$/.test(str) === true) { - str = str.replace(/in['’]$/, 'ing'); - } //turn re-enactment to reenactment + this.uncache(); + var termList = this.termList(); // lowercase things + if (options["case"]) { + this.toLowerCase(); + } //whitespace - if (/^(re|un)-?[^aeiou]./.test(str) === true) { - str = str.replace('-', ''); - } //strip leading & trailing grammatical punctuation + if (options.whitespace) { + _methods.whitespace(this); + } // unicode: é -> e - if (/^[:;]/.test(str) === false) { - str = str.replace(/\.{3,}$/g, ''); - str = str.replace(/['",\.!:;\?\)]+$/g, ''); - str = str.replace(/^['"\(]+/g, ''); - } //do this again.. + if (options.unicode) { + _methods.unicode(termList); + } //punctuation - keep sentence punctation, quotes, parenths - str = str.trim(); //oh shucks, - if (str === '') { - str = original; - } + if (options.punctuation) { + _methods.punctuation(termList); + } // remove ':)' - return str; -}; - -exports.addNormal = function (term) { - var str = term._text || ''; - str = exports.normalize(str); //compact acronyms - - if (isAcronym(term._text)) { - str = str.replace(/\./g, ''); - } //nice-numbers - - - str = str.replace(/([0-9]),([0-9])/g, '$1$2'); - term.normal = str; -}; // console.log(normalize('Dr. V Cooper')); - -},{"./isAcronym":148,"./unicode":151}],150:[function(_dereq_,module,exports){ -'use strict'; // - -var rootForm = function rootForm(term) { - var str = term.normal || term.silent_term || ''; //handle apostrophes and stuff (go further than normalize()) - - str = str.replace(/'s\b/, ''); - str = str.replace(/'$/, ''); - term.root = str; -}; - -module.exports = rootForm; - -},{}],151:[function(_dereq_,module,exports){ -'use strict'; //a hugely-ignorant, and widely subjective transliteration of latin, cryllic, greek unicode characters to english ascii. -//approximate visual (not semantic or phonetic) relationship between unicode and ascii characters -//http://en.wikipedia.org/wiki/List_of_Unicode_characters -//https://docs.google.com/spreadsheet/ccc?key=0Ah46z755j7cVdFRDM1A2YVpwa1ZYWlpJM2pQZ003M0E - -var compact = { - '!': '¡', - '?': '¿Ɂ', - '"': '“”"❝❞', - '\'': '‘‛❛❜', - '-': '—–', - 'a': 'ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАДадѦѧӐӑӒӓƛɅæ', - 'b': 'ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬбвъьѢѣҌҍҔҕƥƾ', - 'c': '¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾϿЄСсєҀҁҪҫ', - 'd': 'ÐĎďĐđƉƊȡƋƌǷ', - 'e': 'ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ', - 'f': 'ƑƒϜϝӺӻҒғӶӷſ', - 'g': 'ĜĝĞğĠġĢģƓǤǥǦǧǴǵ', - 'h': 'ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ', - 'I': 'ÌÍÎÏ', - 'i': 'ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії', - 'j': 'ĴĵǰȷɈɉϳЈј', - 'k': 'ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ', - 'l': 'ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ', - 'm': 'ΜϺϻМмӍӎ', - 'n': 'ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ', - 'o': 'ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ¤ƍΏ', - 'p': 'ƤƿΡρϷϸϼРрҎҏÞ', - 'q': 'Ɋɋ', - 'r': 'ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ', - 's': 'ŚśŜŝŞşŠšƧƨȘșȿςϚϛϟϨϩЅѕ', - 't': 'ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮϯТт҂Ҭҭ', - 'u': 'µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύϑЏЦЧцџҴҵҶҷӋӌӇӈ', - 'v': 'νѴѵѶѷ', - 'w': 'ŴŵƜωώϖϢϣШЩшщѡѿ', - 'x': '×ΧχϗϰХхҲҳӼӽӾӿ', - 'y': 'ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ', - 'z': 'ŹźŻżŽžƩƵƶȤȥɀΖζ' -}; //decompress data into two hashes - -var unicode = {}; -Object.keys(compact).forEach(function (k) { - compact[k].split('').forEach(function (s) { - unicode[s] = k; - }); -}); -var killUnicode = function killUnicode(str) { - var chars = str.split(''); - chars.forEach(function (s, i) { - if (unicode[s]) { - chars[i] = unicode[s]; - } - }); - return chars.join(''); -}; + if (options.emoji) { + this.remove('(#Emoji|#Emoticon)'); + } // 'f.b.i.' -> 'FBI' -module.exports = killUnicode; // console.log(killUnicode('bjŏȒk—Ɏó')); -},{}],152:[function(_dereq_,module,exports){ -'use strict'; + if (options.acronyms) { + this.acronyms().strip(); // .toUpperCase() + } // remove period from abbreviations -var paths = _dereq_('../../paths'); -var fns = paths.fns; -var tagset = paths.tags; //a nicer logger for the client-side + if (options.abbreviations) { + _methods.abbreviations(this); + } // --Medium methods-- + // `isn't` -> 'is not' -var clientSide = function clientSide(t) { - var color = 'silver'; - var tags = Object.keys(t.tags); - for (var i = 0; i < tags.length; i++) { - if (tagset[tags[i]] && tagset[tags[i]].color) { - color = tagset[tags[i]].color; - break; - } - } + if (options.contraction || options.contractions) { + this.contractions().expand(); + } // '(word)' -> 'word' - var word = fns.leftPad(t.text, 12); - word += ' ' + tags; - console.log('%c ' + word, 'color: ' + color); -}; -module.exports = clientSide; + if (options.parentheses) { + this.parentheses().unwrap(); + } // remove "" punctuation -},{"../../paths":161}],153:[function(_dereq_,module,exports){ -'use strict'; -function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + if (options.quotations || options.quotes) { + _methods.quotations(termList); + } // remove any un-necessary adverbs -var renderHtml = _dereq_('./renderHtml'); -var clientDebug = _dereq_('./client'); + if (options.adverbs) { + _methods.adverbs(this); + } // --Heavy methods-- + // `cory hart's -> cory hart' -var serverDebug = _dereq_('./server'); -var methods = { - /** a pixel-perfect reproduction of the input, with whitespace preserved */ - text: function text(r) { - return (r.whitespace.before || '') + r._text + (r.whitespace.after || ''); - }, + if (options.possessive || options.possessives) { + this.possessives().strip(); + } // 'he walked' -> 'he walk' - /** a lowercased, punctuation-cleaned, whitespace-trimmed version of the word */ - normal: function normal(r) { - return r.normal; - }, - /** even-more normalized than normal */ - root: function root(r) { - return r.root || r.normal; - }, + if (options.verbs) { + this.verbs().toInfinitive(); + } // 'three dogs' -> 'three dog' - /** the &encoded term in a span element, with POS as classNames */ - html: function html(r) { - return renderHtml(r); - }, - /** a simplified response for Part-of-Speech tagging*/ - tags: function tags(r) { - return { - text: r.text, - normal: r.normal, - tags: Object.keys(r.tags) - }; - }, + if (options.nouns || options.plurals) { + this.nouns().toSingular(); + } // remove 'Mr.' from 'Mr John Smith' - /** check-print information for the console */ - debug: function debug(t) { - if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object') { - clientDebug(t); - } else { - serverDebug(t); - } - } -}; -var addMethods = function addMethods(Term) { - //hook them into result.proto - Term.prototype.out = function (fn) { - if (!methods[fn]) { - fn = 'text'; + if (options.honorifics) { + this.remove('#Honorific'); } - return methods[fn](this); + return this; }; - return Term; -}; - -module.exports = addMethods; - -},{"./client":152,"./renderHtml":154,"./server":155}],154:[function(_dereq_,module,exports){ -'use strict'; //turn xml special characters into apersand-encoding. -//i'm not sure this is perfectly safe. - -var escapeHtml = function escapeHtml(s) { - var HTML_CHAR_MAP = { - '<': '<', - '>': '>', - '&': '&', - '"': '"', - '\'': ''', - ' ': ' ' + var _02Normalize = { + normalize: normalize }; - return s.replace(/[<>&"' ]/g, function (ch) { - return HTML_CHAR_MAP[ch]; - }); -}; //remove html elements already in the text -//not tested! -//http://stackoverflow.com/questions/295566/sanitize-rewrite-html-on-the-client-side - -var sanitize = function sanitize(html) { - var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*'; - var tagOrComment = new RegExp('<(?:' // Comment body. - + '!--(?:(?:-*[^->])*--+|-?)' // Special "raw text" elements whose content should be elided. - + '|script\\b' + tagBody + '>[\\s\\S]*?[\\s\\S]*?', 'gi'); - var oldHtml; - - do { - oldHtml = html; - html = html.replace(tagOrComment, ''); - } while (html !== oldHtml); + var _03Split = createCommonjsModule(function (module, exports) { + /** return a Document with three parts for every match + * seperate everything before the word, as a new phrase + */ + exports.splitOn = function (reg) { + // if there's no match, split parent, instead + if (!reg) { + var parent = this.parent(); + return parent.splitOn(this); + } //start looking for a match.. - return html.replace(/' + text + ''; - return escapeHtml(t.whitespace.before) + el + escapeHtml(t.whitespace.after); -}; + if (foundEm.length === 0) { + matches.push(p); + return; + } // we found something here. -module.exports = renderHtml; -},{}],155:[function(_dereq_,module,exports){ -'use strict'; + var carry = p; + foundEm.forEach(function (found) { + var parts = carry.splitOn(found); // add em in -var fns = _dereq_('../../paths').fns; //pretty-print a term on the nodejs console + if (parts.before) { + matches.push(parts.before); + } + if (parts.match) { + matches.push(parts.match); + } // start matching now on the end -var serverDebug = function serverDebug(t) { - var tags = Object.keys(t.tags).map(function (tag) { - return fns.printTag(tag); - }).join(', '); - var word = t.text; - word = '\'' + fns.yellow(word || '-') + '\''; - var silent = ''; - if (t.silent_term) { - silent = '[' + t.silent_term + ']'; - } + carry = parts.after; + }); // add that last part - word = fns.leftPad(word, 20); - word += fns.leftPad(silent, 8); - console.log(' ' + word + ' ' + ' - ' + tags); -}; + if (carry) { + matches.push(carry); + } + }); + return this.buildFrom(matches); + }; + /** return a Document with two parts for every match + * seperate everything after the word, as a new phrase + */ -module.exports = serverDebug; -},{"../../paths":161}],156:[function(_dereq_,module,exports){ -'use strict'; // const endPunct = /([^\/,:;.()!?]{0,1})([\/,:;.()!?]+)$/i; + exports.splitAfter = function (reg) { + // if there's no match, split parent, instead + if (!reg) { + var parent = this.parent(); + return parent.splitAfter(this); + } // start looking for our matches -var endPunct = /([a-z0-9 ])([,:;.!?]+)$/i; //old -var addMethods = function addMethods(Term) { - var methods = { - /** the punctuation at the end of this term*/ - getPunctuation: function getPunctuation() { - var m = this.text.match(endPunct); + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + var foundEm = p.match(regs); //no match here, add full sentence - if (m) { - return m[2]; - } + if (foundEm.length === 0) { + matches.push(p); + return; + } // we found something here. - m = this.whitespace.after.match(endPunct); - if (m) { - return m[2]; - } + var carry = p; + foundEm.forEach(function (found) { + var parts = carry.splitOn(found); // add em in - return null; - }, - setPunctuation: function setPunctuation(punct) { - this.killPunctuation(); - this.text += punct; + if (parts.before && parts.match) { + // merge these two together + parts.before.length += parts.match.length; + matches.push(parts.before); + } else if (parts.match) { + matches.push(parts.match); + } // start matching now on the end - if (punct === ',') { - this.tags.Comma = true; - } - return this; - }, + carry = parts.after; + }); // add that last part - /** check if the term ends with a comma */ - hasComma: function hasComma() { - if (this.getPunctuation() === ',') { - return true; - } + if (carry) { + matches.push(carry); + } + }); + return this.buildFrom(matches); + }; - return false; - }, - killPunctuation: function killPunctuation() { - this.text = this._text.replace(endPunct, '$1'); - delete this.tags.Comma; - delete this.tags.ClauseEnd; - return this; - } - }; //hook them into result.proto + exports.split = exports.splitAfter; //i guess? - Object.keys(methods).forEach(function (k) { - Term.prototype[k] = methods[k]; - }); - return Term; -}; + /** return a Document with two parts for every match */ -module.exports = addMethods; + exports.splitBefore = function (reg) { + // if there's no match, split parent, instead + if (!reg) { + var parent = this.parent(); + return parent.splitBefore(this); + } //start looking for a match.. -},{}],157:[function(_dereq_,module,exports){ -'use strict'; //recursively-check compatibility of this tag and term -var canBe = function canBe(term, tag) { - var tagset = term.world.tags; //fail-fast + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + var foundEm = p.match(regs); //no match here, add full sentence - if (tagset[tag] === undefined) { - return true; - } //loop through tag's contradictory tags + if (foundEm.length === 0) { + matches.push(p); + return; + } // we found something here. - var enemies = tagset[tag].notA || []; + var carry = p; + foundEm.forEach(function (found) { + var parts = carry.splitOn(found); // add before part in - for (var i = 0; i < enemies.length; i++) { - if (term.tags[enemies[i]] === true) { - return false; - } - } + if (parts.before) { + matches.push(parts.before); + } // merge match+after - if (tagset[tag].isA !== undefined) { - return canBe(term, tagset[tag].isA); //recursive - } - return true; -}; + if (parts.match && parts.after) { + parts.match.length += parts.after.length; + } // start matching now on the end -module.exports = canBe; -},{}],158:[function(_dereq_,module,exports){ -'use strict'; + carry = parts.match; + }); // add that last part -var setTag = _dereq_('./setTag'); + if (carry) { + matches.push(carry); + } + }); + return this.buildFrom(matches); + }; + /** split a document into labeled sections */ -var _unTag = _dereq_('./unTag'); -var _canBe = _dereq_('./canBe'); //symbols used in sequential taggers which mean 'do nothing' -//.tag('#Person #Place . #City') + exports.segment = function (regs, options) { + regs = regs || {}; + options = options || { + text: true + }; + var doc = this; + var keys = Object.keys(regs); // split em + keys.forEach(function (k) { + doc = doc.splitOn(k); + }); //add labels for each section -var ignore = { - '.': true -}; + doc.list.forEach(function (p) { + for (var i = 0; i < keys.length; i += 1) { + if (p.has(keys[i])) { + p.segment = regs[keys[i]]; + return; + } + } + }); + return doc.list.map(function (p) { + var res = p.json(options); + res.segment = p.segment || null; + return res; + }); + }; + }); + var _03Split_1 = _03Split.splitOn; + var _03Split_2 = _03Split.splitAfter; + var _03Split_3 = _03Split.split; + var _03Split_4 = _03Split.splitBefore; + var _03Split_5 = _03Split.segment; + + var eachTerm = function eachTerm(doc, fn) { + var world = doc.world; + doc.list.forEach(function (p) { + p.terms().forEach(function (t) { + return t[fn](world); + }); + }); + return doc; + }; + /** turn every letter of every term to lower-cse */ -var addMethods = function addMethods(Term) { - var methods = { - /** set the term as this part-of-speech */ - tag: function tag(_tag, reason) { - if (ignore[_tag] !== true) { - setTag(this, _tag, reason); - } - }, - /** remove this part-of-speech from the term*/ - unTag: function unTag(tag, reason) { - if (ignore[tag] !== true) { - _unTag(this, tag, reason); - } - }, + var toLowerCase = function toLowerCase() { + return eachTerm(this, 'toLowerCase'); + }; + /** turn every letter of every term to upper case */ - /** is this tag compatible with this word */ - canBe: function canBe(tag) { - tag = tag || ''; - if (typeof tag === 'string') { - //everything can be '.' - if (ignore[tag] === true) { - return true; - } + var toUpperCase = function toUpperCase() { + return eachTerm(this, 'toUpperCase'); + }; + /** upper-case the first letter of each term */ - tag = tag.replace(/^#/, ''); - } - return _canBe(this, tag); - } - }; //hook them into term.prototype + var toTitleCase = function toTitleCase() { + this.tag('TitleCase'); + return eachTerm(this, 'toTitleCase'); + }; + /** remove whitespace and title-case each term */ - Object.keys(methods).forEach(function (k) { - Term.prototype[k] = methods[k]; - }); - return Term; -}; -module.exports = addMethods; + var toCamelCase = function toCamelCase() { + this.list.forEach(function (p) { + //remove whitespace + var terms = p.terms(); + terms.forEach(function (t, i) { + if (i !== 0) { + t.toTitleCase(); + } -},{"./canBe":157,"./setTag":159,"./unTag":160}],159:[function(_dereq_,module,exports){ -'use strict'; //set a term as a particular Part-of-speech + if (i !== terms.length - 1) { + t.post = ''; + } + }); + }); // this.tag('#CamelCase', 'toCamelCase') -var path = _dereq_('../../paths'); + return this; + }; -var log = path.log; -var fns = path.fns; + var _04Case = { + toLowerCase: toLowerCase, + toUpperCase: toUpperCase, + toTitleCase: toTitleCase, + toCamelCase: toCamelCase + }; -var unTag = _dereq_('./unTag'); // const tagset = path.tags; -// const tagset = require('../../../tagset'); + var _05Whitespace = createCommonjsModule(function (module, exports) { + /** add this punctuation or whitespace before each match: */ + exports.pre = function (str) { + if (str === undefined) { + return this.list[0].terms(0).pre; + } + this.list.forEach(function (p) { + var term = p.terms(0); + term.pre = str; + }); + return this; + }; + /** add this punctuation or whitespace after each match: */ -var putTag = function putTag(term, tag, reason) { - var tagset = term.world.tags; - tag = tag.replace(/^#/, ''); //already got this - if (term.tags[tag] === true) { - return; - } + exports.post = function (str) { + // return array of post strings + if (str === undefined) { + return this.list.map(function (p) { + var terms = p.terms(); + var term = terms[terms.length - 1]; + return term.post; + }); + } // set post string on all ends - term.tags[tag] = true; - log.tag(term, tag, reason); //extra logic per-each POS - if (tagset[tag]) { - //drop any conflicting tags - var enemies = tagset[tag].notA || []; + this.list.forEach(function (p) { + var terms = p.terms(); + var term = terms[terms.length - 1]; + term.post = str; + }); + return this; + }; + /** remove start and end whitespace */ - for (var i = 0; i < enemies.length; i++) { - if (term.tags[enemies[i]] === true) { - unTag(term, enemies[i], reason); - } - } //apply implicit tags + exports.trim = function () { + this.list = this.list.map(function (p) { + return p.trim(); + }); + return this; + }; + /** connect words with hyphen, and remove whitespace */ - if (tagset[tag].isA) { - var doAlso = tagset[tag].isA; - if (term.tags[doAlso] !== true) { - putTag(term, doAlso, ' --> ' + tag); //recursive - } - } - } -}; //give term this tag + exports.hyphenate = function () { + this.list.forEach(function (p) { + var terms = p.terms(); //remove whitespace + terms.forEach(function (t, i) { + if (i !== 0) { + t.pre = ''; + } -var wrap = function wrap(term, tag, reason) { - if (!term || !tag) { - return; - } + if (terms[i + 1]) { + t.post = '-'; + } + }); + }); + return this; + }; + /** remove hyphens between words, and set whitespace */ - var tagset = term.world.tags; //handle multiple tags - if (fns.isArray(tag)) { - tag.forEach(function (t) { - return putTag(term, t, reason); - }); //recursive + exports.dehyphenate = function () { + var hasHyphen = /(-|–|—)/; + this.list.forEach(function (p) { + var terms = p.terms(); //remove whitespace - return; - } + terms.forEach(function (t) { + if (hasHyphen.test(t.post)) { + t.post = ' '; + } + }); + }); + return this; + }; - putTag(term, tag, reason); //add 'extra' tag (for some special tags) + exports.deHyphenate = exports.dehyphenate; + /** add quotations around these matches */ + + exports.toQuotations = function (start, end) { + start = start || "\""; + end = end || "\""; + this.list.forEach(function (p) { + var terms = p.terms(); + terms[0].pre = start + terms[0].pre; + var last = terms[terms.length - 1]; + last.post = end + last.post; + }); + return this; + }; - if (tagset[tag] && tagset[tag].also !== undefined) { - putTag(term, tagset[tag].also, reason); - } -}; + exports.toQuotation = exports.toQuotations; + /** add brackets around these matches */ + + exports.toParentheses = function (start, end) { + start = start || "("; + end = end || ")"; + this.list.forEach(function (p) { + var terms = p.terms(); + terms[0].pre = start + terms[0].pre; + var last = terms[terms.length - 1]; + last.post = end + last.post; + }); + return this; + }; + }); + var _05Whitespace_1 = _05Whitespace.pre; + var _05Whitespace_2 = _05Whitespace.post; + var _05Whitespace_3 = _05Whitespace.trim; + var _05Whitespace_4 = _05Whitespace.hyphenate; + var _05Whitespace_5 = _05Whitespace.dehyphenate; + var _05Whitespace_6 = _05Whitespace.deHyphenate; + var _05Whitespace_7 = _05Whitespace.toQuotations; + var _05Whitespace_8 = _05Whitespace.toQuotation; + var _05Whitespace_9 = _05Whitespace.toParentheses; + + /** make all phrases into one phrase */ + var join = function join(str) { + // clear the cache + this.uncache(); // make one large phrase - 'main' + + var main = this.list[0]; + var before = main.length; + var removed = {}; + + for (var i = 1; i < this.list.length; i++) { + var p = this.list[i]; + removed[p.start] = true; + var term = main.lastTerm(); // add whitespace between them + + if (str) { + term.post += str; + } // main -> p + + + term.next = p.start; // main <- p + + p.terms(0).prev = term.id; + main.length += p.length; + } // parents are bigger than than their children. + // when we increase a child, we increase their parent too. + + + var increase = main.length - before; + this.parents().forEach(function (doc) { + // increase length on each effected phrase + doc.list.forEach(function (p) { + var terms = p.terms(); + + for (var _i = 0; _i < terms.length; _i++) { + if (terms[_i].id === main.start) { + p.length += increase; + break; + } + } + }); // remove redundant phrases now -module.exports = wrap; + doc.list = doc.list.filter(function (p) { + return removed[p.start] !== true; + }); + }); // return one major phrase -},{"../../paths":161,"./unTag":160}],160:[function(_dereq_,module,exports){ -'use strict'; //set a term as a particular Part-of-speech + return this.buildFrom([main]); + }; -var path = _dereq_('../../paths'); + var _06Join = { + join: join + }; -var log = path.log; //remove a tag from a term + var postPunct = /[,\)"';:\-–—\.…]/; // const irregulars = { + // 'will not': `won't`, + // 'i am': `i'm`, + // } -var unTag = function unTag(term, tag, reason) { - var tagset = term.world.tags; + var setContraction = function setContraction(m, suffix) { + if (!m.found) { + return; + } - if (term.tags[tag]) { - log.unTag(term, tag, reason); - delete term.tags[tag]; //delete downstream tags too + var terms = m.termList(); //avoid any problematic punctuation - if (tagset[tag]) { - var also = tagset[tag].downward; + for (var i = 0; i < terms.length - 1; i++) { + var t = terms[i]; - for (var i = 0; i < also.length; i++) { - unTag(term, also[i], ' - - - '); + if (postPunct.test(t.post)) { + return; } - } - } -}; + } // set them as implict -var wrap = function wrap(term, tag, reason) { - if (!term || !tag) { - return; - } //support '*' flag - remove all-tags - - - if (tag === '*') { - term.tags = {}; - return; - } //remove this tag + terms.forEach(function (t) { + t.implicit = t.clean; + }); // perform the contraction - unTag(term, tag, reason); - return; -}; + terms[0].text += suffix; // clean-up the others -module.exports = wrap; + terms.slice(1).forEach(function (t) { + t.text = ''; + }); -},{"../../paths":161}],161:[function(_dereq_,module,exports){ -"use strict"; + for (var _i = 0; _i < terms.length - 1; _i++) { + var _t = terms[_i]; + _t.post = _t.post.replace(/ /, ''); + } + }; + /** turn 'i am' into i'm */ -module.exports = { - fns: _dereq_('../fns'), - log: _dereq_('../log'), - tags: _dereq_('../tags') -}; -},{"../fns":3,"../log":6,"../tags":137}],162:[function(_dereq_,module,exports){ -'use strict'; //punctuation regs- are we having fun yet? + var contract = function contract() { + var doc = this.not('@hasContraction'); // we are -> we're -var before = /^([\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]|\x2D+|\.\.+|\/|"|"|\uFF02|'|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\xAB|\u2039|\u2035|\u2036|\u2037|\u301D|`|\u301F)+/; // const after = /(\s+|-+|\.\.+|"|\u0022|\uFF02|\u0027|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4)+$/u; + var m = doc.match('(we|they|you) are'); + setContraction(m, "'re"); // they will -> they'll -var afterSoft = /([\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+|\x2D+|\.\.+|"|"|\uFF02|'|\u201D|\u2019|\xBB|\u203A|\u2032|\u2033|\u2034|\u301E|\xB4)+[ !,\.;\?]*$/; -var minusNumber = /^( *)-(\$|€|¥|£)?([0-9])/; //seperate the 'meat' from the trailing/leading whitespace. -//works in concert with ./src/text/tokenize.js + m = doc.match('(he|she|they|it|we|you) will'); + setContraction(m, "'ll"); // she is -> she's -var build_whitespace = function build_whitespace(str) { - var whitespace = { - before: '', - after: '' - }; //get before punctuation/whitespace - //mangle 'far - fetched', but don't mangle '-2' + m = doc.match('(he|she|they|it|we) is'); + setContraction(m, "'s"); // spencer is -> spencer's - var m = str.match(minusNumber); + m = doc.match('#Person is'); + setContraction(m, "'s"); // spencer would -> spencer'd - if (m !== null) { - whitespace.before = m[1]; - str = str.replace(/^ */, ''); - } else { - m = str.match(before); + m = doc.match('#Person would'); + setContraction(m, "'d"); // would not -> wouldn't - if (m !== null) { - whitespace.before = m[0]; - str = str.replace(before, ''); - } - } //get after punctuation/whitespace + m = doc.match('(is|was|had|would|should|could|do|does|have|has|can) not'); + setContraction(m, "n't"); // i have -> i've + m = doc.match('(i|we|they) have'); + setContraction(m, "'ve"); // would have -> would've - m = str.match(afterSoft); + m = doc.match('(would|should|could) have'); + setContraction(m, "'ve"); // i am -> i'm - if (m !== null) { - str = str.replace(afterSoft, ''); - whitespace.after = m[0]; - } + m = doc.match('i am'); + setContraction(m, "'m"); // going to -> gonna - return { - whitespace: whitespace, - text: str + m = doc.match('going to'); + return this; }; -}; - -module.exports = build_whitespace; - -},{}],163:[function(_dereq_,module,exports){ -'use strict'; -var Term = _dereq_('../term'); + var _07Contract = { + contract: contract + }; -var wordlike = /\S/; -var isBoundary = /^[!?.]+$/; -var notWord = { - '.': true, - '-': true, - //dash - '–': true, - //en-dash - '—': true, - //em-dash - '--': true, - '...': true -}; + var methods$4 = Object.assign({}, _01Utils$1, _02Accessors, _03Match, _04Tag, _05Loops, _06Lookup, _01Replace, _02Insert, _01Text, _02Json, _03Out, _04Export, _01Sort, _02Normalize, _03Split, _04Case, _05Whitespace, _06Join, _07Contract); -var hasHyphen = function hasHyphen(str) { - //dont split 're-do' - if (/^(re|un)-?[^aeiou]./.test(str) === true) { - return false; - } //letter-number + var methods$5 = {}; // allow helper methods like .adjectives() and .adverbs() + var arr = [['terms', '.'], ['hyphenated', '@hasHyphen .'], ['adjectives', '#Adjective'], ['hashTags', '#HashTag'], ['emails', '#Email'], ['emoji', '#Emoji'], ['emoticons', '#Emoticon'], ['atMentions', '#AtMention'], ['urls', '#Url'], ['adverbs', '#Adverb'], ['pronouns', '#Pronoun'], ['conjunctions', '#Conjunction'], ['prepositions', '#Preposition']]; + arr.forEach(function (a) { + methods$5[a[0]] = function (n) { + var m = this.match(a[1]); - var reg = /^([a-z`"'/]+)(-|–|—)([a-z0-9].*)/i; + if (typeof n === 'number') { + m = m.get(n); + } - if (reg.test(str) === true) { - return true; - } //number-letter - // reg = /^([0-9]+)(-|–|—)([a-z].*)/i; - // if (reg.test(str) === true) { - // return true; - // } - //support weird number-emdash combo '2010–2011' + return m; + }; + }); // aliases + methods$5.emojis = methods$5.emoji; + methods$5.atmentions = methods$5.atMentions; + methods$5.words = methods$5.terms; + /** return anything tagged as a phone number */ - var reg2 = /^([0-9]+)(–|—)([0-9].*)/i; + methods$5.phoneNumbers = function (n) { + var m = this.splitAfter('@hasComma'); + m = m.match('#PhoneNumber+'); - if (reg2.test(str)) { - return true; - } + if (typeof n === 'number') { + m = m.get(n); + } - return false; -}; //support splitting terms like "open/closed" + return m; + }; + /** money + currency pair */ -var hasSlash = function hasSlash(word) { - var reg = /[a-z]\/[a-z]/; + methods$5.money = function (n) { + var m = this.match('#Money #Currency?'); - if (reg.test(word)) { - //only one slash though - if (word.split(/\//g).length === 2) { - return true; + if (typeof n === 'number') { + m = m.get(n); } - } - - return false; -}; //turn a string into an array of terms (naiive for now, lumped later) - -var fromString = function fromString(str, world) { - var result = []; - var arr = []; //start with a naiive split - - str = str || ''; + return m; + }; + /** return all cities, countries, addresses, and regions */ - if (typeof str === 'number') { - str = String(str); - } - var firstSplit = str.split(/(\S+)/); + methods$5.places = function (n) { + // don't split 'paris, france' + var keep = this.match('(#City && @hasComma) (#Region|#Country)'); // but split the other commas - for (var i = 0; i < firstSplit.length; i++) { - var word = firstSplit[i]; + var m = this.not(keep).splitAfter('@hasComma'); // combine them back together - if (hasHyphen(word) === true) { - //support multiple-hyphenated-terms - var hyphens = word.split(/[-–—]/); + m = m.concat(keep); + m.sort('index'); + m = m.match('#Place+'); - for (var o = 0; o < hyphens.length; o++) { - if (o === hyphens.length - 1) { - arr.push(hyphens[o]); - } else { - arr.push(hyphens[o] + '-'); - } - } - } else if (hasSlash(word) === true) { - var slashes = word.split(/\//); - arr.push(slashes[0]); - arr.push('/' + slashes[1]); - } else { - arr.push(word); + if (typeof n === 'number') { + m = m.get(n); } - } //greedy merge whitespace+arr to the right + return m; + }; + /** return all schools, businesses and institutions */ - var carry = ''; - - for (var _i = 0; _i < arr.length; _i++) { - //if it's more than a whitespace - if (wordlike.test(arr[_i]) === true && notWord.hasOwnProperty(arr[_i]) === false && isBoundary.test(arr[_i]) === false) { - result.push(carry + arr[_i]); - carry = ''; - } else { - carry += arr[_i]; - } - } //handle last one + methods$5.organizations = function (n) { + var m = this.clauses(); + m = m.match('#Organization+'); - if (carry && result.length > 0) { - result[result.length - 1] += carry; //put it on the end - } + if (typeof n === 'number') { + m = m.get(n); + } - return result.map(function (t) { - return new Term(t, world); - }); -}; + return m; + }; //combine them with .topics() method -module.exports = fromString; -},{"../term":143}],164:[function(_dereq_,module,exports){ -'use strict'; //getters/setters for the Terms class + methods$5.entities = function (n) { + var r = this.clauses(); // Find people, places, and organizations -module.exports = { - parent: { - get: function get() { - return this.refText || this; - }, - set: function set(r) { - this.refText = r; - return this; - } - }, - parentTerms: { - get: function get() { - return this.refTerms || this; - }, - set: function set(r) { - this.refTerms = r; - return this; - } - }, - dirty: { - get: function get() { - for (var i = 0; i < this.terms.length; i++) { - if (this.terms[i].dirty === true) { - return true; - } - } + var yup = r.people(); + yup = yup.concat(r.places()); + yup = yup.concat(r.organizations()); + var ignore = ['someone', 'man', 'woman', 'mother', 'brother', 'sister', 'father']; + yup = yup.not(ignore); //return them to normal ordering - return false; - }, - set: function set(dirt) { - this.terms.forEach(function (t) { - t.dirty = dirt; - }); - } - }, - refTerms: { - get: function get() { - return this._refTerms || this; - }, - set: function set(ts) { - this._refTerms = ts; - return this; - } - }, - found: { - get: function get() { - return this.terms.length > 0; - } - }, - length: { - get: function get() { - return this.terms.length; - } - }, - isA: { - get: function get() { - return 'Terms'; - } - }, - whitespace: { - get: function get() { - var _this = this; + yup.sort('sequence'); // yup.unique() //? not sure - return { - before: function before(str) { - _this.firstTerm().whitespace.before = str; - return _this; - }, - after: function after(str) { - _this.lastTerm().whitespace.after = str; - return _this; - } - }; + if (typeof n === 'number') { + yup = yup.get(n); } - } -}; -},{}],165:[function(_dereq_,module,exports){ -'use strict'; + return yup; + }; //aliases -var build = _dereq_('./build'); -var getters = _dereq_('./getters'); + methods$5.things = methods$5.entities; + methods$5.topics = methods$5.entities; + /** alias for .all() until it gets overloaded by plugin */ -var w = _dereq_('../world'); //Terms is an array of Term objects, and methods that wrap around them + methods$5.sentences = function () { + return this.all(); + }; + var _simple = methods$5; -var Terms = function Terms(arr, world, refText, refTerms) { - var _this = this; + /** match a word-sequence, like 'super bowl' in the lexicon */ + var tryMultiple = function tryMultiple(terms, t, world) { + var lex = world.words; //try a two-word version - this.terms = arr; - this.world = world || w; - this.refText = refText; - this._refTerms = refTerms; + var txt = terms[t].reduced + ' ' + terms[t + 1].reduced; - this.get = function (n) { - return _this.terms[n]; - }; //apply getters + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-two', world); + terms[t + 1].tag(lex[txt], 'lexicon-two', world); + return 1; + } //try a three-word version? - var keys = Object.keys(getters); + if (t + 2 < terms.length) { + txt += ' ' + terms[t + 2].reduced; - for (var i = 0; i < keys.length; i++) { - Object.defineProperty(this, keys[i], getters[keys[i]]); - } -}; + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-three', world); + terms[t + 1].tag(lex[txt], 'lexicon-three', world); + terms[t + 2].tag(lex[txt], 'lexicon-three', world); + return 2; + } + } //try a four-word version? -Terms.fromString = function (str, world) { - var termArr = build(str, world); - var ts = new Terms(termArr, world, null); //give each term a original to this ts - ts.terms.forEach(function (t) { - t.parentTerms = ts; - }); - return ts; -}; // Terms = require('./methods/lookup')(Terms); + if (t + 3 < terms.length) { + txt += ' ' + terms[t + 3].reduced; + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-four', world); + terms[t + 1].tag(lex[txt], 'lexicon-four', world); + terms[t + 2].tag(lex[txt], 'lexicon-four', world); + terms[t + 3].tag(lex[txt], 'lexicon-four', world); + return 3; + } + } -_dereq_('./match')(Terms); + return 0; + }; + /** look at each word in our list of known-words */ -_dereq_('./methods/tag')(Terms); -_dereq_('./methods/loops')(Terms); + var checkLexicon = function checkLexicon(terms, world) { + var lex = world.words; + var hasCompound = world.hasCompound; // use reduced? + //go through each term, and check the lexicon -_dereq_('./match/not')(Terms); + for (var t = 0; t < terms.length; t += 1) { + var str = terms[t].clean; //is it the start of a compound word, like 'super bowl'? -_dereq_('./methods/delete')(Terms); + if (hasCompound[str] === true && t + 1 < terms.length) { + var foundWords = tryMultiple(terms, t, world); -_dereq_('./methods/insert')(Terms); + if (foundWords > 0) { + t += foundWords; //skip any already-found words -_dereq_('./methods/misc')(Terms); + continue; + } + } //try one-word lexicon -_dereq_('./methods/out')(Terms); -_dereq_('./methods/replace')(Terms); + if (lex[str] !== undefined && lex.hasOwnProperty(str) === true) { + terms[t].tag(lex[str], 'lexicon', world); + } // look at reduced version of term, too -_dereq_('./methods/split')(Terms); -_dereq_('./methods/transform')(Terms); + if (str !== terms[t].reduced && lex.hasOwnProperty(terms[t].reduced) === true) { + terms[t].tag(lex[terms[t].reduced], 'lexicon', world); + } + } -_dereq_('./methods/lump')(Terms); + return terms; + }; -module.exports = Terms; + var _01Lexicon = checkLexicon; -},{"../world":215,"./build":163,"./getters":164,"./match":166,"./match/not":176,"./methods/delete":177,"./methods/insert":178,"./methods/loops":179,"./methods/lump":181,"./methods/misc":182,"./methods/out":183,"./methods/replace":184,"./methods/split":185,"./methods/tag":186,"./methods/transform":187}],166:[function(_dereq_,module,exports){ -'use strict'; + var apostrophes = /[\'‘’‛‵′`´]$/; + var oneLetterAcronym$1 = /^[A-Z]('s|,)?$/; + var oneLetterWord = { + I: true, + A: true + }; -var syntax = _dereq_('./lib/syntax'); + var isAcronym$2 = function isAcronym(term, world) { + var str = term.reduced; // a known acronym like fbi -var startHere = _dereq_('./lib/startHere'); + if (term.tags.Acronym) { + return true; + } // if (term.tags.Adverb || term.tags.Verb || term.tags.Value || term.tags.Plural) { + // return false + // } + // 'PIZZA' is not an acronym. -var Text = _dereq_('../../text'); -var _match = _dereq_('./lib'); + if (str.length > 4 && world.words[str]) { + return false; + } -var matchMethods = function matchMethods(Terms) { - var methods = { - //support regex-like whitelist-match - match: function match(reg, verbose) { - var _this = this; + return term.isAcronym(); + }; // - //fail-fast #1 - if (this.terms.length === 0) { - return new Text([], this.world, this.parent); - } //fail-fast #2 + var checkPunctuation = function checkPunctuation(terms, i, world) { + var term = terms[i]; //check hyphenation + // if (term.post.indexOf('-') !== -1 && terms[i + 1] && terms[i + 1].pre === '') { + // term.tag('Hyphenated', 'has-hyphen', world) + // } + //an end-tick (trailing apostrophe) - flanders', or Carlos' - if (!reg) { - return new Text([], this.world, this.parent); - } + if (apostrophes.test(term.text)) { + if (!apostrophes.test(term.pre) && !apostrophes.test(term.post) && term.clean.length > 2) { + var endChar = term.clean[term.clean.length - 2]; //flanders' - var matches = _match(this, reg, verbose); + if (endChar === 's') { + term.tag(['Possessive', 'Noun'], 'end-tick', world); + return; + } //chillin' - matches = matches.map(function (a) { - return new Terms(a, _this.world, _this.refText, _this.refTerms); - }); - return new Text(matches, this.world, this.parent); - }, - /**return first match */ - matchOne: function matchOne(str) { - //fail-fast - if (this.terms.length === 0) { - return null; + if (endChar === 'n') { + term.tag(['Gerund'], 'chillin', world); + } } + } // 'NASA' is, but not 'i REALLY love it.' - var regs = syntax(str); - for (var t = 0; t < this.terms.length; t++) { - //don't loop through if '^' - if (regs[0] && regs[0].starting && t > 0) { - break; - } - - var m = startHere(this, t, regs); + if (isAcronym$2(term, world)) { + term.tag('Acronym', 'acronym-step', world); + term.tag('Noun', 'acronym-infer', world); + } else if (!oneLetterWord.hasOwnProperty(term.text) && oneLetterAcronym$1.test(term.text)) { + term.tag('Acronym', 'one-letter-acronym', world); + term.tag('Noun', 'one-letter-infer', world); + } + }; - if (m) { - return m; - } + var _02Punctuation$1 = checkPunctuation; + + //these are regexes applied to t.text, instead of t.clean + // order matters. + var startsWith = [//phone numbers + [/^[0-9]{3}-[0-9]{4}$/, 'PhoneNumber'], //589-3809 + [/^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$/, 'PhoneNumber'], //632-589-3809 + //money + [/^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?([a-z]{1,4})?$/, ['Money', 'Value']], //like $5.30 + [/^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$/, ['Money', 'Value']], //like $5,231.30 + [/^[-+]?[0-9]([0-9,.]+)?(usd|eur|jpy|gbp|cad|aud|chf|cny|hkd|nzd|kr|rub)$/i, ['Money', 'Value']], //like 400usd + //web tags + [/^\w+@\w+\.[a-z]{2,3}$/, 'Email'], //not fancy + [/^#[a-z0-9_\u00C0-\u00FF]{2,}$/, 'HashTag'], [/^@\w{2,}$/, 'AtMention'], [/^(https?:\/\/|www\.)\w+\.[a-z]{2,3}/, 'Url'], //with http/www + [/^[\w\.\/]+\.(com|net|gov|org|ly|edu|info|biz|ru|jp|de|in|uk|br)/, 'Url'], //http://mostpopularwebsites.net/top-level-domain + //dates/times + [/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$/, 'Time'], //4:32:32 + [/^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$/, 'Time'], //4pm + [/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$/, 'Time'], //4:00pm + [/^[PMCE]ST$/, 'Time'], //PST, time zone abbrevs + [/^utc ?[+-]?[0-9]+?$/, 'Time'], //UTC 8+ + [/^[a-z0-9]*? o\'?clock$/, 'Time'], //3 oclock + [/^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$/, 'Date'], // 03-02-89 + [/^[0-9]{1,4}\/[0-9]{1,2}\/[0-9]{1,4}$/, 'Date'], // 03/02/89 + //names + [/^ma?c\'.*/, 'LastName'], //mc'adams + [/^o\'[drlkn].*/, 'LastName'], //o'douggan + [/^ma?cd[aeiou]/, 'LastName'], //macdonell - Last patterns https://en.wikipedia.org/wiki/List_of_family_name_affixes + //slang things + [/^(lol)+[sz]$/, 'Expression'], //lol + [/^(un|de|re)\\-[a-z\u00C0-\u00FF]{2}/, 'Verb'], [/^[\-\+]?[0-9]+(\.[0-9])*$/, ['Cardinal', 'NumericValue']], [/^(over|under)[a-z]{2,}/, 'Adjective'], [/^[0-9]{1,4}\.[0-9]{1,2}\.[0-9]{1,4}$/, 'Date'], // 03-02-89 + //numbers + [/^[\-\+]?[0-9][0-9,]*(\.[0-9])*$/, ['Cardinal', 'NumericValue']], //like 5 + [/^[-+]?[0-9]+(.[0-9]+)?$/, ['Cardinal', 'NumericValue']], //like +5.0 + [/^[0-9\.]{1,4}(st|nd|rd|th)?[-–][0-9\.]{1,4}(st|nd|rd|th)?$/, 'NumberRange'], //5-7 + [/^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$/, 'NumericValue'], //like 5,999.0 + [/^.?[0-9]+([0-9,.]+)?%$/, ['Percent', 'Cardinal', 'NumericValue']], //7% .. + [/^[0-9]{1,4}\/[0-9]{1,4}$/, 'Fraction'], //3/2ths + [/^[0-9\.]{1,2}[-–][0-9]{1,2}$/, ['Value', 'NumberRange']], //7-8 + [/^[0-9][0-9,\.]*(st|nd|rd|r?th)$/, ['NumericValue', 'Ordinal']], //like 5th + [/[0-9]\+$/, ['Cardinal', 'NumericValue']], //10+ + [/^[0-9]+(st|nd|rd|th)$/, 'Ordinal'], //like 5th + [/^[0-9\.]+([a-z]{1,4})$/, 'Value'] //like 5tbsp + ]; + + var romanNumeral = /^[IVXLCDM]{2,}$/; + var romanNumValid = /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/; // https://stackoverflow.com/a/267405/168877 + //try each of the ^regexes in our list + + var checkRegex = function checkRegex(term, world) { + var str = term.text; // do them all! + + for (var r = 0; r < startsWith.length; r += 1) { + if (startsWith[r][0].test(str) === true) { + term.tagSafe(startsWith[r][1], 'regex #' + r, world); + break; } + } // do some more! + //roman numberals - XVII - return null; - }, - /**return first match */ - has: function has(str) { - return this.matchOne(str) !== null; + if (term.text.length >= 2 && romanNumeral.test(str) && romanNumValid.test(str)) { + term.tag('RomanNumeral', 'xvii', world); } - }; //hook them into result.proto + }; - Object.keys(methods).forEach(function (k) { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; + var _03Prefixes = checkRegex; + + //regex suffix patterns and their most common parts of speech, + //built using wordnet, by spencer kelly. + //this mapping shrinks-down the uglified build + var Adj = 'Adjective'; + var Inf = 'Infinitive'; + var Pres = 'PresentTense'; + var Sing = 'Singular'; + var Past = 'PastTense'; + var Adverb = 'Adverb'; + var Exp = 'Expression'; + var Actor = 'Actor'; + var Verb = 'Verb'; + var Noun = 'Noun'; + var Last = 'LastName'; //the order here matters. + //regexes indexed by mandated last-character + + var endsWith$1 = { + a: [[/.[aeiou]na$/, Noun], [/.[oau][wvl]ska$/, Last], //polish (female) + [/.[^aeiou]ica$/, Sing], [/^([hyj]a)+$/, Exp] //hahah + ], + c: [[/.[^aeiou]ic$/, Adj]], + d: [[/.[ia]sed$/, Adj], [/.[gt]led$/, Adj], [/.[td]ed$/, Past], [/.[aeiou]red$/, Past], [/.[^aeiou]led$/, Past], //rumbled + [/[^aeiou]ard$/, Sing], [/[aeiou][^aeiou]id$/, Adj], [/[aeiou]c?ked$/, Past], //hooked + [/[^aeiou][aeiou][tvx]ed$/, Past], //boxed + [/.[vrl]id$/, Adj]], + e: [[/.[lnr]ize$/, Inf], [/.[^aeiou]ise$/, Inf], [/.[aeiou]te$/, Inf], [/.[^aeiou][ai]ble$/, Adj], [/.[^aeiou]eable$/, Adj], [/.[ts]ive$/, Adj]], + h: [[/.[^aeiouf]ish$/, Adj], [/.v[iy]ch$/, Last], //east-europe + [/^ug?h+$/, Exp], //uhh + [/^uh[ -]?oh$/, Exp] //uhoh + ], + i: [[/.[oau][wvl]ski$/, Last] //polish (male) + ], + k: [[/^(k)+$/, Exp] //kkkk + ], + l: [[/.[gl]ial$/, Adj], [/.[^aeiou]ful$/, Adj], [/.[nrtumcd]al$/, Adj], [/.[^aeiou][ei]al$/, Adj]], + m: [[/.[^aeiou]ium$/, Sing], [/[^aeiou]ism$/, Sing], [/^h*u*m+$/, Exp], //mmmmmmm / ummmm / huuuuuummmmmm + [/^\d+ ?[ap]m$/, 'Date']], + n: [[/.[lsrnpb]ian$/, Adj], [/[^aeiou]ician$/, Actor]], + o: [[/^no+$/, Exp], //noooo + [/^(yo)+$/, Exp], //yoyo + [/^woo+[pt]?$/, Exp] //woo + ], + r: [[/.[bdfklmst]ler$/, 'Noun'], [/.[ilk]er$/, 'Comparative'], [/[aeiou][pns]er$/, Sing], [/[^i]fer$/, Inf], [/.[^aeiou][ao]pher$/, Actor]], + t: [[/.[di]est$/, 'Superlative'], [/.[icldtgrv]ent$/, Adj], [/[aeiou].*ist$/, Adj], [/^[a-z]et$/, Verb]], + s: [[/.[rln]ates$/, Pres], [/.[^z]ens$/, Verb], [/.[lstrn]us$/, Sing], [/[aeiou][^aeiou]is$/, Sing], [/[a-z]\'s$/, Noun], [/^yes+$/, Exp] //yessss + ], + v: [[/.[^aeiou][ai][kln]ov$/, Last] //east-europe + ], + y: [[/.[cts]hy$/, Adj], [/.[st]ty$/, Adj], [/.[gk]y$/, Adj], [/.[tnl]ary$/, Adj], [/.[oe]ry$/, Sing], [/[rdntkbhs]ly$/, Adverb], [/...lly$/, Adverb], [/[bszmp]{2}y$/, Adj], [/.(gg|bb|zz)ly$/, Adj], [/.[aeiou]my$/, Adj], [/[ea]{2}zy$/, Adj], [/.[^aeiou]ity$/, Sing]] + }; -module.exports = matchMethods; + //just a foolish lookup of known suffixes + var Adj$1 = 'Adjective'; + var Inf$1 = 'Infinitive'; + var Pres$1 = 'PresentTense'; + var Sing$1 = 'Singular'; + var Past$1 = 'PastTense'; + var Avb = 'Adverb'; + var Plrl = 'Plural'; + var Actor$1 = 'Actor'; + var Vb = 'Verb'; + var Noun$1 = 'Noun'; + var Last$1 = 'LastName'; + var Modal = 'Modal'; // find any issues - https://observablehq.com/@spencermountain/suffix-word-lookup + + var suffixMap = [null, //0 + null, //1 + { + //2-letter + ea: Sing$1, + ia: Noun$1, + ic: Adj$1, + ly: Avb, + "'n": Vb, + "'t": Vb + }, { + //3-letter + que: Adj$1, + lar: Adj$1, + ffy: Adj$1, + nny: Adj$1, + rmy: Adj$1, + azy: Adj$1, + oid: Adj$1, + mum: Adj$1, + ous: Adj$1, + end: Vb, + sis: Sing$1, + rol: Sing$1, + ize: Inf$1, + ify: Inf$1, + zes: Pres$1, + nes: Pres$1, + ing: 'Gerund', + //likely to be converted to Adj after lexicon pass + ' so': Avb, + "'ll": Modal, + "'re": 'Copula' + }, { + //4-letter + teen: 'Value', + tors: Noun$1, + amed: Past$1, + ched: Past$1, + ends: Vb, + oses: Pres$1, + fies: Pres$1, + ects: Pres$1, + nded: Past$1, + cede: Inf$1, + tage: Inf$1, + gate: Inf$1, + vice: Sing$1, + tion: Sing$1, + cted: Past$1, + ette: Sing$1, + some: Adj$1, + llen: Adj$1, + ried: Adj$1, + gone: Adj$1, + made: Adj$1, + fore: Avb, + less: Avb, + ices: Plrl, + ions: Plrl, + ints: Plrl, + aped: Past$1, + lked: Past$1, + ould: Modal, + tive: Actor$1, + sson: Last$1, + //swedish male + czyk: Last$1, + //polish (male) + chuk: Last$1, + //east-europe + enko: Last$1, + //east-europe + akis: Last$1, + //greek + nsen: Last$1 //norway -},{"../../text":192,"./lib":170,"./lib/startHere":174,"./lib/syntax":175}],167:[function(_dereq_,module,exports){ -'use strict'; //applies the reg capture group setting to the term + }, { + //5-letter + fully: Avb, + where: Avb, + wards: Avb, + urned: Past$1, + tized: Past$1, + eased: Past$1, + ances: Plrl, + tures: Plrl, + ports: Plrl, + ettes: Plrl, + ities: Plrl, + rough: Adj$1, + ology: Noun$1, + bound: Adj$1, + tieth: 'Ordinal', + ishes: Pres$1, + tches: Pres$1, + nssen: Last$1, + //norway + marek: Last$1 //polish (male) -var applyCaptureGroup = function applyCaptureGroup(term, reg) { - if (reg.capture) { - term.captureGroup = true; - } else { - term.captureGroup = undefined; - } -}; + }, { + //6-letter + keeper: Actor$1, + logist: Actor$1, + auskas: Last$1, + //lithuania + teenth: 'Value' + }, { + //7-letter + sdottir: Last$1, + //swedish female + opoulos: Last$1 //greek -module.exports = applyCaptureGroup; + }]; -},{}],168:[function(_dereq_,module,exports){ -'use strict'; //take all the matches, and if there is a [capture group], only return that. + var endRegexs = function endRegexs(term, world) { + var str = term.clean; + var _char = str[str.length - 1]; -var onlyCaptureGroup = function onlyCaptureGroup(matches) { - var results = []; - matches.forEach(function (terms) { - //if there's no capture group, we good. - if (terms.filter(function (t) { - return t.captureGroup === true; - }).length === 0) { - results.push(terms); - return; - } //otherwise, just return them as seperate subsets + if (endsWith$1.hasOwnProperty(_char) === true) { + var regs = endsWith$1[_char]; + for (var r = 0; r < regs.length; r += 1) { + if (regs[r][0].test(str) === true) { + term.tagSafe(regs[r][1], "endReg ".concat(_char, " #").concat(r), world); + break; + } + } + } + }; //sweep-through all suffixes - var current = []; - for (var i = 0; i < terms.length; i += 1) { - if (terms[i].captureGroup) { - current.push(terms[i]); - } else if (current.length > 0) { - results.push(current); - current = []; - } + var knownSuffixes = function knownSuffixes(term, world) { + var len = term.clean.length; + var max = 7; + + if (len <= max) { + max = len - 1; } - if (current.length > 0) { - results.push(current); + for (var i = max; i > 1; i -= 1) { + var str = term.clean.substr(len - i, len); + + if (suffixMap[str.length].hasOwnProperty(str) === true) { + var tag = suffixMap[str.length][str]; + term.tagSafe(tag, 'suffix -' + str, world); + break; + } } - }); - return results; -}; + }; //all-the-way-down! -module.exports = onlyCaptureGroup; -},{}],169:[function(_dereq_,module,exports){ -'use strict'; // -//find easy reasons to skip running the full match on this + var checkRegex$1 = function checkRegex(term, world) { + knownSuffixes(term, world); + endRegexs(term, world); + }; -var fastPass = function fastPass(ts, regs) { - for (var i = 0; i < regs.length; i++) { - var reg = regs[i]; - var found = false; //we can't cheat on these fancy rules: + var _04Suffixes = checkRegex$1; + + //just some of the most common emoticons + //faster than + //http://stackoverflow.com/questions/28077049/regex-matching-emoticons + var emoticons = { + ':(': true, + ':)': true, + ':P': true, + ':p': true, + ':O': true, + ':3': true, + ':|': true, + ':/': true, + ':\\': true, + ':$': true, + ':*': true, + ':@': true, + ':-(': true, + ':-)': true, + ':-P': true, + ':-p': true, + ':-O': true, + ':-3': true, + ':-|': true, + ':-/': true, + ':-\\': true, + ':-$': true, + ':-*': true, + ':-@': true, + ':^(': true, + ':^)': true, + ':^P': true, + ':^p': true, + ':^O': true, + ':^3': true, + ':^|': true, + ':^/': true, + ':^\\': true, + ':^$': true, + ':^*': true, + ':^@': true, + '):': true, + '(:': true, + '$:': true, + '*:': true, + ')-:': true, + '(-:': true, + '$-:': true, + '*-:': true, + ')^:': true, + '(^:': true, + '$^:': true, + '*^:': true, + '<3': true, + ' 35) { + return false; } - if (found === false) { - return true; - } - } //look for missing tags + return true; + } + return false; + }; //check against emoticon whitelist - if (reg.tag !== undefined) { - for (var _o = 0; _o < ts.terms.length; _o++) { - if (ts.terms[_o].tags[reg.tag] === true) { - found = true; - break; - } - } - if (found === false) { - return true; - } - } - } + var isEmoticon = function isEmoticon(str) { + str = str.replace(/^[:;]/, ':'); //normalize the 'eyes' - return false; -}; + return emoticons.hasOwnProperty(str); + }; -module.exports = fastPass; + var tagEmoji = function tagEmoji(term, world) { + var raw = term.pre + term.text + term.post; + raw = raw.trim(); //test for :keyword: emojis -},{}],170:[function(_dereq_,module,exports){ -'use strict'; + if (isCommaEmoji(raw) === true) { + term.tag('Emoji', 'comma-emoji', world); + term.text = raw; + term.pre = term.pre.replace(':', ''); + term.post = term.post.replace(':', ''); + } //test for unicode emojis -var syntax = _dereq_('./syntax'); -var startHere = _dereq_('./startHere'); + if (term.text.match(emojiReg)) { + term.tag('Emoji', 'unicode-emoji', world); + term.text = raw; + } //test for emoticon ':)' emojis -var fastPass = _dereq_('./fastPass'); -var handleCaptureGroup = _dereq_('./captureGroup'); //ensure we have atleast one non-optional demand -// const isTautology = function(regs) { -// for (let i = 0; i < regs.length; i++) { -// if (!regs[i].optional && !regs[i].astrix && !regs[i].anyOne) { -// return false; -// } -// } -// return true; -// }; -//make a reg syntax from a text object + if (isEmoticon(raw) === true) { + term.tag('Emoticon', 'emoticon-emoji', world); + term.text = raw; + } + }; + var _05Emoji = tagEmoji; -var findFromTerms = function findFromTerms(ts) { - if (!ts) { - return []; - } + var steps = { + lexicon: _01Lexicon, + punctuation: _02Punctuation$1, + regex: _03Prefixes, + suffix: _04Suffixes, + emoji: _05Emoji + }; //'lookups' look at a term by itself - var arr = ts.terms.map(function (t) { - return { - id: t.uid - }; - }); - return arr; -}; // - - -var match = function match(ts, reg, verbose) { - //parse for backwards-compatibility - if (typeof reg === 'string') { - reg = syntax(reg); - } else if (reg && reg.isA === 'Text') { - reg = findFromTerms(reg.list[0]); - } else if (reg && reg.isA === 'Terms') { - reg = findFromTerms(reg); - } + var lookups = function lookups(doc) { + var terms = doc.termList(); + var world = doc.world; //our list of known-words - if (!reg || reg.length === 0) { - return []; - } //do a fast-pass for easy negatives + steps.lexicon(terms, world); //try these other methods + for (var i = 0; i < terms.length; i += 1) { + var term = terms[i]; //or maybe some helpful punctuation - if (fastPass(ts, reg, verbose) === true) { - return []; - } //ok, start long-match + steps.punctuation(terms, i, world); //mostly prefix checks + steps.regex(term, world); //maybe we can guess - var matches = []; + steps.suffix(term, world); //emoji and emoticons - for (var t = 0; t < ts.terms.length; t += 1) { - //don't loop through if '^' - if (t > 0 && reg[0] && reg[0].starting) { - break; + steps.emoji(term, world); } - var m = startHere(ts, t, reg, verbose); + return doc; + }; - if (m && m.length > 0) { - matches.push(m); //handle capture-groups subset - // let hasCapture=matches - //ok, don't try to match these again. + var _01Init = lookups; + + //markov-like stats about co-occurance, for hints about unknown terms + //basically, a little-bit better than the noun-fallback + //just top n-grams from nlp tags, generated from nlp-corpus + //after this word, here's what happens usually + var afterThisWord = { + i: 'Verb', + //44% //i walk.. + first: 'Noun', + //50% //first principles.. + it: 'Verb', + //33% + there: 'Verb', + //35% + not: 'Verb', + //33% + because: 'Noun', + //31% + "if": 'Noun', + //32% + but: 'Noun', + //26% + who: 'Verb', + //40% + "this": 'Noun', + //37% + his: 'Noun', + //48% + when: 'Noun', + //33% + you: 'Verb', + //35% + very: 'Adjective', + // 39% + old: 'Noun', + //51% + never: 'Verb', + //42% + before: 'Noun' //28% + + }; //in advance of this word, this is what happens usually + + var beforeThisWord = { + there: 'Verb', + //23% // be there + me: 'Verb', + //31% //see me + man: 'Adjective', + // 80% //quiet man + only: 'Verb', + //27% //sees only + him: 'Verb', + //32% //show him + were: 'Noun', + //48% //we were + took: 'Noun', + //38% //he took + himself: 'Verb', + //31% //see himself + went: 'Noun', + //43% //he went + who: 'Noun', + //47% //person who + jr: 'Person' + }; //following this POS, this is likely + + var afterThisPOS = { + Adjective: 'Noun', + //36% //blue dress + Possessive: 'Noun', + //41% //his song + Determiner: 'Noun', + //47% + Adverb: 'Verb', + //20% + Pronoun: 'Verb', + //40% + Value: 'Noun', + //47% + Ordinal: 'Noun', + //53% + Modal: 'Verb', + //35% + Superlative: 'Noun', + //43% + Demonym: 'Noun', + //38% + Honorific: 'Person' // + + }; //in advance of this POS, this is likely + + var beforeThisPOS = { + Copula: 'Noun', + //44% //spencer is + PastTense: 'Noun', + //33% //spencer walked + Conjunction: 'Noun', + //36% + Modal: 'Noun', + //38% + Pluperfect: 'Noun', + //40% + PerfectTense: 'Verb' //32% - var skip = m.length - 1; - t += skip; //this could use some work - } - } //handle capture-group subset + }; + var markov = { + beforeThisWord: beforeThisWord, + afterThisWord: afterThisWord, + beforeThisPos: beforeThisPOS, + afterThisPos: afterThisPOS + }; + var afterKeys = Object.keys(markov.afterThisPos); + var beforeKeys = Object.keys(markov.beforeThisPos); - matches = handleCaptureGroup(matches); - return matches; -}; + var checkNeighbours = function checkNeighbours(terms, world) { + var _loop = function _loop(i) { + var term = terms[i]; //do we still need a tag? -module.exports = match; + if (term.isKnown() === true) { + return "continue"; + } //ok, this term needs a tag. + //look at previous word for clues.. -},{"./captureGroup":168,"./fastPass":169,"./startHere":174,"./syntax":175}],171:[function(_dereq_,module,exports){ -'use strict'; -var applyCaptureGroup = _dereq_('./applyCaptureGroup'); //compare 1 term to one reg + var lastTerm = terms[i - 1]; + if (lastTerm) { + // 'foobar term' + if (markov.afterThisWord.hasOwnProperty(lastTerm.clean) === true) { + var tag = markov.afterThisWord[lastTerm.clean]; + term.tag(tag, 'after-' + lastTerm.clean, world); + return "continue"; + } // 'Tag term' + // (look at previous POS tags for clues..) -var perfectMatch = function perfectMatch(term, reg) { - if (!term || !reg) { - return false; - } //support '.' - any + var foundTag = afterKeys.find(function (tag) { + return lastTerm.tags[tag]; + }); - if (reg.anyOne === true) { - return true; - } //pos-match + if (foundTag !== undefined) { + var _tag = markov.afterThisPos[foundTag]; + term.tag(_tag, 'after-' + foundTag, world); + return "continue"; + } + } //look at next word for clues.. - if (reg.tag !== undefined) { - return term.tags[reg.tag]; - } //id-match + var nextTerm = terms[i + 1]; + if (nextTerm) { + // 'term foobar' + if (markov.beforeThisWord.hasOwnProperty(nextTerm.clean) === true) { + var _tag2 = markov.beforeThisWord[nextTerm.clean]; + term.tag(_tag2, 'before-' + nextTerm.clean, world); + return "continue"; + } // 'term Tag' + // (look at next POS tags for clues..) - if (reg.id !== undefined) { - return reg.id === term.uid; - } //text-match + var _foundTag = beforeKeys.find(function (tag) { + return nextTerm.tags[tag]; + }); - if (reg.normal !== undefined) { - return reg.normal === term.normal || reg.normal === term.silent_term; - } //suffix matches '-nny' + if (_foundTag !== undefined) { + var _tag3 = markov.beforeThisPos[_foundTag]; + term.tag(_tag3, 'before-' + _foundTag, world); + return "continue"; + } + } + }; + for (var i = 0; i < terms.length; i += 1) { + var _ret = _loop(i); - if (reg.suffix === true && reg.partial !== undefined) { - var len = term.normal.length; - return term.normal.substr(len - reg.partial.length, len) === reg.partial; - } //prefix matches 'fun-' + if (_ret === "continue") continue; + } + }; + var _01Neighbours = checkNeighbours; - if (reg.prefix === true && reg.partial !== undefined) { - return term.normal.substr(0, reg.partial.length) === reg.partial; - } //infix matches '-nn-' + var titleCase$3 = /^[A-Z][a-z'\u00C0-\u00FF]/; + var hasNumber = /[0-9]/; + /** look for any grammar signals based on capital/lowercase */ + var checkCase = function checkCase(terms, world) { + terms.forEach(function (term, i) { + //is it a titlecased word? + if (titleCase$3.test(term.text) === true && hasNumber.test(term.text) === false) { + // tag it as titlecase, if possible + if (i !== 0) { + term.tag('TitleCase', 'case', world); + } else if (term.tags.Person || term.tags.Organization || term.tags.Place) { + term.tag('TitleCase', 'case-person', world); + } // can we call it a noun? - if (reg.infix === true && reg.partial) { - return term.normal.indexOf(reg.partial) !== -1; - } //full-on regex-match '/a*?/' + if (i !== 0) { + //sure! + term.tag('ProperNoun', 'case-noun', world); + } + } + }); + }; - if (reg.regex !== undefined) { - return reg.regex.test(term.normal) || reg.regex.test(term.text); - } //one-of term-match + var _02Case = checkCase; + var hasPrefix = /^(re|un)-?[a-z\u00C0-\u00FF]/; + var prefix = /^(re|un)-?/; + /** check 'rewatch' in lexicon as 'watch' */ - if (reg.oneOf !== undefined) { - for (var i = 0; i < reg.oneOf.tagArr.length; i++) { - if (term.tags.hasOwnProperty(reg.oneOf.tagArr[i]) === true) { - return true; + var checkPrefix = function checkPrefix(terms, world) { + var lex = world.words; + terms.forEach(function (term) { + // skip if we have a good tag already + if (term.isKnown() === true) { + return; + } //does it start with 'un|re' + + + if (hasPrefix.test(term.clean) === true) { + // look for the root word in the lexicon: + var stem = term.clean.replace(prefix, ''); + + if (stem && stem.length > 3 && lex[stem] !== undefined && lex.hasOwnProperty(stem) === true) { + term.tag(lex[stem], 'stem-' + stem, world); + } } - } + }); + }; - return reg.oneOf.terms.hasOwnProperty(term.normal) || reg.oneOf.terms.hasOwnProperty(term.silent_term); - } + var _03Stem = checkPrefix; - return false; -}; //wrap above method, to support '!' negation + //similar to plural/singularize rules, but not the same + var isPlural = [/(^v)ies$/i, /ises$/i, /ives$/i, /(antenn|formul|nebul|vertebr|vit)ae$/i, /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, /(buffal|tomat|tornad)oes$/i, /(analy|ba|diagno|parenthe|progno|synop|the)ses$/i, /(vert|ind|cort)ices$/i, /(matr|append)ices$/i, /(x|ch|ss|sh|s|z|o)es$/i, /is$/i, /men$/i, /news$/i, /.tia$/i, /(^f)ves$/i, /(lr)ves$/i, /(^aeiouy|qu)ies$/i, /(m|l)ice$/i, /(cris|ax|test)es$/i, /(alias|status)es$/i, /ics$/i]; //similar to plural/singularize rules, but not the same + var isSingular = [/(ax|test)is$/i, /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, /(octop|vir)i$/i, /(rl)f$/i, /(alias|status)$/i, /(bu)s$/i, /(al|ad|at|er|et|ed|ad)o$/i, /(ti)um$/i, /(ti)a$/i, /sis$/i, /(?:(^f)fe|(lr)f)$/i, /hive$/i, /s[aeiou]+ns$/i, // sans, siens + /(^aeiouy|qu)y$/i, /(x|ch|ss|sh|z)$/i, /(matr|vert|ind|cort)(ix|ex)$/i, /(m|l)ouse$/i, /(m|l)ice$/i, /(antenn|formul|nebul|vertebr|vit)a$/i, /.sis$/i, /^(?!talis|.*hu)(.*)man$/i]; + var isPlural_1 = { + isSingular: isSingular, + isPlural: isPlural + }; -var isMatch = function isMatch(term, reg, verbose) { - if (!term || !reg) { - return false; - } + var noPlurals = ['Uncountable', 'Pronoun', 'Place', 'Value', 'Person', 'Month', 'WeekDay', 'Holiday']; + var notPlural = [/ss$/, /sis$/, /[^aeiou][uo]s$/, /'s$/]; + var notSingular = [/i$/, /ae$/]; + /** turn nouns into singular/plural */ - var found = perfectMatch(term, reg, verbose); //reverse it for .not() + var checkPlural = function checkPlural(t, world) { + if (t.tags.Noun && !t.tags.Acronym) { + var str = t.clean; //skip existing tags, fast - if (reg.negative) { - found = !Boolean(found); - } + if (t.tags.Singular || t.tags.Plural) { + return; + } //too short - if (found) { - //only apply capture group settings to matches - applyCaptureGroup(term, reg); - } - return found; -}; + if (str.length <= 3) { + t.tag('Singular', 'short-singular', world); + return; + } //is it impossible to be plural? + -module.exports = isMatch; + if (noPlurals.find(function (tag) { + return t.tags[tag]; + })) { + return; + } // isPlural suffix rules -},{"./applyCaptureGroup":167}],172:[function(_dereq_,module,exports){ -'use strict'; -var almostMatch = function almostMatch(reg_str, term) { - var want = term.normal.substr(0, reg_str.length); - return want === reg_str; -}; // match ['john', 'smith'] regs, when the term is lumped + if (isPlural_1.isPlural.find(function (reg) { + return reg.test(str); + })) { + t.tag('Plural', 'plural-rules', world); + return; + } // isSingular suffix rules -var lumpMatch = function lumpMatch(term, regs, reg_i) { - var reg_str = regs[reg_i].normal; //is this a partial match? 'tony'& 'tony hawk' + if (isPlural_1.isSingular.find(function (reg) { + return reg.test(str); + })) { + t.tag('Singular', 'singular-rules', world); + return; + } // finally, fallback 'looks plural' rules.. - if (reg_str !== undefined && almostMatch(reg_str, term)) { - //try to grow it - reg_i = reg_i + 1; - for (reg_i; reg_i < regs.length; reg_i++) { - reg_str += ' ' + regs[reg_i].normal; // is it now perfect? + if (/s$/.test(str) === true) { + //avoid anything too sketchy to be plural + if (notPlural.find(function (reg) { + return reg.test(str); + })) { + return; + } - if (reg_str === term.normal) { - return reg_i; - } // is it still almost? + t.tag('Plural', 'plural-fallback', world); + return; + } //avoid anything too sketchy to be singular - if (almostMatch(reg_str, term) === false) { - return null; + if (notSingular.find(function (reg) { + return reg.test(str); + })) { + return; } - } - } - return null; -}; + t.tag('Singular', 'singular-fallback', world); + } + }; -module.exports = lumpMatch; + var _04Plurals = checkPlural; -},{}],173:[function(_dereq_,module,exports){ -arguments[4][73][0].apply(exports,arguments) -},{"../../paths":189,"dup":73}],174:[function(_dereq_,module,exports){ -'use strict'; + //nouns that also signal the title of an unknown organization + //todo remove/normalize plural forms + var orgWords = ['academy', 'administration', 'agence', 'agences', 'agencies', 'agency', 'airlines', 'airways', 'army', 'assoc', 'associates', 'association', 'assurance', 'authority', 'autorite', 'aviation', 'bank', 'banque', 'board', 'boys', 'brands', 'brewery', 'brotherhood', 'brothers', 'building society', 'bureau', 'cafe', 'caisse', 'capital', 'care', 'cathedral', 'center', 'central bank', 'centre', 'chemicals', 'choir', 'chronicle', 'church', 'circus', 'clinic', 'clinique', 'club', 'co', 'coalition', 'coffee', 'collective', 'college', 'commission', 'committee', 'communications', 'community', 'company', 'comprehensive', 'computers', 'confederation', 'conference', 'conseil', 'consulting', 'containers', 'corporation', 'corps', 'corp', 'council', 'crew', 'daily news', 'data', 'departement', 'department', 'department store', 'departments', 'design', 'development', 'directorate', 'division', 'drilling', 'education', 'eglise', 'electric', 'electricity', 'energy', 'ensemble', 'enterprise', 'enterprises', 'entertainment', 'estate', 'etat', 'evening news', 'faculty', 'federation', 'financial', 'fm', 'foundation', 'fund', 'gas', 'gazette', 'girls', 'government', 'group', 'guild', 'health authority', 'herald', 'holdings', 'hospital', 'hotel', 'hotels', 'inc', 'industries', 'institut', 'institute', 'institute of technology', 'institutes', 'insurance', 'international', 'interstate', 'investment', 'investments', 'investors', 'journal', 'laboratory', 'labs', // 'law', + 'liberation army', 'limited', 'local authority', 'local health authority', 'machines', 'magazine', 'management', 'marine', 'marketing', 'markets', 'media', 'memorial', 'mercantile exchange', 'ministere', 'ministry', 'military', 'mobile', 'motor', 'motors', 'musee', 'museum', // 'network', + 'news', 'news service', 'observatory', 'office', 'oil', 'optical', 'orchestra', 'organization', 'partners', 'partnership', // 'party', + "people's party", 'petrol', 'petroleum', 'pharmacare', 'pharmaceutical', 'pharmaceuticals', 'pizza', 'plc', 'police', 'polytechnic', 'post', 'power', 'press', 'productions', 'quartet', 'radio', 'regional authority', 'regional health authority', 'reserve', 'resources', 'restaurant', 'restaurants', 'savings', 'school', 'securities', 'service', 'services', 'social club', 'societe', 'society', 'sons', 'standard', 'state police', 'state university', 'stock exchange', 'subcommittee', 'syndicat', 'systems', 'telecommunications', 'telegraph', 'television', 'times', 'tribunal', 'tv', 'union', 'university', 'utilities', 'workers']; + var organizations = orgWords.reduce(function (h, str) { + h[str] = 'Noun'; + return h; + }, {}); -var lumpMatch = _dereq_('./lumpMatch'); + var maybeOrg = function maybeOrg(t) { + //must be a noun + if (!t.tags.Noun) { + return false; + } //can't be these things -var isMatch = _dereq_('./isMatch'); -var applyCaptureGroup = _dereq_('./applyCaptureGroup'); // match everything until this point - '*' + if (t.tags.Pronoun || t.tags.Comma || t.tags.Possessive) { + return false; + } //must be one of these -var greedyUntil = function greedyUntil(ts, i, reg) { - for (; i < ts.length; i++) { - if (isMatch(ts.terms[i], reg)) { - return i; + if (t.tags.Organization || t.tags.Acronym || t.tags.Place || t.titleCase()) { + return true; } - } - return null; -}; //keep matching this reg as long as possible + return false; + }; + + var tagOrgs = function tagOrgs(terms, world) { + for (var i = 0; i < terms.length; i += 1) { + var t = terms[i]; + if (organizations[t.clean] !== undefined && organizations.hasOwnProperty(t.clean) === true) { + // look-backward - eg. 'Toronto University' + var lastTerm = terms[i - 1]; -var greedyOf = function greedyOf(ts, i, reg, until) { - for (; i < ts.length; i++) { - var t = ts.terms[i]; //found next reg ('until') + if (lastTerm !== undefined && maybeOrg(lastTerm) === true) { + lastTerm.tagSafe('Organization', 'org-word-1', world); + t.tagSafe('Organization', 'org-word-2', world); + continue; + } //look-forward - eg. University of Toronto - if (until && isMatch(t, until)) { - return i; - } //stop here + var nextTerm = terms[i + 1]; - if (!isMatch(t, reg)) { - return i; + if (nextTerm !== undefined && nextTerm.clean === 'of') { + if (terms[i + 2] && maybeOrg(terms[i + 2])) { + t.tagSafe('Organization', 'org-of-word-1', world); + nextTerm.tagSafe('Organization', 'org-of-word-2', world); + terms[i + 2].tagSafe('Organization', 'org-of-word-3', world); + continue; + } + } + } } - } + }; - return i; -}; //try and match all regs, starting at this term + var _05Organizations = tagOrgs; + var step = { + neighbours: _01Neighbours, + "case": _02Case, + stem: _03Stem, + plural: _04Plurals, + organizations: _05Organizations + }; // -var startHere = function startHere(ts, startAt, regs, verbose) { - var term_i = startAt; //check each regex-thing + var fallbacks = function fallbacks(doc) { + var terms = doc.termList(); + var world = doc.world; // if it's empty, consult it's neighbours, first - for (var reg_i = 0; reg_i < regs.length; reg_i++) { - var term = ts.terms[term_i]; - var reg = regs[reg_i]; - var next_reg = regs[reg_i + 1]; + step.neighbours(terms, world); // is there a case-sensitive clue? - if (!term) { - //we didn't need it anyways - if (reg.optional === true) { - continue; + step["case"](terms, world); // check 'rewatch' as 'watch' + + step.stem(terms, world); // ... fallback to a noun! + + terms.forEach(function (t) { + if (t.isKnown() === false) { + t.tag('Noun', 'noun-fallback', doc.world); } + }); // turn 'Foo University' into an Org - return null; - } //catch '^' errors + step.organizations(terms, world); //are the nouns singular or plural? + terms.forEach(function (t) { + step.plural(t, doc.world); + }); + return doc; + }; - if (reg.starting === true && term_i > 0) { - return null; - } //catch '$' errors + var _02Fallbacks = fallbacks; + var hasNegative = /n't$/; + var irregulars$3 = { + "won't": ['will', 'not'], + wont: ['will', 'not'], + "can't": ['can', 'not'], + cant: ['can', 'not'], + cannot: ['can', 'not'], + "shan't": ['should', 'not'], + dont: ['do', 'not'], + dun: ['do', 'not'] // "ain't" is ambiguous for is/was - if (reg.ending === true && term_i !== ts.length - 1 && !reg.minMax) { - return null; - } //support '*' + }; + var checkNegative = function checkNegative(term) { + //check named-ones + if (irregulars$3.hasOwnProperty(term.clean) === true) { + return irregulars$3[term.clean]; + } //try it normally - if (reg.astrix === true) { - //just grab until the end.. - if (!next_reg) { - var terms = ts.terms.slice(startAt, ts.length); //apply capture group settings for all wildcard terms - for (var wildcardTerm_i = term_i - startAt; wildcardTerm_i < terms.length; wildcardTerm_i++) { - applyCaptureGroup(terms[wildcardTerm_i], reg); - } + if (hasNegative.test(term.clean) === true) { + var main = term.clean.replace(hasNegative, ''); + return [main, 'not']; + } - return terms; - } + return null; + }; - var foundAt = greedyUntil(ts, term_i, regs[reg_i + 1]); + var _01Negative = checkNegative; - if (!foundAt) { - return null; - } //apply capture group settings for all wildcard terms + var contraction = /([a-z\u00C0-\u00FF]+)'([a-z]{1,2})$/i; //these ones don't seem to be ambiguous + var easy = { + ll: 'will', + ve: 'have', + re: 'are', + m: 'am', + "n't": 'not' + }; // - for (var _wildcardTerm_i = term_i; _wildcardTerm_i < foundAt; _wildcardTerm_i++) { - applyCaptureGroup(ts.terms[_wildcardTerm_i], reg); - } + var checkApostrophe = function checkApostrophe(term) { + var parts = term.text.match(contraction); - term_i = foundAt + 1; - reg_i += 1; - continue; - } //support '#Noun{x,y}' + if (parts === null) { + return null; + } + if (easy.hasOwnProperty(parts[2])) { + return [parts[1], easy[parts[2]]]; + } - if (regs[reg_i].minMax !== undefined) { - var min = regs[reg_i].minMax.min || 0; - var max = regs[reg_i].minMax.max; - var until = regs[reg_i + 1]; + return null; + }; - for (var i = 0; i < max; i++) { - //ergh, please clean this loop up.. - var t = ts.terms[term_i + i]; + var _02Simple = checkApostrophe; + + var irregulars$4 = { + wanna: ['want', 'to'], + gonna: ['going', 'to'], + im: ['i', 'am'], + alot: ['a', 'lot'], + ive: ['i', 'have'], + imma: ['I', 'will'], + "where'd": ['where', 'did'], + whered: ['where', 'did'], + "when'd": ['when', 'did'], + whend: ['when', 'did'], + "how'd": ['how', 'did'], + howd: ['how', 'did'], + "what'd": ['what', 'did'], + whatd: ['what', 'did'], + // "let's": ['let', 'us'], //too weird + //multiple word contractions + dunno: ['do', 'not', 'know'], + brb: ['be', 'right', 'back'], + gtg: ['got', 'to', 'go'], + irl: ['in', 'real', 'life'], + tbh: ['to', 'be', 'honest'], + imo: ['in', 'my', 'opinion'], + til: ['today', 'i', 'learned'], + rn: ['right', 'now'], + twas: ['it', 'was'], + '@': ['at'] + }; // either 'is not' or 'are not' + + var doAint = function doAint(term, phrase) { + var terms = phrase.terms(); + var index = terms.indexOf(term); + var before = terms.slice(0, index); //look for the preceding noun + + var noun = before.find(function (t) { + return t.tags.Noun; + }); - if (!t) { - return null; - } //end here + if (noun && noun.tags.Plural) { + return ['are', 'not']; + } + return ['is', 'not']; + }; // - if (isMatch(t, reg) === false) { - return null; - } //should we be greedier? + var checkIrregulars = function checkIrregulars(term, phrase) { + //this word needs it's own logic: + if (term.clean === "ain't" || term.clean === 'aint') { + return doAint(term, phrase); + } //check white-list - if (i < min - 1) { - continue; //gotta keep going! - } //we can end here, after the minimum + if (irregulars$4.hasOwnProperty(term.clean)) { + return irregulars$4[term.clean]; + } - if (!until) { - term_i += 1; - break; - } // we're greedy-to-now + return null; + }; + var _03Irregulars = checkIrregulars; - if (i >= min && isMatch(t, until)) { - break; - } //end with a greedy-match for next term + var hasApostropheS = /([a-z\u00C0-\u00FF]+)'s$/i; + var blacklist = { + that: true, + there: true + }; + var isPossessive = function isPossessive(term, pool) { + // if we already know it + if (term.tags.Possessive) { + return true; + } //a pronoun can't be possessive - "he's house" - var nextT = ts.terms[term_i + i + 1]; - if (nextT && isMatch(nextT, until)) { - term_i += i + 2; - reg_i += 1; - break; - } else if (i === max - 1) { - //we've maxed-out - return null; - } - } + if (term.tags.Pronoun || term.tags.QuestionWord) { + return false; + } - continue; - } //if optional, check next one + if (blacklist.hasOwnProperty(term.clean)) { + return false; + } //if end of sentence, it is possessive - "was spencer's" - if (reg.optional === true) { - var _until = regs[reg_i + 1]; - term_i = greedyOf(ts, term_i, reg, _until); - continue; - } //check a perfect match + var nextTerm = pool.get(term.next); + if (!nextTerm) { + return true; + } //a gerund suggests 'is walking' - if (isMatch(term, reg, verbose)) { - term_i += 1; //try to greedy-match '+' - if (reg.consecutive === true) { - var _until2 = regs[reg_i + 1]; - term_i = greedyOf(ts, term_i, reg, _until2); + if (nextTerm.tags.Verb) { + //fix 'jamie's bite' + if (nextTerm.tags.Infinitive) { + return true; } - continue; - } - - if (term.silent_term && !term.normal) { - //skip over silent contraction terms - //we will continue on it, but not start on it - if (reg_i === 0) { - return null; - } //try the next term, but with this regex again + return false; + } //spencer's house - term_i += 1; - reg_i -= 1; - continue; - } //handle partial-matches of lumped terms + if (nextTerm.tags.Noun) { + return true; + } //rocket's red glare - var lumpUntil = lumpMatch(term, regs, reg_i, verbose); + var twoTerm = pool.get(nextTerm.next); - if (lumpUntil !== null) { - reg_i = lumpUntil; - term_i += 1; - continue; - } //was it optional anways? + if (twoTerm && twoTerm.tags.Noun && !twoTerm.tags.Pronoun) { + return true; + } //othwerwise, an adjective suggests 'is good' - if (reg.optional === true) { - continue; + if (nextTerm.tags.Adjective || nextTerm.tags.Adverb || nextTerm.tags.Verb) { + return false; } - return null; - } - - return ts.terms.slice(startAt, term_i); -}; - -module.exports = startHere; - -},{"./applyCaptureGroup":167,"./isMatch":171,"./lumpMatch":172}],175:[function(_dereq_,module,exports){ -'use strict'; // parse a search lookup term find the regex-like syntax in this term + return false; + }; -var fns = _dereq_('./paths').fns; //regs- + var isHas = function isHas(term, phrase) { + var terms = phrase.terms(); + var index = terms.indexOf(term); + var after = terms.slice(index + 1, index + 3); //look for a past-tense verb + return after.find(function (t) { + return t.tags.PastTense; + }); + }; -var range = /\{[0-9,]+\}$/; //trim char#0 + var checkPossessive = function checkPossessive(term, phrase, world) { + //the rest of 's + var found = term.text.match(hasApostropheS); -var noFirst = function noFirst(str) { - return str.substr(1, str.length); -}; + if (found !== null) { + //spencer's thing vs spencer-is + if (isPossessive(term, phrase.pool) === true) { + term.tag('#Possessive', 'isPossessive', world); + return null; + } //'spencer is' -var noLast = function noLast(str) { - return str.substring(0, str.length - 1); -}; //turn 'regex-like' search string into parsed json + if (found !== null) { + if (isHas(term, phrase)) { + return [found[1], 'has']; + } -var parse_term = function parse_term(term) { - term = term || ''; - term = term.trim(); - var reg = {}; //order matters here - //1-character hasta be a text-match + return [found[1], 'is']; + } + } - if (term.length === 1 && term !== '.' && term !== '*') { - reg.normal = term.toLowerCase(); - return reg; - } //negation ! flag + return null; + }; + var _04Possessive = checkPossessive; - if (term.charAt(0) === '!') { - term = noFirst(term); - reg.negative = true; - } //leading ^ flag + var hasPerfect = /[a-z\u00C0-\u00FF]'d$/; + /** split `i'd` into 'i had', or 'i would' */ + var checkPerfect = function checkPerfect(term, phrase) { + if (hasPerfect.test(term.clean)) { + var root = term.clean.replace(/'d$/, ''); //look at the next few words - if (term.charAt(0) === '^') { - term = noFirst(term); - reg.starting = true; - } //trailing $ flag means ending + var terms = phrase.terms(); + var index = terms.indexOf(term); + var after = terms.slice(index + 1, index + 4); //is it before a past-tense verb? - 'i'd walked' + for (var i = 0; i < after.length; i++) { + var t = after[i]; - if (term.charAt(term.length - 1) === '$') { - term = noLast(term); - reg.ending = true; - } //optional flag + if (t.tags.Verb) { + if (t.tags.PastTense) { + return [root, 'had']; + } + return [root, 'would']; + } + } //otherwise, 'i'd walk' - if (term.charAt(term.length - 1) === '?') { - term = noLast(term); - reg.optional = true; - } //atleast-one-but-greedy flag + return [root, 'would']; + } - if (term.charAt(term.length - 1) === '+') { - term = noLast(term); - reg.consecutive = true; - } //prefix/suffix/infix matches + return null; + }; + var _05PerfectTense = checkPerfect; - if (term.charAt(term.length - 1) === '_') { - term = noLast(term); - reg.prefix = true; //try both '-match-' + var isRange = /^([0-9]+)[-–—]([0-9]+)$/i; //split '2-4' into '2 to 4' - if (term.charAt(0) === '_') { - term = noFirst(term); - reg.prefix = undefined; - reg.infix = true; + var checkRange = function checkRange(term) { + if (term.tags.PhoneNumber === true) { + return null; } - reg.partial = term; - term = ''; - } else if (term.charAt(0) === '_') { - term = noFirst(term); - reg.suffix = true; - reg.partial = term; - term = ''; - } //min/max any '{1,3}' + var parts = term.text.match(isRange); + if (parts !== null) { + return [parts[1], 'to', parts[2]]; + } - if (term.charAt(term.length - 1) === '}' && range.test(term) === true) { - var m = term.match(/\{([0-9])*,? ?([0-9]+)\}/); - reg.minMax = { - min: parseInt(m[1], 10) || 0, - max: parseInt(m[2], 10) - }; - term = term.replace(range, ''); - } //pos flag + return null; + }; + var _06Ranges = checkRange; - if (term.charAt(0) === '#') { - term = noFirst(term); - reg.tag = fns.titleCase(term); - term = ''; - } //support /regex/ mode + var isNumber = /^[0-9]+$/; + var createPhrase = function createPhrase(found, doc) { + //create phrase from ['would', 'not'] + var phrase = _01Tokenizer.fromText(found.join(' '), doc.world, doc.pool())[0]; //tag it - if (term.charAt(0) === '/' && term.charAt(term.length - 1) === '/') { - term = noLast(term); - term = noFirst(term); //actually make the regex + var terms = phrase.terms(); + _01Lexicon(terms, doc.world); //make these terms implicit - reg.regex = new RegExp(term, 'i'); - term = ''; - } //one_of options flag + terms.forEach(function (t) { + t.implicit = t.text; + t.text = ''; + t.clean = ''; // remove whitespace for implicit terms + t.pre = ''; + t.post = ''; // tag number-ranges - if (term.charAt(0) === '(' && term.charAt(term.length - 1) === ')') { - term = noLast(term); - term = noFirst(term); - var arr = term.split(/\|/g); - reg.oneOf = { - terms: {}, - tagArr: [] - }; - arr.forEach(function (str) { - //try a tag match - if (str.charAt(0) === '#') { - var tag = str.substr(1, str.length); - tag = fns.titleCase(tag); - reg.oneOf.tagArr.push(tag); - } else { - reg.oneOf.terms[str] = true; + if (isNumber.test(t.implicit)) { + t.tags.Number = true; + t.tags.Cardinal = true; } }); - term = ''; - } //a period means any one term - - - if (term === '.') { - reg.anyOne = true; - term = ''; - } //a * means anything until sentence end + return phrase; + }; + var contractions = function contractions(doc) { + var world = doc.world; + doc.list.forEach(function (p) { + var terms = p.terms(); - if (term === '*') { - reg.astrix = true; - term = ''; - } + for (var i = 0; i < terms.length; i += 1) { + var term = terms[i]; + var found = _01Negative(term); + found = found || _02Simple(term); + found = found || _03Irregulars(term, p); + found = found || _04Possessive(term, p, world); + found = found || _05PerfectTense(term, p); + found = found || _06Ranges(term); //add them in - if (term !== '') { - //support \ encoding of #[]()*+?^ - term = term.replace(/\\([\\#\*\.\[\]\(\)\+\?\^])/g, ''); - reg.normal = term.toLowerCase(); - } + if (found !== null) { + var newPhrase = createPhrase(found, doc); //set text as contraction - return reg; -}; //turn a match string into an array of objects + var firstTerm = newPhrase.terms(0); + firstTerm.text = term.text; //grab sub-phrase to remove + var match = p.buildFrom(term.id, 1, doc.pool()); + match.replace(newPhrase, doc, true); + } + } + }); + return doc; + }; -var parse_all = function parse_all(input) { - input = input || ''; - var regs = input.split(/ +/); //bundle-up multiple-words inside parentheses + var _03Contractions = contractions; - for (var i = 0; i < regs.length; i += 1) { - if (regs[i].indexOf('(') !== -1 && regs[i].indexOf(')') === -1) { - var nextWord = regs[i + 1]; + //mostly pos-corections here + var miscCorrection = function miscCorrection(doc) { + //misc: + //foot/feet + doc.match('(foot|feet)').tag('Noun', 'foot-noun'); // blood, sweat, and tears - if (nextWord && nextWord.indexOf('(') === -1 && nextWord.indexOf(')') !== -1) { - regs[i + 1] = regs[i] + ' ' + regs[i + 1]; - regs[i] = ''; - } - } - } + doc.match('(#Noun && @hasComma) #Noun (and|or) [#PresentTense]').tag('#Noun', 'noun-list'); //3 feet - regs = regs.filter(function (f) { - return f; - }); - var captureOn = false; - regs = regs.map(function (reg) { - var hasEnd = false; //support [#Noun] capture-group syntax + doc.match('#Value [(foot|feet)]').tag('Unit', 'foot-unit'); //'u' as pronoun - if (reg.charAt(0) === '[') { - reg = noFirst(reg); - captureOn = true; - } + doc.match('#Conjunction [u]').tag('Pronoun', 'u-pronoun-2'); //6 am - if (reg.charAt(reg.length - 1) === ']') { - reg = noLast(reg); - captureOn = false; - hasEnd = true; - } + doc.match('#Holiday (day|eve)').tag('Holiday', 'holiday-day'); // the captain who - reg = parse_term(reg); + doc.match('#Noun [(who|whom)]').tag('Determiner', 'captain-who'); //timezones - if (captureOn === true || hasEnd === true) { - reg.capture = true; - } + doc.match('(standard|daylight|summer|eastern|pacific|central|mountain) standard? time').tag('Time', 'timezone'); //Brazilian pesos - return reg; - }); - return regs; -}; + doc.match('#Demonym #Currency').tag('Currency', 'demonym-currency'); //about to go -module.exports = parse_all; // console.log(JSON.stringify(parse_all('the (canadian|united states|british) senate'), null, 2)); + doc.match('[about to] #Adverb? #Verb').tag(['Auxiliary', 'Verb'], 'about-to'); //right of way -},{"./paths":173}],176:[function(_dereq_,module,exports){ -'use strict'; // + doc.match('(right|rights) of .').tag('Noun', 'right-of'); // a bit -function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + doc.match('[much] #Adjective').tag('Adverb', 'bit-1'); + doc.match('a [bit]').tag('Noun', 'bit-2'); + doc.match('a bit much').tag('Determiner Adverb Adjective', 'bit-3'); + doc.match('too much').tag('Adverb Adjective', 'bit-4'); // u r cool -var syntax = _dereq_('./lib/syntax'); + doc.match('u r').tag('Pronoun #Copula', 'u r'); // well, ... -var startHere = _dereq_('./lib/startHere'); + doc.match('^(well|so|okay)').tag('Expression', 'well-'); // some conditional statements -var Text = _dereq_('../../text'); + var m = doc.clauses(); // had he survived, -var addfns = function addfns(Terms) { - var fns = { - //blacklist from a {word:true} object - notObj: function notObj(r, obj) { - var matches = []; - var current = []; - r.terms.forEach(function (t) { - //TODO? support multi-word blacklists - //we should blacklist this term - if (obj.hasOwnProperty(t.normal)) { - if (current.length) { - matches.push(current); - } + m.match('^had #Noun+ #PastTense').firstTerm().tag('Condition', 'had-he'); // were he to survive - current = []; - } else { - current.push(t); - } - }); //add remainder + m.match('^were #Noun+ to #Infinitive').firstTerm().tag('Condition', 'were-he'); //swear-words as non-expression POS + //nsfw - if (current.length) { - matches.push(current); - } + doc.match('holy (shit|fuck|hell)').tag('Expression', 'swears-expression'); + doc.match('#Determiner [(shit|damn|hell)]').tag('Noun', 'swears-noun'); + doc.match('[(shit|damn|fuck)] (#Determiner|#Possessive|them)').tag('Verb', 'swears-verb'); + doc.match('#Copula fucked up?').not('#Copula').tag('Adjective', 'swears-adjective'); //ambig prepositions/conjunctions - matches = matches.map(function (a) { - return new Terms(a, r.world, r.refText, r.refTerms); - }); - return new Text(matches, r.world, r.parent); - }, - //blacklist from a match string - notString: function notString(r, want, verbose) { - var matches = []; - var regs = syntax(want); - var terms = []; //try the match starting from each term + var so = doc["if"]('so'); - for (var i = 0; i < r.terms.length; i++) { - var bad = startHere(r, i, regs, verbose); + if (so.found === true) { + //so funny + so.match('[so] #Adjective').tag('Adverb', 'so-adv'); //so the - if (bad && bad.length > 0) { - //reset matches - if (terms.length > 0) { - matches.push(terms); - terms = []; - } //skip these terms now + so.match('[so] #Noun').tag('Conjunction', 'so-conj'); //do so + so.match('do [so]').tag('Noun', 'so-noun'); + } - i += bad.length - 1; - continue; - } + var all = doc["if"]('all'); - terms.push(r.terms[i]); - } //remaining ones + if (all.found === true) { + //all students + all.match('[all] #Determiner? #Noun').tag('Adjective', 'all-noun'); //it all fell apart + all.match('[all] #Verb').tag('Adverb', 'all-verb'); + } //the ambiguous word 'that' and 'which' - if (terms.length > 0) { - matches.push(terms); - } - matches = matches.map(function (a) { - return new Terms(a, r.world, r.refText, r.refTerms); - }); // return matches + var which = doc["if"]('which'); - return new Text(matches, r.world, r.parent); - } - }; //blacklist from a [word, word] array + if (which.found === true) { + //remind john that + which.match('#Verb #Adverb? #Noun [(that|which)]').tag('Preposition', 'that-prep'); //that car goes - fns.notArray = function (r, arr) { - var obj = arr.reduce(function (h, a) { - h[a] = true; - return h; - }, {}); - return fns.notObj(r, obj); - }; + which.match('that #Noun [#Verb]').tag('Determiner', 'that-determiner'); //work, which has been done. - fns.notText = function (r, m) { - var arr = m.out('array'); //i guess this is fine.. + which.match('@hasComma [which] (#Pronoun|#Verb)').tag('Preposition', 'which-copula'); + } //like - return fns.notArray(r, arr); - }; - /**return everything but these matches*/ + var like = doc["if"]('like'); - Terms.prototype.not = function (want, verbose) { - //support [word, word] blacklist - if (_typeof(want) === 'object') { - var type = Object.prototype.toString.call(want); + if (like.found === true) { + like.match('just [like]').tag('Preposition', 'like-preposition'); //folks like her - if (type === '[object Array]') { - return fns.notArray(this, want, verbose); - } + like.match('#Noun [like] #Noun').tag('Preposition', 'noun-like'); //look like - if (type === '[object Object]') { - if (want.isA === 'Text') { - return fns.notText(this, want, verbose); - } else { - return fns.notObj(this, want, verbose); - } - } - } + like.match('#Verb [like]').tag('Adverb', 'verb-like'); //exactly like - if (typeof want === 'string') { - return fns.notString(this, want, verbose); + like.match('#Adverb like').notIf('(really|generally|typically|usually|sometimes|often) [like]').tag('Adverb', 'adverb-like'); } - return this; - }; + var title = doc["if"]('@titleCase'); - return Terms; -}; + if (title.found === true) { + //FitBit Inc + title.match('@titleCase (ltd|co|inc|dept|assn|bros)').tag('Organization', 'org-abbrv'); //Foo District -module.exports = addfns; + title.match('@titleCase+ (district|region|province|county|prefecture|municipality|territory|burough|reservation)').tag('Region', 'foo-district'); //District of Foo -},{"../../text":192,"./lib/startHere":174,"./lib/syntax":175}],177:[function(_dereq_,module,exports){ -'use strict'; - -var mutate = _dereq_('../mutate'); + title.match('(district|region|province|municipality|territory|burough|state) of @titleCase').tag('Region', 'district-of-Foo'); + } -var addMethod = function addMethod(Terms) { - //hook it into Terms.proto - Terms.prototype["delete"] = function (reg) { - //don't touch parent if empty - if (!this.found) { - return this; - } //remove all selected + var hyph = doc["if"]('@hasHyphen'); + if (hyph.found === true) { + //air-flow + hyph.match('@hasHyphen .').match('#Noun #Verb').tag('Noun', 'hyphen-verb'); //connect hyphenated expressions - 'ooh-wee' - if (!reg) { - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - return this; - } //only remove a portion of this + hyph["if"]('#Expression').match('@hasHyphen+').tag('Expression', 'ooh-wee'); + } + var place = doc["if"]('#Place'); - var found = this.match(reg); + if (place.found === true) { + //West Norforlk + place.match('(west|north|south|east|western|northern|southern|eastern)+ #Place').tag('Region', 'west-norfolk'); //some us-state acronyms (exlude: al, in, la, mo, hi, me, md, ok..) - if (found.found) { - var r = mutate.deleteThese(this, found); - return r; + place.match('#City [#Acronym]').match('(al|ak|az|ar|ca|ct|dc|fl|ga|id|il|nv|nh|nj|ny|oh|or|pa|sc|tn|tx|ut|vt|pr)').tag('Region', 'us-state'); } - return this.parentTerms; + return doc; }; - return Terms; -}; - -module.exports = addMethod; + var fixMisc = miscCorrection; -},{"../mutate":188}],178:[function(_dereq_,module,exports){ -'use strict'; + //Determiner-signals + var fixThe = function fixThe(doc) { + var det = doc["if"]('#Determiner'); -var mutate = _dereq_('../mutate'); //whitespace + if (det.found === true) { + var adj = det["if"]('#Adjective'); + if (adj.found) { + //the nice swim + adj.match('(the|this|those|these) #Adjective [#Verb]').tag('Noun', 'the-adj-verb'); // the truly nice swim -var addSpaceAt = function addSpaceAt(ts, i) { - if (!ts.terms.length || !ts.terms[i]) { - return ts; - } - - ts.terms[i].whitespace.before = ' '; - return ts; -}; + adj.match('(the|this|those|these) #Adverb #Adjective [#Verb]').tag('Noun', 'correction-determiner4'); //the orange is -var insertMethods = function insertMethods(Terms) { - //accept any sorta thing - var ensureTerms = function ensureTerms(input, world) { - if (input.isA === 'Terms') { - return input; - } + adj.match('#Determiner [#Adjective] (#Copula|#PastTense|#Auxiliary)').tag('Noun', 'the-adj-2'); //the orange. - if (input.isA === 'Term') { - return new Terms([input], world); - } //handle a string + adj.match('#Determiner #Adjective$').notIf('(#Comparative|#Superlative)').terms(1).tag('Noun', 'the-adj-1'); + } + var inf = det["if"]('#Infinitive'); - var ts = Terms.fromString(input, world); - ts.tagger(); - return ts; - }; + if (inf.found) { + // a stream runs + inf.match('(the|this|a|an) [#Infinitive] #Adverb? #Verb').tag('Noun', 'correction-determiner5'); //the test string - var methods = { - insertBefore: function insertBefore(input, tag) { - var original_l = this.terms.length; - var ts = ensureTerms(input, this.world); + inf.match('#Determiner [#Infinitive] #Noun').tag('Noun', 'correction-determiner7'); //by a bear. - if (tag) { - ts.tag(tag); - } + inf.match('#Determiner [#Infinitive]$').tag('Noun', 'a-inf'); + } //the wait to vote - var index = this.index(); //pad a space on parent - addSpaceAt(this.parentTerms, index); + det.match('(the|this) [#Verb] #Preposition .').tag('Noun', 'correction-determiner1'); //a sense of - if (index > 0) { - addSpaceAt(ts, 0); //if in middle of sentence - } + det.match('#Determiner [#Verb] of').tag('Noun', 'the-verb-of'); //the threat of force - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, ts); //also copy them to current selection + det.match('#Determiner #Noun of [#Verb]').tag('Noun', 'noun-of-noun'); //a close - if (this.terms.length === original_l) { - this.terms = ts.terms.concat(this.terms); - } + det.match('#Determiner #Adverb? [close]').tag('Adjective', 'a-close'); //the western line - return this; - }, - insertAfter: function insertAfter(input, tag) { - var original_l = this.terms.length; - var ts = ensureTerms(input, this.world); + det.match('#Determiner [(western|eastern|northern|southern|central)] #Noun').tag('Noun', 'western-line'); //the swim - if (tag) { - ts.tag(tag); - } + det.match('(the|those|these) [(#Infinitive|#PresentTense|#PastTense)]').tag('Noun', 'correction-determiner2'); + } - var index = this.terms[this.terms.length - 1].index(); //beginning whitespace to ts + var an = doc["if"]('(a|an)'); - addSpaceAt(ts, 0); - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index + 1, ts); //also copy them to current selection + if (an.found === true) { + //a staggering cost + an.match('(a|an) [#Gerund]').tag('Adjective', 'correction-a|an'); //did a 900, paid a 20 - if (this.terms.length === original_l) { - this.terms = this.terms.concat(ts.terms); - } + an.match('#Verb (a|an) [#Value]').tag('Singular', 'a-value'); //a tv show - return this; - }, - insertAt: function insertAt(index, input, tag) { - if (index < 0) { - index = 0; - } + an.match('(a|an) #Noun [#Infinitive]').tag('Noun', 'a-noun-inf'); //a great run - var original_l = this.terms.length; - var ts = ensureTerms(input, this.world); //tag that thing too + an.match('(a|an) #Adjective (#Infinitive|#PresentTense)').terms(2).tag('Noun', 'correction-a|an2'); //'a/an' can mean 1 - "a hour" - if (tag) { - ts.tag(tag); - } + an.match('[(a|an)] (#Duration|hundred|thousand|million|billion|trillion)').ifNo('#Plural').tag('Value', 'a-is-one'); + } - if (index > 0) { - addSpaceAt(ts, 0); //if in middle of sentence - } + return doc; + }; - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, ts); //also copy them to current selection + var fixThe_1 = fixThe; - if (this.terms.length === original_l) { - //splice the new terms into this (yikes!) - Array.prototype.splice.apply(this.terms, [index, 0].concat(ts.terms)); - } //beginning whitespace to ts + // + var fixNouns = function fixNouns(doc) { + var noun = doc["if"]('#Noun'); + if (noun.found === true) { + //'more' is not always an adverb + noun.match('more #Noun').tag('Noun', 'more-noun'); //he quickly foo - if (index === 0) { - this.terms[0].whitespace.before = ''; - ts.terms[ts.terms.length - 1].whitespace.after = ' '; - } + noun.match('#Noun #Adverb [#Noun]').tag('Verb', 'quickly-foo'); //fix for busted-up phrasalVerbs - return this; - } - }; //hook them into result.proto + noun.match('#Noun [#Particle]').tag('Preposition', 'repair-noPhrasal'); //John & Joe's - Object.keys(methods).forEach(function (k) { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = insertMethods; - -},{"../mutate":188}],179:[function(_dereq_,module,exports){ -'use strict'; //these methods are simply term-methods called in a loop - -var addMethods = function addMethods(Terms) { - var foreach = [// ['tag'], - // ['unTag'], - // ['canBe'], - ['toUpperCase', 'UpperCase'], ['toLowerCase'], ['toTitleCase', 'TitleCase']]; - foreach.forEach(function (arr) { - var k = arr[0]; - var tag = arr[1]; - - var myFn = function myFn() { - var args = arguments; - this.terms.forEach(function (t) { - t[k].apply(t, args); - }); + noun.match('#Noun (&|n) #Noun').tag('Organization', 'Noun-&-Noun'); //Aircraft designer - if (tag) { - this.tag(tag, k); - } + noun.match('#Noun #Actor').tag('Actor', 'thing-doer'); //j.k Rowling - return this; - }; + doc.match('#Noun van der? #Noun').tagSafe('#Person', 'von der noun'); //king of spain - Terms.prototype[k] = myFn; - }); - return Terms; -}; + doc.match('(king|queen|prince|saint|lady) of? #Noun').tagSafe('#Person', 'king-of-noun'); // addresses -module.exports = addMethods; + doc.match('#Value #Noun (st|street|rd|road|crescent|cr|way|tr|terrace|avenue|ave)').tag('Address'); // schools -},{}],180:[function(_dereq_,module,exports){ -'use strict'; + doc.match('#Noun+ (public|private) school').tag('School'); //the word 'second' -var Term = _dereq_('../../../term'); //merge two term objects.. carefully + noun.match('[second] #Noun').notIf('#Honorific').unTag('Unit').tag('Ordinal', 'second-noun'); //linear algebra + noun.match('(#Determiner|#Value) [(linear|binary|mobile|lexical|technical|computer|scientific|formal)] #Noun').tag('Noun', 'technical-noun'); //organization -var makeText = function makeText(a, b) { - var text = a.whitespace.before + a.text + a.whitespace.after; - text += b.whitespace.before + b.text + b.whitespace.after; - return text; -}; + var org = noun["if"]('#Organization'); -var combine = function combine(s, i) { - var a = s.terms[i]; - var b = s.terms[i + 1]; + if (org.found === true) { + org.match('#Organization of the? @titleCase').tagSafe('Organization', 'org-of-place'); + org.match('#Organization #Country').tag('Organization', 'org-country'); + org.match('(world|global|international|national|#Demonym) #Organization').tag('Organization', 'global-org'); + org.match('#TitleCase #Organization').ifNo('@hasComma').tag('Organization', 'titlecase-org'); + } - if (!b) { - return; - } + var plural = noun["if"]('#Plural'); - var text = makeText(a, b); - s.terms[i] = new Term(text, a.context); - s.terms[i].normal = a.normal + ' ' + b.normal; - s.terms[i].lumped = true; - s.terms[i].parentTerms = s.terms[i + 1].parentTerms; - s.terms[i + 1] = null; - s.terms = s.terms.filter(function (t) { - return t !== null; - }); - return; -}; + if (plural.found === true) { + //some pressing issues + plural.match('some [#Verb] #Plural').tag('Noun', 'correction-determiner6'); //this rocks -module.exports = combine; + noun.match('(this|that) [#Plural]').tag('PresentTense', 'this-verbs'); + } + } //acronyms -},{"../../../term":143}],181:[function(_dereq_,module,exports){ -'use strict'; -var combine = _dereq_('./combine'); + var acronym = doc["if"]('#Acronym'); -var mutate = _dereq_('../../mutate'); //merge-together our current match into one term + if (acronym.found === true) { + acronym.match('the [#Acronym]').notIf('(iou|fomo|yolo|diy|dui|nimby)').tag('Organization', 'the-acronym'); + acronym.match('#Acronym').match('#Possessive').tag('Organization', 'possessive-acronym'); + } //possessives -var combineThem = function combineThem(ts, tags) { - var len = ts.terms.length; + var poss = doc["if"]('#Possessive'); - for (var i = 0; i < len; i++) { - combine(ts, 0); - } + if (poss.found === true) { + //my buddy + poss.match('#Possessive [#FirstName]').unTag('Person', 'possessive-name'); //spencer kelly's - var lumped = ts.terms[0]; - lumped.tags = tags; - return lumped; -}; + poss.match('#FirstName #Acronym? #Possessive').ifNo('@hasComma').match('#FirstName #Acronym? #LastName').tag('Possessive'); //Super Corp's fundraiser -var lumpMethods = function lumpMethods(Terms) { - Terms.prototype.lump = function () { - //collect the tags up - var index = this.index(); - var tags = {}; - this.terms.forEach(function (t) { - Object.keys(t.tags).forEach(function (tag) { - return tags[tag] = true; - }); - }); //just lump the whole-thing together + poss.match('#Organization+ #Possessive').ifNo('@hasComma').tag('Possessive'); //Los Angeles's fundraiser - if (this.parentTerms === this) { - var _lumped = combineThem(this, tags); + poss.match('#Place+ #Possessive').ifNo('@hasComma').tag('Possessive'); //her polling - this.terms = [_lumped]; - return this; - } //otherwise lump just part of it. delete/insert. + poss.match('#Possessive [#Verb]').tag('Noun', 'correction-possessive'); + } + return doc; + }; - this.parentTerms = mutate.deleteThese(this.parentTerms, this); //merge-together our current match into one term + var fixNouns_1 = fixNouns; - var lumped = combineThem(this, tags); //put it back (in the same place) + var maybeNoun = '(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)'; + var maybeVerb = '(pat|wade|ollie|will|rob|buck|bob|mark|jack)'; + var maybeAdj = '(misty|rusty|dusty|rich|randy)'; + var maybeDate = '(april|june|may|jan|august|eve)'; + var maybePlace = '(paris|alexandria|houston|kobe|salvador|sydney)'; - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, lumped); - return this; - }; + var fixPerson = function fixPerson(doc) { + // clues from honorifics + var hon = doc["if"]('#Honorific'); - return Terms; -}; + if (hon.found === true) { + //mr Putin + doc.match('(mr|mrs|ms|dr) (#TitleCase|#Possessive)+').tag('#Person', 'mr-putin'); //mr X -module.exports = lumpMethods; + hon.match('#Honorific #Acronym').tag('Person', 'Honorific-TitleCase'); //remove single 'mr' -},{"../../mutate":188,"./combine":180}],182:[function(_dereq_,module,exports){ -'use strict'; + hon.match('^#Honorific$').unTag('Person', 'single-honorific'); //first general.. -var _tagger = _dereq_('../../tagger'); + hon.match('[(1st|2nd|first|second)] #Honorific').tag('Honorific', 'ordinal-honorific'); + } //methods requiring a titlecase -var miscMethods = function miscMethods(Terms) { - var methods = { - tagger: function tagger() { - _tagger(this); - return this; - }, - firstTerm: function firstTerm() { - return this.terms[0]; - }, - lastTerm: function lastTerm() { - return this.terms[this.terms.length - 1]; - }, - all: function all() { - return this.parent; - }, - data: function data() { - return { - text: this.out('text'), - normal: this.out('normal') - }; - }, - term: function term(n) { - return this.terms[n]; - }, - first: function first() { - var t = this.terms[0]; - return new Terms([t], this.world, this.refText, this.refTerms); - }, - last: function last() { - var t = this.terms[this.terms.length - 1]; - return new Terms([t], this.world, this.refText, this.refTerms); - }, - slice: function slice(start, end) { - var terms = this.terms.slice(start, end); - return new Terms(terms, this.world, this.refText, this.refTerms); - }, - index: function index() { - var parent = this.parentTerms; - var first = this.terms[0]; + var title = doc["if"]('#TitleCase'); - if (!parent || !first) { - return null; //maybe.. - } + if (title.found === true) { + title.match('#Acronym #TitleCase').tagSafe('#Person', 'acronym-titlecase'); //ludwig van beethovan - for (var i = 0; i < parent.terms.length; i++) { - if (first === parent.terms[i]) { - return i; - } - } + title.match('#TitleCase (van|al|bin) #TitleCase').tagSafe('Person', 'titlecase-van-titlecase'); //jose de Sucre - return null; - }, - termIndex: function termIndex() { - var first = this.terms[0]; - var ref = this.refText || this; + title.match('#TitleCase (de|du) la? #TitleCase').tagSafe('Person', 'titlecase-van-titlecase'); //pope francis - if (!ref || !first) { - return null; //maybe.. - } + title.match('(lady|queen|sister) #TitleCase').ifNo('#Date').ifNo('#Honorific').tag('#FemaleName', 'lady-titlecase'); + title.match('(king|pope|father) #TitleCase').ifNo('#Date').tag('#MaleName', 'poe'); // jean Foobar - var n = 0; + title.match(maybeNoun + ' #Acronym? #TitleCase').tagSafe('Person', 'ray-smith'); // rob Foobar - for (var i = 0; i < ref.list.length; i++) { - var ts = ref.list[i]; + title.match(maybeVerb + ' #Acronym? #TitleCase').tag('Person', 'rob-smith'); // rusty Foobar - for (var o = 0; o < ts.terms.length; o++) { - if (ts.terms[o] === first) { - return n; - } + title.match(maybeAdj + ' #Acronym? #TitleCase').tag('Person', 'rusty-smith'); // june Foobar - n += 1; - } - } + title.match(maybeDate + ' #Acronym? (#TitleCase && !#Month)').tagSafe('Person', 'june-smith'); + } - return n; - }, - //number of characters in this match - chars: function chars() { - return this.terms.reduce(function (i, t) { - i += t.whitespace.before.length; - i += t.text.length; - i += t.whitespace.after.length; - return i; - }, 0); - }, - //just .length - wordCount: function wordCount() { - return this.terms.length; - }, + var person = doc["if"]('#Person'); - /** punctuation */ - setPunctuation: function setPunctuation(punct) { - var last = this.terms[this.terms.length - 1]; - last.setPunctuation(punct); - }, - getPunctuation: function getPunctuation() { - var lastTerm = this.last().terms[0]; + if (person.found === true) { + //Frank jr + person.match('#Person (jr|sr|md)').tag('Person', 'person-honorific'); //peter II - if (!lastTerm) { - return ''; - } + person.match('#Person #Person the? #RomanNumeral').tag('Person', 'roman-numeral'); //'Professor Fink', 'General McCarthy' - return lastTerm.getPunctuation() || ''; - }, - //this has term-order logic, so has to be here - toCamelCase: function toCamelCase() { - this.toTitleCase(); - this.terms.forEach(function (t, i) { - if (i !== 0) { - t.whitespace.before = ''; - } + person.match('#Honorific #Person').tag('Person', 'Honorific-Person'); // 'john E rockefeller' - t.whitespace.after = ''; - }); - this.tag('#CamelCase', 'toCamelCase'); - return this; - } - }; //hook them into result.proto + person.match('#FirstName [/^[^aiurck]$/]').tag(['Acronym', 'Person'], 'john-e'); //Doctor john smith jr - Object.keys(methods).forEach(function (k) { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; + person.match('#Honorific #Person').tag('Person', 'honorific-person'); //general pearson -module.exports = miscMethods; + person.match('[(private|general|major|corporal|lord|lady|secretary|premier)] #Honorific? #Person').tag('Honorific', 'ambg-honorifics'); //Morgan Shlkjsfne -},{"../../tagger":95}],183:[function(_dereq_,module,exports){ -'use strict'; + title.match('#Person #TitleCase').match('#TitleCase #Noun').tagSafe('Person', 'person-titlecase'); //a bunch of ambiguous first names + //Nouns: 'viola' or 'sky' -var fns = _dereq_('../paths').fns; + var ambigNoun = person["if"](maybeNoun); -var methods = { - text: function text(ts) { - return ts.terms.reduce(function (str, t) { - str += t.out('text'); - return str; - }, ''); - }, - //like 'text', but no leading/trailing whitespace - match: function match(ts) { - var str = ''; - var len = ts.terms.length; + if (ambigNoun.found === true) { + // ambigNoun.match('(#Determiner|#Adverb|#Pronoun|#Possessive) [' + maybeNoun + ']').tag('Noun', 'the-ray') + ambigNoun.match(maybeNoun + ' #Person').tagSafe('Person', 'ray-smith'); + } //Verbs: 'pat' or 'wade' - for (var i = 0; i < len; i++) { - if (i > 0) { - str += ts.terms[i].whitespace.before; - } - str += ts.terms[i].text.replace(/[,.?!]$/, ''); //remove comma + var ambigVerb = person["if"](maybeVerb); - if (i < len - 1) { - str += ts.terms[i].whitespace.after; - } - } + if (ambigVerb === true) { + ambigVerb.match('(#Modal|#Adverb) [' + maybeVerb + ']').tag('Verb', 'would-mark'); + ambigVerb.match(maybeVerb + ' #Person').tag('Person', 'rob-smith'); + } //Adjectives: 'rusty' or 'rich' - return str; - }, - normal: function normal(ts) { - var terms = ts.terms.filter(function (t) { - return t.text; - }); - terms = terms.map(function (t) { - return t.normal; //+ punct; - }); - return terms.join(' '); - }, - grid: function grid(ts) { - var str = ' '; - str += ts.terms.reduce(function (s, t) { - s += fns.leftPad(t.text, 11); - return s; - }, ''); - return str + '\n\n'; - }, - color: function color(ts) { - return ts.terms.reduce(function (s, t) { - s += fns.printTerm(t); - return s; - }, ''); - }, - csv: function csv(ts) { - return ts.terms.map(function (t) { - return t.normal.replace(/,/g, ''); - }).join(','); - }, - newlines: function newlines(ts) { - return ts.terms.reduce(function (str, t) { - str += t.out('text').replace(/\n/g, ' '); - return str; - }, '').replace(/^\s/, ''); - }, - /** no punctuation, fancy business **/ - root: function root(ts) { - return ts.terms.map(function (t) { - return t.silent_term || t.root; - }).join(' ').toLowerCase(); - }, - html: function html(ts) { - return ts.terms.map(function (t) { - return t.render.html(); - }).join(' '); - }, - debug: function debug(ts) { - ts.terms.forEach(function (t) { - t.out('debug'); - }); - }, - custom: function custom(ts, obj) { - return ts.terms.map(function (t) { - return Object.keys(obj).reduce(function (h, k) { - if (obj[k] && t[k]) { - if (typeof t[k] === 'function') { - h[k] = t[k](); - } else { - h[k] = t[k]; - } - } + var ambigAdj = person["if"](maybeAdj); - return h; - }, {}); - }); - } -}; -methods.plaintext = methods.text; -methods.normalize = methods.normal; -methods.normalized = methods.normal; -methods.colors = methods.color; -methods.tags = methods.terms; + if (ambigAdj.found === true) { + ambigAdj.match('#Adverb [' + maybeAdj + ']').tag('Adjective', 'really-rich'); + ambigAdj.match(maybeAdj + ' #Person').tag('Person', 'randy-smith'); + } //Dates: 'june' or 'may' -var renderMethods = function renderMethods(Terms) { - Terms.prototype.out = function (fn) { - if (typeof fn === 'string') { - if (methods[fn]) { - return methods[fn](this); - } - } else if (fns.isObject(fn) === true) { - //support .out({}) - return methods.custom(this, fn); - } - return methods.text(this); - }; //check method + var ambigDate = person["if"](maybeDate); + if (ambigDate.found === true) { + ambigDate.match(String(maybeDate) + ' #Person').tagSafe('Person', 'june-smith'); + ambigDate.match('(in|during|on|by|before|#Date) [' + maybeDate + ']').tagSafe('Date', 'in-june'); + ambigDate.match(maybeDate + ' (#Date|#Value)').tagSafe('Date', 'june-5th'); + } //Places: paris or syndey - Terms.prototype.debug = function () { - return methods.debug(this); - }; - return Terms; -}; + var ambigPlace = person["if"](maybePlace); -module.exports = renderMethods; + if (ambigPlace.found === true) { + ambigPlace.match('(in|near|at|from|to|#Place) [' + maybePlace + ']').tagSafe('Place', 'in-paris'); + ambigPlace.match('[' + maybePlace + '] #Place').tagSafe('Place', 'paris-france'); // ambigPlace.match('[' + maybePlace + '] #Person').tagSafe('Person', 'paris-hilton') + } //this one is tricky -},{"../paths":189}],184:[function(_dereq_,module,exports){ -'use strict'; -var mutate = _dereq_('../mutate'); + var al = person["if"]('al'); -var replaceMethods = function replaceMethods(Terms) { - var methods = { - /**swap this for that */ - replace: function replace(str1, str2, keepTags) { - //in this form, we 'replaceWith' - if (str2 === undefined) { - return this.replaceWith(str1, keepTags); + if (al.found === true) { + al.match('al (#Person|#TitleCase)').tagSafe('#Person', 'al-borlen'); + al.match('#TitleCase al #TitleCase').tagSafe('#Person', 'arabic-al-arabic'); } - this.match(str1).replaceWith(str2, keepTags); - return this; - }, + var firstName = person["if"]('#FirstName'); - /**swap this for that */ - replaceWith: function replaceWith(str, keepTags) { - var newTs = Terms.fromString(str, this.world); - newTs.tagger(); //if instructed, apply old tags to new terms + if (firstName.found === true) { + //ferdinand de almar + firstName.match('#FirstName de #Noun').tag('#Person', 'firstname-de-noun'); //Osama bin Laden - if (keepTags) { - this.terms.forEach(function (t, i) { - var tags = Object.keys(t.tags); + firstName.match('#FirstName (bin|al) #Noun').tag('#Person', 'firstname-al-noun'); //John L. Foo - if (newTs.terms[i] !== undefined) { - tags.forEach(function (tg) { - return newTs.terms[i].tag(tg, 'from-memory'); - }); - } - }); - } //keep its ending punctation.. + firstName.match('#FirstName #Acronym #TitleCase').tag('Person', 'firstname-acronym-titlecase'); //Andrew Lloyd Webber + firstName.match('#FirstName #FirstName #TitleCase').tag('Person', 'firstname-firstname-titlecase'); //Mr Foo - var endPunct = this.getPunctuation(); //grab the insertion place.. + firstName.match('#Honorific #FirstName? #TitleCase').tag('Person', 'Honorific-TitleCase'); //peter the great - var index = this.index(); - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, newTs); - this.terms = newTs.terms; //add-in the punctuation at the end.. + firstName.match('#FirstName the #Adjective').tag('Person', 'determiner5'); //very common-but-ambiguous lastnames - if (this.terms.length > 0) { - this.terms[this.terms.length - 1].whitespace.after += endPunct; - } + firstName.match('#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)').tag('#Person', 'firstname-maybe'); //John Foo - return this; - } - }; //hook them into result.proto + firstName.match('#FirstName #TitleCase #TitleCase?').match('#Noun+').tag('Person', 'firstname-titlecase'); //Joe K. Sombrero - Object.keys(methods).forEach(function (k) { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; + firstName.match('#FirstName #Acronym #Noun').ifNo('#Date').tag('#Person', 'n-acro-noun').lastTerm().tag('#LastName', 'n-acro-noun'); // Dwayne 'the rock' Johnson + + firstName.match('#FirstName [#Determiner #Noun] #LastName').tag('#NickName', 'first-noun-last').tag('#Person', 'first-noun-last'); //john bodego's -module.exports = replaceMethods; + firstName.match('#FirstName (#Singular|#Possessive)').ifNo('(#Date|#Pronoun|#NickName)').tag('#Person', 'first-possessive').lastTerm().tag('#LastName', 'first-possessive'); // Firstname x (dangerous) -},{"../mutate":188}],185:[function(_dereq_,module,exports){ -'use strict'; //break apart a termlist into (before, match after) + var tmp = firstName.match('#FirstName (#Noun|#TitleCase)').ifNo('^#Possessive').ifNo('#ClauseEnd .').ifNo('#Pronoun'); + tmp.lastTerm().tag('#LastName', 'firstname-noun'); + } -var breakUpHere = function breakUpHere(terms, ts) { - var firstTerm = ts.terms[0]; - var len = ts.terms.length; + var lastName = person["if"]('#LastName'); - for (var i = 0; i < terms.length; i++) { - if (terms[i] === firstTerm) { - return { - before: terms.slice(0, i), - match: terms.slice(i, i + len), - after: terms.slice(i + len, terms.length) - }; + if (lastName.found === true) { + //is foo Smith + lastName.match('#Copula [(#Noun|#PresentTense)] #LastName').tag('#FirstName', 'copula-noun-lastname'); // x Lastname + + lastName.match('[#Noun] #LastName').canBe('#FirstName').tag('#FirstName', 'noun-lastname'); //ambiguous-but-common firstnames + + lastName.match('[(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill)] #LastName').tag('#FirstName', 'maybe-lastname'); //Jani K. Smith + + lastName.match('(#TitleCase|#Singular) #Acronym? #LastName').ifNo('#Date').tag('#Person', 'title-acro-noun').lastTerm().tag('#LastName', 'title-acro-noun'); + } } - } - return { - after: terms + return doc; }; -}; -var splitMethods = function splitMethods(Terms) { - var methods = { - /** at the end of the match, split the terms **/ - splitAfter: function splitAfter(reg, verbose) { - var _this = this; + var fixPerson_1 = fixPerson; - var ms = this.match(reg, verbose); //Array[ts] + var advb = '(#Adverb|not)+?'; // - var termArr = this.terms; - var all = []; - ms.list.forEach(function (lookFor) { - var section = breakUpHere(termArr, lookFor); + var fixVerb = function fixVerb(doc) { + var vb = doc["if"]('#Verb'); - if (section.before && section.match) { - all.push(section.before.concat(section.match)); - } + if (vb.found) { + vb.match('[(do|does|will|have|had)] (not|#Adverb)? #Verb').tag('Auxiliary', 'have-had'); //still make - termArr = section.after; - }); //add the remaining + vb.match('[still] #Verb').tag('Adverb', 'still-verb'); //'u' as pronoun - if (termArr.length) { - all.push(termArr); - } //make them termlists + vb.match('[u] #Verb').tag('Pronoun', 'u-pronoun-1'); //is no walk + vb.match('is no [#Verb]').tag('Noun', 'is-no-verb'); //different views than - all = all.map(function (ts) { - var parent = _this.refText; //|| this; + vb.match('[#Verb] than').tag('Noun', 'correction'); // smoked poutine is - return new Terms(ts, _this.world, parent, _this.refTerms); - }); - return all; - }, + vb.match('[#PastTense] #Singular is').tag('#Adjective', 'smoked-poutine'); // baked onions are - /** return only before & after the match**/ - splitOn: function splitOn(reg, verbose) { - var _this2 = this; + vb.match('[#PastTense] #Plural are').tag('#Adjective', 'baked-onions'); // goes to sleep - var ms = this.match(reg, verbose); //Array[ts] + vb.match('(go|goes|went) to [#Infinitive]').tag('#Noun', 'goes-to-verb'); //there are reasons - var termArr = this.terms; - var all = []; - ms.list.forEach(function (lookFor) { - var section = breakUpHere(termArr, lookFor); + vb.match('there (are|were) #Adjective? [#PresentTense]').tag('Plural', 'there-are'); //jack seems guarded - if (section.before) { - all.push(section.before); - } + vb.match('#Singular (seems|appears) #Adverb? [#PastTense$]').tag('Adjective', 'seems-filled'); //fall over - if (section.match) { - all.push(section.match); - } + vb.match('#PhrasalVerb [#PhrasalVerb]').tag('Particle', 'phrasal-particle'); //went to sleep + // vb.match('#Verb to #Verb').lastTerm().tag('Noun', 'verb-to-verb'); + //been walking - termArr = section.after; - }); //add the remaining + vb.match("(be|been) ".concat(advb, " #Gerund")).not('#Verb$').tag('Auxiliary', 'be-walking'); // directive verb - 'use reverse' - if (termArr.length) { - all.push(termArr); - } //make them termlists + vb.match('(try|use|attempt|build|make) #Verb').ifNo('(@hasComma|#Negative|#Copula|will|be)').lastTerm().tag('#Noun', 'do-verb'); //infinitive verbs suggest plural nouns - 'XYZ walk to the store' + // r.match(`#Singular+ #Infinitive`).match('#Singular+').tag('Plural', 'infinitive-make-plural'); + var modal = vb["if"]('(#Modal|did|had|has)'); - all = all.filter(function (a) { - return a && a.length; - }); - all = all.map(function (ts) { - return new Terms(ts, _this2.world, ts.refText, _this2.refTerms); - }); - return all; - }, + if (modal.found === true) { + //support a splattering of auxillaries before a verb + modal.match("(has|had) ".concat(advb, " #PastTense")).not('#Verb$').tag('Auxiliary', 'had-walked'); //would walk - /** at the start of the match, split the terms**/ - splitBefore: function splitBefore(reg, verbose) { - var _this3 = this; + modal.match("(#Modal|did) ".concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'modal-verb'); //would have had - var ms = this.match(reg, verbose); //Array[ts] + modal.match("#Modal ".concat(advb, " have ").concat(advb, " had ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-have'); //would be walking - var termArr = this.terms; - var all = []; - ms.list.forEach(function (lookFor) { - var section = breakUpHere(termArr, lookFor); + modal.match("#Modal ".concat(advb, " be ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-be'); //would been walking - if (section.before) { - all.push(section.before); - } + modal.match("(#Modal|had|has) ".concat(advb, " been ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-be'); + } - if (section.match) { - all.push(section.match); - } + var copula = vb["if"]('#Copula'); - termArr = section.after; - }); //add the remaining + if (copula.found === true) { + //was walking + copula.match("#Copula ".concat(advb, " #Gerund")).not('#Verb$').tag('Auxiliary', 'copula-walking'); //is mark hughes - if (termArr.length) { - all.push(termArr); - } //cleanup-step: merge all (middle) matches with the next one + copula.match('#Copula [#Infinitive] #Noun').tag('Noun', 'is-pres-noun'); // + copula.match('[#Infinitive] #Copula').tag('Noun', 'inf-copula'); //sometimes not-adverbs - for (var i = 0; i < all.length; i++) { - for (var o = 0; o < ms.length; o++) { - if (ms.list[o].terms[0] === all[i][0]) { - if (all[i + 1]) { - all[i] = all[i].concat(all[i + 1]); - all[i + 1] = []; - } - } - } - } //make them termlists + copula.match('#Copula [(just|alone)]$').tag('Adjective', 'not-adverb'); //jack is guarded + copula.match('#Singular is #Adverb? [#PastTense$]').tag('Adjective', 'is-filled'); //is eager to go - all = all.filter(function (a) { - return a && a.length; - }); - all = all.map(function (ts) { - return new Terms(ts, ts.world, ts.refText, _this3.refTerms); - }); - return all; - } - }; //hook them into result.proto + copula.match('#Copula [#Adjective to] #Verb').tag('Verb', 'adj-to'); //sometimes adverbs - 'pretty good','well above' - Object.keys(methods).forEach(function (k) { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; + copula.match('#Copula (pretty|dead|full|well) (#Adjective|#Noun)').ifNo('@hasComma').tag('#Copula #Adverb #Adjective', 'sometimes-adverb'); + } //Gerund - 'walking' -module.exports = splitMethods; -exports = splitMethods; -},{}],186:[function(_dereq_,module,exports){ -'use strict'; + var gerund = vb["if"]('#Gerund'); -var addMethod = function addMethod(Terms) { - var methods = { - tag: function tag(_tag, reason) { - var tags = []; + if (gerund.found === true) { + //walking is cool + gerund.match('[#Gerund] #Adverb? not? #Copula').tag('Activity', 'gerund-copula'); //walking should be fun - if (typeof _tag === 'string') { - tags = _tag.split(' '); - } //fancy version: + gerund.match('[#Gerund] #Modal').tag('Activity', 'gerund-modal'); //running-a-show + gerund.match('#Gerund #Determiner [#Infinitive]').tag('Noun', 'running-a-show'); //setting records + // doc.match('#Gerund [#PresentTense]').tag('Plural', 'setting-records'); + } //'will be' - if (tags.length > 1) { - //do indepenent tags for each term: - this.terms.forEach(function (t, i) { - t.tag(tags[i], reason); - }); - return this; - } //non-fancy version: + var willBe = vb["if"]('will #Adverb? not? #Adverb? be'); - this.terms.forEach(function (t) { - t.tag(_tag, reason); - }); - return this; - }, - unTag: function unTag(tag, reason) { - var tags = []; + if (willBe.found === true) { + //will be running (not copula + if (willBe.has('will #Adverb? not? #Adverb? be #Gerund') === false) { + //tag it all + willBe.match('will not? be').tag('Copula', 'will-be-copula'); //for more complex forms, just tag 'be' - if (typeof tag === 'string') { - tags = tag.split(' '); - } //fancy version: + willBe.match('will #Adverb? not? #Adverb? be #Adjective').match('be').tag('Copula', 'be-copula'); + } + } + } //question words - if (tags.length > 1) { - //do indepenent tags for each term: - this.terms.forEach(function (t, i) { - t.unTag(tags[i], reason); - }); - return this; - } //non-fancy version: + var m = doc["if"]('(who|what|where|why|how|when)'); + if (m.found) { + //the word 'how' + m.match('^how').tag('QuestionWord', 'how-question'); + m.match('[how] (#Determiner|#Copula|#Modal|#PastTense)').tag('QuestionWord', 'how-is'); // //the word 'which' - this.terms.forEach(function (t) { - t.unTag(tag, reason); - }); - return this; - }, - //which terms are consistent with this tag - canBe: function canBe(tag) { - var terms = this.terms.filter(function (t) { - return t.canBe(tag); - }); - return new Terms(terms, this.world, this.refText, this.refTerms); + m.match('^which').tag('QuestionWord', 'which-question'); + m.match('[which] . (#Noun)+ #Pronoun').tag('QuestionWord', 'which-question2'); + m.match('which').tag('QuestionWord', 'which-question3'); //how he is driving + + m.match('[#QuestionWord] #Noun #Copula #Adverb? (#Verb|#Adjective)').unTag('QuestionWord').tag('Conjunction', 'how-he-is-x'); //when i go fishing + + m.match('#QuestionWord #Noun #Adverb? #Infinitive not? #Gerund').unTag('QuestionWord').tag('Conjunction', 'when i go fishing'); } - }; //hook them into result.proto - Object.keys(methods).forEach(function (k) { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; + return doc; + }; -module.exports = addMethod; + var fixVerb_1 = fixVerb; -},{}],187:[function(_dereq_,module,exports){ -'use strict'; + // + var fixAdjective = function fixAdjective(doc) { + var adj = doc["if"]('#Adjective'); -var transforms = function transforms(Terms) { - var methods = { - clone: function clone() { - // this.world = this.world.clone(); - var terms = this.terms.map(function (t) { - return t.clone(); - }); - return new Terms(terms, this.world, this.refText, null); //, this.refTerms - }, - hyphenate: function hyphenate() { - var _this = this; + if (adj.found) { + //still good + adj.match('[still] #Adjective').tag('Adverb', 'still-advb'); //barely even walk - this.terms.forEach(function (t, i) { - if (i !== _this.terms.length - 1) { - t.whitespace.after = '-'; - } + adj.match('(barely|hardly) even').tag('#Adverb', 'barely-even'); //big dreams, critical thinking - if (i !== 0) { - t.whitespace.before = ''; - } - }); - return this; - }, - dehyphenate: function dehyphenate() { - this.terms.forEach(function (t) { - if (t.whitespace.after === '-') { - t.whitespace.after = ' '; - } - }); - return this; - }, - trim: function trim() { - if (this.length <= 0) { - return this; - } + adj.match('#Adjective [#PresentTense]').tag('Noun', 'adj-presentTense'); //will secure our - this.terms[0].whitespace.before = ''; - this.terms[this.terms.length - 1].whitespace.after = ''; - return this; + adj.match('will [#Adjective]').tag('Verb', 'will-adj'); //cheering hard - dropped -ly's + + adj.match('#PresentTense [(hard|quick|long|bright|slow)]').tag('Adverb', 'lazy-ly'); //his fine + + adj.match('(his|her|its) [#Adjective]').tag('Noun', 'his-fine'); //he left + + adj.match('#Noun #Adverb? [left]').tag('PastTense', 'left-verb'); //he disguised the thing + + adj.match('#Pronoun [#Adjective] #Determiner #Adjective? #Noun').tag('Verb', 'he-adj-the'); } - }; //hook them into result.proto - Object.keys(methods).forEach(function (k) { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; + return doc; + }; -module.exports = transforms; + var fixAdjective_1 = fixAdjective; -},{}],188:[function(_dereq_,module,exports){ -'use strict'; // + var units = '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)'; // -var getTerms = function getTerms(needle) { - var arr = []; + var fixValue = function fixValue(doc) { + var val = doc["if"]('#Value'); - if (needle.isA === 'Terms') { - arr = needle.terms; - } else if (needle.isA === 'Text') { - arr = needle.flatten().list[0].terms; - } else if (needle.isA === 'Term') { - arr = [needle]; - } + if (val.found === true) { + //1 800 PhoneNumber + val.match('1 #Value #PhoneNumber').tag('PhoneNumber', '1-800-Value'); //(454) 232-9873 - return arr; -}; //remove them + val.match('#NumericValue #PhoneNumber').tag('PhoneNumber', '(800) PhoneNumber'); //three trains + val.match('#Value [#PresentTense]').tag('Plural', 'value-presentTense'); //money -exports.deleteThese = function (source, needle) { - var arr = getTerms(needle); - source.terms = source.terms.filter(function (t) { - for (var i = 0; i < arr.length; i++) { - if (t === arr[i]) { - return false; - } - } + var m = val.match('#Value+ #Currency'); + m.lastTerm().tag('Unit', 'money-unit'); + m.match('#Value+').tag('Money', 'value-currency'); + } //5 kg. - return true; - }); - return source; -}; //add them + val.match('#Value #Abbreviation').tag('Value', 'value-abbr'); //seven point five -exports.insertAt = function (terms, i, needle) { - needle.dirty = true; - var arr = getTerms(needle); //handle whitespace + val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value'); //minus 7 - if (i > 0 && arr[0] && !arr[0].whitespace.before) { - arr[0].whitespace.before = ' '; - } //gnarly splice - //-( basically - terms.splice(i+1, 0, arr) ) + val.match('(minus|negative) #Value').tag('Value', 'minus-value'); // ten grand + val.match('#Value grand').tag('Value', 'value-grand'); //quarter million - Array.prototype.splice.apply(terms, [i, 0].concat(arr)); - return terms; -}; + val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal'); //eg 'trillion' -},{}],189:[function(_dereq_,module,exports){ -"use strict"; + var mult = val["if"](units); -module.exports = { - fns: _dereq_('../fns'), - Term: _dereq_('../term') -}; + if (mult.found === true) { + mult.match('a #Value').tag('Value', 'a-value'); //? + // mult.match('#Ordinal (half|quarter)').tag('Value', 'ordinal-half');//not ready -},{"../fns":3,"../term":143}],190:[function(_dereq_,module,exports){ -'use strict'; + mult.match("".concat(units, " and #Value")).tag('Value', 'magnitude-and-value'); + } -var Text = _dereq_('./index'); + return doc; + }; -var tokenize = _dereq_('./tokenize'); + var fixValue_1 = fixValue; -var paths = _dereq_('./paths'); + var preps = '(in|by|before|during|on|until|after|of|within|all)'; //6 -var Terms = paths.Terms; -var fns = paths.fns; + var people = '(january|april|may|june|summer|autumn|jan|sep)'; //ambiguous month-names -var fromString = function fromString(str, world) { - var sentences = []; //allow pre-tokenized input + var verbs$2 = '(may|march)'; //ambiguous month-verbs - if (fns.isArray(str)) { - sentences = str; - } else { - str = fns.ensureString(str); - sentences = tokenize(str); - } + var fixDates = function fixDates(doc) { + //ambiguous month - person forms + var person = doc["if"](people); - var list = sentences.map(function (s) { - return Terms.fromString(s, world); - }); - var doc = new Text(list, world); //give each ts a ref to the result + if (person.found === true) { + //give to april + person.match("#Infinitive #Determiner? #Adjective? #Noun? (to|for) [".concat(people, "]")).tag('Person', 'ambig-person'); //remind june - doc.list.forEach(function (ts) { - ts.refText = doc; - }); - return doc; -}; + person.match("#Infinitive [".concat(people, "]")).tag('Person', 'infinitive-person'); //may waits for -module.exports = fromString; + person.match("[".concat(people, "] #PresentTense (to|for)")).tag('Person', 'ambig-active'); //april will -},{"./index":192,"./paths":205,"./tokenize":207}],191:[function(_dereq_,module,exports){ -"use strict"; + person.match("[".concat(people, "] #Modal")).tag('Person', 'ambig-modal'); //would april -module.exports = { - /** did it find anything? */ - found: function found() { - return this.list.length > 0; - }, + person.match("#Modal [".concat(people, "]")).tag('Person', 'modal-ambig'); //with april - /** just a handy wrap*/ - parent: function parent() { - return this.original || this; - }, + person.match("(that|with|for) [".concat(people, "]")).tag('Person', 'that-month'); //it is may - /** how many Texts are there?*/ - length: function length() { - return this.list.length; - }, + person.match("#Copula [".concat(people, "]")).tag('Person', 'is-may'); //may is - /** nicer than constructor.call.name or whatever*/ - isA: function isA() { - return 'Text'; - }, + person.match("[".concat(people, "] #Copula")).tag('Person', 'may-is'); //april the 5th - /** the whitespace before and after this match*/ - whitespace: function whitespace() { - var _this = this; + person.match("[".concat(people, "] the? #Value")).tag('Month', 'person-value'); //wednesday april - return { - before: function before(str) { - _this.list.forEach(function (ts) { - ts.whitespace.before(str); - }); + person.match("#Date [".concat(people, "]")).tag('Month', 'correction-may'); //may 5th - return _this; - }, - after: function after(str) { - _this.list.forEach(function (ts) { - ts.whitespace.after(str); - }); + person.match("[".concat(people, "] the? #Value")).tag('Month', 'may-5th'); //5th of may - return _this; - } - }; - } -}; + person.match("#Value of [".concat(people, "]")).tag('Month', '5th-of-may'); //by april -},{}],192:[function(_dereq_,module,exports){ -'use strict'; //a Text is an array of termLists + person.match("".concat(preps, " [").concat(people, "]")).ifNo('#Holiday').tag('Month', 'preps-month'); //this april -var getters = _dereq_('./getters'); + person.match("(next|this|last) [".concat(people, "]")).tag('Month', 'correction-may'); //maybe not 'this' + } //ambiguous month - verb-forms -function Text(arr, world, original) { - this.list = arr || []; - if (typeof world === 'function') { - world = world(); - } + var verb = doc["if"](verbs$2); - this.world = function () { - return world; - }; + if (verb.found === true) { + //quickly march + verb.match("#Adverb [".concat(verbs$2, "]")).tag('Infinitive', 'ambig-verb'); + verb.match("".concat(verbs$2, " [#Adverb]")).tag('Infinitive', 'ambig-verb'); //all march - this.original = original; //apply getters + verb.match("".concat(preps, " [").concat(verbs$2, "]")).tag('Month', 'in-month'); //this march - var keys = Object.keys(getters); + verb.match("(next|this|last) [".concat(verbs$2, "]")).tag('Month', 'this-month'); //with date - for (var i = 0; i < keys.length; i++) { - Object.defineProperty(this, keys[i], { - get: getters[keys[i]] - }); - } -} + verb.match("[".concat(verbs$2, "] the? #Value")).tag('Month', 'march-5th'); + verb.match("#Value of? [".concat(verbs$2, "]")).tag('Month', '5th-of-march'); //nearby -module.exports = Text; + verb.match("[".concat(verbs$2, "] .? #Date")).tag('Month', 'march-and-feb'); + verb.match("#Date .? [".concat(verbs$2, "]")).tag('Month', 'feb-and-march'); + var march = doc["if"]('march'); -Text.addMethods = function (cl, obj) { - var fns = Object.keys(obj); + if (march.found === true) { + //march to + march.match('[march] (up|down|back|to|toward)').tag('Infinitive', 'march-to'); //must march - for (var i = 0; i < fns.length; i++) { - cl.prototype[fns[i]] = obj[fns[i]]; - } -}; //make a sub-class of this class easily + march.match('#Modal [march]').tag('Infinitive', 'must-march'); + } + } //sun 5th -Text.makeSubset = function (methods, find) { - var Subset = function Subset(arr, world, original) { - Text.call(this, arr, world, original); - }; //inheritance + var sun = doc["if"]('sun'); + if (sun.found === true) { + //sun feb 2 + sun.match('[sun] #Date').tag('WeekDay', 'sun-feb'); //sun the 5th - Subset.prototype = Object.create(Text.prototype); - Text.addMethods(Subset, methods); - Subset.find = find; - return Subset; -}; //apply instance methods + sun.match('sun the #Ordinal').tag('Date').firstTerm().tag('WeekDay', 'sun-the-5th'); //the sun + sun.match('#Determiner [sun]').tag('Singular', 'the-sun'); + } //sat, nov 5th -_dereq_('./methods/misc')(Text); -_dereq_('./methods/loops')(Text); + var sat = doc["if"]('sat'); -_dereq_('./methods/match')(Text); + if (sat.found) { + //sat november + sat.match('[sat] #Date').tag('WeekDay', 'sat-feb'); //this sat -_dereq_('./methods/out')(Text); + sat.match("".concat(preps, " [sat]")).tag('WeekDay', 'sat'); + } //months: -_dereq_('./methods/sort')(Text); -_dereq_('./methods/split')(Text); + var month = doc["if"]('#Month'); -_dereq_('./methods/normalize')(Text); + if (month.found === true) { + //June 5-7th + month.match("#Month #DateRange+").tag('Date', 'correction-numberRange'); //5th of March -_dereq_('./subsets')(Text); //apply subset methods + month.match('#Value of #Month').tag('Date', 'value-of-month'); //5 March + month.match('#Cardinal #Month').tag('Date', 'cardinal-month'); //march 5 to 7 -var subset = { - acronyms: _dereq_('../subset/acronyms'), - adjectives: _dereq_('../subset/adjectives'), - adverbs: _dereq_('../subset/adverbs'), - contractions: _dereq_('../subset/contractions'), - dates: _dereq_('../subset/dates'), - nouns: _dereq_('../subset/nouns'), - people: _dereq_('../subset/people'), - sentences: _dereq_('../subset/sentences'), - terms: _dereq_('../subset/terms'), - possessives: _dereq_('../subset/possessives'), - values: _dereq_('../subset/values'), - verbs: _dereq_('../subset/verbs'), - ngrams: _dereq_('../subset/ngrams'), - startGrams: _dereq_('../subset/ngrams/startGrams'), - endGrams: _dereq_('../subset/ngrams/endGrams') -}; -Object.keys(subset).forEach(function (k) { - Text.prototype[k] = function (num, arg) { - var sub = subset[k]; - var m = sub.find(this, num, arg); - return new subset[k](m.list, this.world, this.parent); - }; -}); //aliases + month.match('#Month #Value to #Value').tag('Date', 'value-to-value'); //march the 12th -Text.prototype.words = Text.prototype.terms; + month.match('#Month the #Value').tag('Date', 'month-the-value'); + } //months: -},{"../subset/acronyms":9,"../subset/adjectives":10,"../subset/adverbs":17,"../subset/contractions":23,"../subset/dates":25,"../subset/ngrams":35,"../subset/ngrams/endGrams":32,"../subset/ngrams/startGrams":36,"../subset/nouns":38,"../subset/people":49,"../subset/possessives":51,"../subset/sentences":52,"../subset/terms":58,"../subset/values":65,"../subset/verbs":75,"./getters":191,"./methods/loops":193,"./methods/match":194,"./methods/misc":195,"./methods/normalize":196,"./methods/out":197,"./methods/sort":202,"./methods/split":204,"./subsets":206}],193:[function(_dereq_,module,exports){ -'use strict'; //this methods are simply loops around each termList object. -var methods = ['toTitleCase', 'toUpperCase', 'toLowerCase', 'toCamelCase', 'hyphenate', 'dehyphenate', 'trim', 'insertBefore', 'insertAfter', 'insertAt', 'replace', 'replaceWith', 'delete', 'lump', 'tagger', // 'tag', -'unTag']; + var val = doc["if"]('#Value'); -var addMethods = function addMethods(Text) { - methods.forEach(function (k) { - Text.prototype[k] = function () { - for (var i = 0; i < this.list.length; i++) { - this.list[i][k].apply(this.list[i], arguments); - } + if (val.found === true) { + //values + val.match('#Value #Abbreviation').tag('Value', 'value-abbr'); //seven point five - return this; - }; - }); //add an extra optimisation for tag method + val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value'); //minus 7 - Text.prototype.tag = function () { - //fail-fast optimisation - if (this.list.length === 0) { - return this; - } + val.match('(minus|negative) #Value').tag('Value', 'minus-value'); // ten grand + + val.match('#Value grand').tag('Value', 'value-grand'); //quarter million - for (var i = 0; i < this.list.length; i++) { - this.list[i].tag.apply(this.list[i], arguments); + val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal'); //june 7 + + val.match('(#WeekDay|#Month) #Value').ifNo('#Money').tag('Date', 'date-value'); //7 june + + val.match('#Value (#WeekDay|#Month)').ifNo('#Money').tag('Date', 'value-date'); //may twenty five + + val.match('#TextValue #TextValue')["if"]('#Date').tag('#Date', 'textvalue-date'); } - return this; + return doc; }; -}; - -module.exports = addMethods; -},{}],194:[function(_dereq_,module,exports){ -'use strict'; + var fixDates_1 = fixDates; -var syntaxParse = _dereq_('../../../terms/match/lib/syntax'); + // verb: 100.828ms + // dates: 80.874ms + // person: 66.054ms + // nouns: 51.340ms + // adj: 19.760ms + // value: 12.950ms + // misc: 43.359ms + //sequence of match-tag statements to correct mis-tags -var Terms = _dereq_('../../../terms'); + var corrections = function corrections(doc) { + // console.time('det') + fixThe_1(doc); //27 + // console.timeEnd('det') + // console.time('nouns') -var splitMethods = function splitMethods(Text) { - //support "#Noun word" regex-matches - var matchReg = function matchReg(r, reg, verbose) { - //parse the 'regex' into some json - var list = []; - reg = syntaxParse(reg); - r.list.forEach(function (ts) { - //an array of arrays - var matches = ts.match(reg, verbose); - matches.list.forEach(function (ms) { - list.push(ms); - }); - }); - var parent = r.parent || r; - return new Text(list, r.world(), parent); - }; //support {word:true} whitelist + fixNouns_1(doc); //30 + // // console.timeEnd('nouns') + // // console.time('person') + fixPerson_1(doc); //58 + // // console.timeEnd('person') + // // console.time('verb') - var matchObj = function matchObj(r, obj) { - var matches = []; - r.list.forEach(function (ts) { - ts.terms.forEach(function (t) { - if (obj.hasOwnProperty(t.normal) === true) { - matches.push(t); - } - }); - }); - matches = matches.map(function (t) { - return new Terms([t], r.world(), r, t.parentTerms); - }); - return new Text(matches, r.world(), r.parent); - }; //support [word, word] whitelist + fixVerb_1(doc); //50 + // // console.timeEnd('verb') + // // console.time('adj') + fixAdjective_1(doc); //8 + // // console.timeEnd('adj') + // // console.time('value') - var matchArr = function matchArr(r, arr) { - //its faster this way - var obj = arr.reduce(function (h, a) { - h[a] = true; - return h; - }, {}); - return matchObj(r, obj); - }; //take a Text object as a match + fixValue_1(doc); //12 + // // console.timeEnd('value') + // // console.time('dates') + fixDates_1(doc); //92 + // // console.timeEnd('dates') + // // console.time('misc') - var matchTextObj = function matchTextObj(r, m) { - var arr = m.out('array'); //i guess this is fine.. + fixMisc(doc); //43 + // console.timeEnd('misc') - return matchArr(r, arr); + return doc; }; - var methods = { - /** do a regex-like search through terms and return a subset */ - match: function match(reg, verbose) { - //fail-fast - if (this.list.length === 0 || reg === undefined || reg === null) { - var parent = this.parent || this; - return new Text([], this.world(), parent); - } //match "#Noun word" regex + var _04Correction = corrections; + /** POS-tag all terms in this document */ - if (typeof reg === 'string' || typeof reg === 'number') { - return matchReg(this, reg, verbose); - } //match [word, word] whitelist + var tagger = function tagger(doc) { + var terms = doc.termList(); // check against any known-words + doc = _01Init(doc); // everything has gotta be something. ¯\_(:/)_/¯ - var type = Object.prototype.toString.call(reg); + doc = _02Fallbacks(doc); // support "didn't" & "spencer's" - if (type === '[object Array]') { - return matchArr(this, reg); - } //match {word:true} whitelist + doc = _03Contractions(doc); //set our cache, to speed things up + doc.cache(); // wiggle-around the results, so they make more sense - if (type === '[object Object]') { - if (reg.isA === 'Text') { - return matchTextObj(this, reg); - } else { - return matchObj(this, reg); - } + doc = _04Correction(doc); //remove our cache + // doc.uncache() + // run any user-given tagger functions + + doc.world.taggers.forEach(function (fn) { + fn(doc); + }); + return doc; + }; + + var _02Tagger = tagger; + + var addMethod = function addMethod(Doc) { + /** */ + var Abbreviations = + /*#__PURE__*/ + function (_Doc) { + _inherits(Abbreviations, _Doc); + + function Abbreviations() { + _classCallCheck(this, Abbreviations); + + return _possibleConstructorReturn(this, _getPrototypeOf(Abbreviations).apply(this, arguments)); } - return this; - }, - not: function not(reg, verbose) { - var list = []; - this.list.forEach(function (ts) { - var found = ts.not(reg, verbose); - list = list.concat(found.list); - }); - var parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - "if": function _if(reg) { - var list = []; + _createClass(Abbreviations, [{ + key: "stripPeriods", + value: function stripPeriods() { + this.termList().forEach(function (t) { + if (t.tags.Abbreviation === true && t.next) { + t.post = t.post.replace(/^\./, ''); + } - for (var i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === true) { - list.push(this.list[i]); + var str = t.text.replace(/\./, ''); + t.set(str); + }); + return this; + } + }, { + key: "addPeriods", + value: function addPeriods() { + this.termList().forEach(function (t) { + t.post = t.post.replace(/^\./, ''); + t.post = '.' + t.post; + }); + return this; } + }]); + + return Abbreviations; + }(Doc); + + Abbreviations.prototype.unwrap = Abbreviations.prototype.stripPeriods; + + Doc.prototype.abbreviations = function (n) { + var match = this.match('#Abbreviation'); + + if (typeof n === 'number') { + match = match.get(n); } - var parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - ifNo: function ifNo(reg) { - var list = []; + return new Abbreviations(match.list, this, this.world); + }; - for (var i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === false) { - list.push(this.list[i]); - } + return Doc; + }; + + var Abbreviations = addMethod; + + var addMethod$1 = function addMethod(Doc) { + /** */ + var Acronyms = + /*#__PURE__*/ + function (_Doc) { + _inherits(Acronyms, _Doc); + + function Acronyms() { + _classCallCheck(this, Acronyms); + + return _possibleConstructorReturn(this, _getPrototypeOf(Acronyms).apply(this, arguments)); } - var parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - has: function has(reg) { - for (var i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === true) { - return true; + _createClass(Acronyms, [{ + key: "stripPeriods", + value: function stripPeriods() { + this.termList().forEach(function (t) { + var str = t.text.replace(/\./g, ''); + t.set(str); + }); + return this; } + }, { + key: "addPeriods", + value: function addPeriods() { + this.termList().forEach(function (t) { + var str = t.text.replace(/\./g, ''); + str = str.split('').join('.'); + t.set(str); + }); + return this; + } + }]); + + return Acronyms; + }(Doc); + + Acronyms.prototype.unwrap = Acronyms.prototype.stripPeriods; + Acronyms.prototype.strip = Acronyms.prototype.stripPeriods; + + Doc.prototype.acronyms = function (n) { + var match = this.match('#Acronym'); + + if (typeof n === 'number') { + match = match.get(n); } - return false; - }, + return new Acronyms(match.list, this, this.world); + }; - /**find a match, and return everything infront of it*/ - before: function before(reg) { - var list = []; + return Doc; + }; - for (var i = 0; i < this.list.length; i++) { - var m = this.list[i].matchOne(reg); + var Acronyms = addMethod$1; + + var addMethod$2 = function addMethod(Doc) { + /** split into approximate sub-sentence phrases */ + Doc.prototype.clauses = function (n) { + // an awkward way to disambiguate a comma use + var commas = this["if"]('@hasComma').notIf('@hasComma @hasComma') //fun, cool... + .notIf('@hasComma . .? (and|or) .') //cool, and fun + .notIf('(#City && @hasComma) #Country') //'toronto, canada' + .notIf('(#Date && @hasComma) #Year') //'july 6, 1992' + .notIf('@hasComma (too|also)$') //at end of sentence + .match('@hasComma'); + var found = this.splitAfter(commas); + var quotes = found.quotations(); + found = found.splitOn(quotes); + var parentheses = found.parentheses(); + found = found.splitOn(parentheses); // it is cool and it is .. + + var conjunctions = found["if"]('#Copula #Adjective #Conjunction (#Pronoun|#Determiner) #Verb').match('#Conjunction'); + found = found.splitBefore(conjunctions); // if it is this then that + + var condition = found["if"]('if .{2,9} then .').match('then'); + found = found.splitBefore(condition); // misc clause partitions + + found = found.splitBefore('as well as .'); + found = found.splitBefore('such as .'); + found = found.splitBefore('in addition to .'); // semicolons, dashes + + found = found.splitAfter('@hasSemicolon'); + found = found.splitAfter('@hasDash'); // does there appear to have relative/subordinate clause still? + + var tooLong = found.filter(function (d) { + return d.wordCount() > 5 && d.match('#Verb+').length >= 2; + }); - if (m) { - var index = m[0].index(); - var found = this.list[i].slice(0, index); + if (tooLong.found) { + var m = tooLong.splitAfter('#Noun .* #Verb .* #Noun+'); + found = found.splitOn(m.eq(0)); + } - if (found.length > 0) { - list.push(found); - } - } + if (typeof n === 'number') { + found = found.get(n); } - var parent = this.parent || this; - return new Text(list, this.world(), parent); - }, + return new Doc(found.list, this, this.world); + }; - /**find a match, and return everything after of it*/ - after: function after(reg) { - var list = []; + return Doc; + }; - for (var i = 0; i < this.list.length; i++) { - var m = this.list[i].matchOne(reg); + var Clauses = addMethod$2; - if (m) { - var lastTerm = m[m.length - 1]; - var index = lastTerm.index(); - var found = this.list[i].slice(index + 1, this.list[i].length); + var addMethod$3 = function addMethod(Doc) { + /** */ + var Contractions = + /*#__PURE__*/ + function (_Doc) { + _inherits(Contractions, _Doc); - if (found.length > 0) { - list.push(found); - } - } + function Contractions(list, from, world) { + var _this; + + _classCallCheck(this, Contractions); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Contractions).call(this, list, from, world)); + _this.contracted = null; + return _this; } + /** turn didn't into 'did not' */ - var parent = this.parent || this; - return new Text(list, this.world(), parent); - } - }; //alias 'and' - methods.and = methods.match; - methods.notIf = methods.ifNo; - methods.only = methods["if"]; - methods.onlyIf = methods["if"]; //hook them into result.proto + _createClass(Contractions, [{ + key: "expand", + value: function expand() { + this.list.forEach(function (p) { + var terms = p.terms(); //change the case? - Text.addMethods(Text, methods); - return Text; -}; + var isTitlecase = terms[0].isTitleCase(); + terms.forEach(function (t, i) { + //use the implicit text + // console.log(t.clean) + t.set(t.implicit || t.text); + t.implicit = undefined; //add whitespace -module.exports = splitMethods; + if (i < terms.length - 1 && t.post === '') { + t.post += ' '; + } + }); //set titlecase -},{"../../../terms":165,"../../../terms/match/lib/syntax":175}],195:[function(_dereq_,module,exports){ -'use strict'; + if (isTitlecase) { + terms[0].toTitleCase(); + } + }); + return this; + } + }]); + + return Contractions; + }(Doc); //find contractable, expanded-contractions + // const findExpanded = r => { + // let remain = r.not('#Contraction') + // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)') + // m.concat(remain.match('(they|we|you|i) have')) + // m.concat(remain.match('i am')) + // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')) + // return m + // } -function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } -var Terms = _dereq_('../../terms'); + Doc.prototype.contractions = function (n) { + //find currently-contracted + var found = this.match('@hasContraction+'); //(may want to split these up) + //todo: split consecutive contractions -var miscMethods = function miscMethods(Text) { - var methods = { - all: function all() { - return this.parent; - }, - index: function index() { - return this.list.map(function (ts) { - return ts.index(); - }); - }, - wordCount: function wordCount() { - return this.terms().length; - }, - data: function data() { - return this.list.map(function (ts) { - return ts.data(); - }); - }, + if (typeof n === 'number') { + found = found.get(n); + } - /* javascript array loop-wrappers */ - map: function map(fn) { - var _this = this; + return new Contractions(found.list, this, this.world); + }; //aliases - return this.list.map(function (ts, i) { - var text = new Text([ts], _this.world); - return fn(text, i); - }); - }, - forEach: function forEach(fn) { - var _this2 = this; - this.list.forEach(function (ts, i) { - var text = new Text([ts], _this2.world); - fn(text, i); - }); - return this; - }, - filter: function filter(fn) { - var _this3 = this; + Doc.prototype.expanded = Doc.prototype.isExpanded; + Doc.prototype.contracted = Doc.prototype.isContracted; + return Doc; + }; - var list = this.list.filter(function (ts, i) { - var text = new Text([ts], _this3.world); - return fn(text, i); - }); - return new Text(list, this.world); - }, - reduce: function reduce(fn, h) { - var _this4 = this; + var Contractions = addMethod$3; - return this.list.reduce(function (_h, ts) { - var text = new Text([ts], _this4.world); - return fn(_h, text); - }, h); - }, - find: function find(fn) { - for (var i = 0; i < this.list.length; i++) { - var ts = this.list[i]; - var text = new Text([ts], this.world); + var addMethod$4 = function addMethod(Doc) { + //pull it apart.. + var parse = function parse(doc) { + var things = doc.splitAfter('@hasComma').not('(and|or) not?'); + var beforeLast = doc.match('[.] (and|or)'); + return { + things: things, + conjunction: doc.match('(and|or) not?'), + beforeLast: beforeLast, + hasOxford: beforeLast.has('@hasComma') + }; + }; + /** cool, fun, and nice */ - if (fn(text)) { - return text; - } + + var Lists = + /*#__PURE__*/ + function (_Doc) { + _inherits(Lists, _Doc); + + function Lists() { + _classCallCheck(this, Lists); + + return _possibleConstructorReturn(this, _getPrototypeOf(Lists).apply(this, arguments)); } - return undefined; - }, + _createClass(Lists, [{ + key: "conjunctions", - /**copy data properly so later transformations will have no effect*/ - clone: function clone() { - var list = this.list.map(function (ts) { - return ts.clone(); - }); - return new Text(list, this.world); //this.lexicon, this.parent - }, + /** coordinating conjunction */ + value: function conjunctions() { + return this.match('(and|or)'); + } + /** split-up by list object */ - /** get the nth term of each result*/ - term: function term(n) { - var _this5 = this; + }, { + key: "parts", + value: function parts() { + return this.splitAfter('(@hasComma|#Conjunction)'); + } + /** remove the conjunction */ - var list = this.list.map(function (ts) { - var arr = []; - var el = ts.terms[n]; + }, { + key: "items", + value: function items() { + return this.parts().notIf('#Conjunction'); + } + /** add a new unit to the list */ + + }, { + key: "add", + value: function add(str) { + this.forEach(function (p) { + var beforeLast = parse(p).beforeLast; + beforeLast.append(str); //add a comma to it + + beforeLast.termList(0).addPunctuation(','); + }); + return this; + } + /** remove any matching unit from the list */ - if (el) { - arr = [el]; + }, { + key: "remove", + value: function remove() { + return this; + } + /** return only lists that use a serial comma */ + + }, { + key: "hasOxfordComma", + value: function hasOxfordComma() { + return this.filter(function (doc) { + return parse(doc).hasOxford; + }); + } + }, { + key: "addOxfordComma", + value: function addOxfordComma() { + return this; } + }, { + key: "removeOxfordComma", + value: function removeOxfordComma() { + return this; + } + }]); - return new Terms(arr, _this5.world, _this5.refText, _this5.refTerms); - }); - return new Text(list, this.world, this.parent); - }, - firstTerm: function firstTerm() { - return this.match('^.'); - }, - lastTerm: function lastTerm() { - return this.match('.$'); - }, - - /** grab a subset of the results*/ - slice: function slice(start, end) { - this.list = this.list.slice(start, end); - return this; - }, + return Lists; + }(Doc); // aliases - /** use only the nth result*/ - get: function get(n) { - //return an empty result - if (!n && n !== 0 || !this.list[n]) { - return new Text([], this.world, this.parent); - } - var ts = this.list[n]; - return new Text([ts], this.world, this.parent); - }, + Lists.prototype.things = Lists.prototype.items; - /**use only the first result */ - first: function first(n) { - if (!n && n !== 0) { - return this.get(0); - } + Doc.prototype.lists = function (n) { + var m = this["if"]('@hasComma+ .? (and|or) not? .'); // person-list - return new Text(this.list.slice(0, n), this.world, this.parent); - }, + var nounList = m.match('(#Noun|#Adjective)+ #Conjunction not? #Adjective? #Noun+'); + var adjList = m.match('(#Adjective|#Adverb)+ #Conjunction not? #Adverb? #Adjective+'); + var verbList = m.match('(#Verb|#Adverb)+ #Conjunction not? #Adverb? #Verb+'); + var result = nounList.concat(adjList); + result = result.concat(verbList); + result = result["if"]('@hasComma'); - /**use only the last result */ - last: function last(n) { - if (!n && n !== 0) { - return this.get(this.list.length - 1); + if (typeof n === 'number') { + result = m.get(n); } - var end = this.list.length; - var start = end - n; - return new Text(this.list.slice(start, end), this.world, this.parent); - }, - concat: function concat() { - //any number of params - for (var i = 0; i < arguments.length; i++) { - var p = arguments[i]; + return new Lists(result.list, this, this.world); + }; - if (_typeof(p) === 'object') { - //Text() - if (p.isA === 'Text' && p.list) { - this.list = this.list.concat(p.list); - } //Terms() + return Doc; + }; + var Lists = addMethod$4; - if (p.isA === 'Terms') { - this.list.push(p); - } - } - } + var noPlural = '(#Pronoun|#Place|#Value|#Person|#Uncountable|#Month|#WeekDay|#Holiday|#Possessive)'; //certain words can't be plural, like 'peace' - return this; - }, + var hasPlural = function hasPlural(doc) { + if (doc.has('#Plural') === true) { + return true; + } // these can't be plural - /** make it into one sentence/termlist */ - flatten: function flatten() { - var terms = []; - this.list.forEach(function (ts) { - terms = terms.concat(ts.terms); - }); //dont create an empty ts - if (!terms.length) { - return new Text(null, this.world, this.parent); - } + if (doc.has(noPlural) === true) { + return false; + } - var ts = new Terms(terms, this.world, this, null); - return new Text([ts], this.world, this.parent); - }, + return true; + }; - /** see if these terms can become this tag*/ - canBe: function canBe(tag) { - this.list.forEach(function (ts) { - ts.terms = ts.terms.filter(function (t) { - return t.canBe(tag); - }); - }); - return this; - }, + var hasPlural_1 = hasPlural; - /** sample part of the array */ - random: function random(n) { - n = n || 1; - var r = Math.floor(Math.random() * this.list.length); - var arr = this.list.slice(r, r + n); //if we're off the end, add some from the start + var irregulars$5 = { + hour: 'an', + heir: 'an', + heirloom: 'an', + honest: 'an', + honour: 'an', + honor: 'an', + uber: 'an' //german u - if (arr.length < n) { - var diff = n - arr.length; + }; //pronounced letters of acronyms that get a 'an' - if (diff > r) { - diff = r; //prevent it from going full-around - } + var an_acronyms = { + a: true, + e: true, + f: true, + h: true, + i: true, + l: true, + m: true, + n: true, + o: true, + r: true, + s: true, + x: true + }; //'a' regexes - arr = arr.concat(this.list.slice(0, diff)); - } + var a_regexs = [/^onc?e/i, //'wu' sound of 'o' + /^u[bcfhjkqrstn][aeiou]/i, // 'yu' sound for hard 'u' + /^eul/i]; - return new Text(arr, this.world, this.parent); - }, - setPunctuation: function setPunctuation(punct) { - this.list.forEach(function (ts) { - return ts.setPunctuation(punct); - }); - return this; - }, - getPunctuation: function getPunctuation(num) { - //support num param - if (num || num === 0) { - if (!this.list[num]) { - return ''; - } + var makeArticle = function makeArticle(doc) { + //no 'the john smith', but 'a london hotel' + if (doc.has('#Person') || doc.has('#Place')) { + return ''; + } //no a/an if it's plural - return this.list[num].getPunctuation(); - } - return this.list.map(function (ts) { - return ts.getPunctuation(); - }); - }, - //jquery-like api aliases - offset: function offset() { - return this.out('offset'); - }, - text: function text() { - return this.out('text'); + if (doc.has('#Plural')) { + return 'the'; } - }; //aliases - methods.eq = methods.get; - methods.join = methods.flatten; - Text.addMethods(Text, methods); -}; + var str = doc.text('normal').trim(); //explicit irregular forms -module.exports = miscMethods; + if (irregulars$5.hasOwnProperty(str)) { + return irregulars$5[str]; + } //spelled-out acronyms -},{"../../terms":165}],196:[function(_dereq_,module,exports){ -'use strict'; -var _unicode = _dereq_('../../term/methods/normalize/unicode'); // + var firstLetter = str.substr(0, 1); + if (doc.has('^@isAcronym') && an_acronyms.hasOwnProperty(firstLetter)) { + return 'an'; + } //'a' regexes -var defaults = { - whitespace: true, - "case": true, - numbers: true, - punctuation: true, - unicode: true, - contractions: true, - acronyms: true, - parentheses: false, - possessives: false, - plurals: false, - verbs: false, - honorifics: false -}; -var methods = { - /** make only one space between each word */ - whitespace: function whitespace(r) { - r.terms().list.forEach(function (ts, i) { - var t = ts.terms[0]; - if (i > 0 && !t.silent_term) { - t.whitespace.before = ' '; - } else if (i === 0) { - t.whitespace.before = ''; + for (var i = 0; i < a_regexs.length; i++) { + if (a_regexs[i].test(str)) { + return 'a'; } + } //basic vowel-startings - t.whitespace.after = ''; //add normalized quotation symbols - if (t.tags.StartQuotation === true) { - t.whitespace.before += '"'; - } + if (/^[aeiou]/i.test(str)) { + return 'an'; + } - if (t.tags.EndQuotation === true) { - t.whitespace.after = '"' + t.whitespace.after; - } - }); - return r; - }, + return 'a'; + }; - /** make first-word titlecase, and people, places titlecase */ - "case": function _case(r) { - r.list.forEach(function (ts) { - ts.terms.forEach(function (t, i) { - if (i === 0 || t.tags.Person || t.tags.Place || t.tags.Organization) {// ts.toTitleCase() //fixme: too weird here. - } else { - ts.toLowerCase(); - } - }); - }); - return r; - }, + var getArticle = makeArticle; - /** turn 'five' to 5, and 'fifth' to 5th*/ - numbers: function numbers(r) { - r.values().toNumber(); - return r; - }, + //similar to plural/singularize rules, but not the same + var isPlural$1 = [/(antenn|formul|nebul|vertebr|vit)ae$/i, /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, /men$/i, /.tia$/i, /(m|l)ice$/i]; //similar to plural/singularize rules, but not the same - /** remove commas, semicolons - but keep sentence-ending punctuation*/ - punctuation: function punctuation(r) { - r.list.forEach(function (ts) { - if (!ts.terms.length) { - return; - } //first-term punctuation + var isSingular$1 = [/(ax|test)is$/i, /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, /(octop|vir)i$/i, /(rl)f$/i, /(alias|status)$/i, /(bu)s$/i, /(al|ad|at|er|et|ed|ad)o$/i, /(ti)um$/i, /(ti)a$/i, /sis$/i, /(?:(^f)fe|(lr)f)$/i, /hive$/i, /(^aeiouy|qu)y$/i, /(x|ch|ss|sh|z)$/i, /(matr|vert|ind|cort)(ix|ex)$/i, /(m|l)ouse$/i, /(m|l)ice$/i, /(antenn|formul|nebul|vertebr|vit)a$/i, /.sis$/i, /^(?!talis|.*hu)(.*)man$/i]; + var _rules$2 = { + isSingular: isSingular$1, + isPlural: isPlural$1 + }; + var endS = /s$/; // double-check this term, if it is not plural, or singular. + // (this is a partial copy of ./tagger/fallbacks/plural) + // fallback plural if it ends in an 's'. - ts.terms[0]._text = ts.terms[0]._text.replace(/^¿/, ''); //middle-terms + var isPlural$2 = function isPlural(str) { + // isSingular suffix rules + if (_rules$2.isSingular.find(function (reg) { + return reg.test(str); + })) { + return false; + } // does it end in an s? - for (var i = 0; i < ts.terms.length - 1; i++) { - var t = ts.terms[i]; //remove non-sentence-ending stuff - t._text = t._text.replace(/[:;,]$/, ''); - } //replace !!! with ! + if (endS.test(str) === true) { + return true; + } // is it a plural like 'fungi'? - var last = ts.terms[ts.terms.length - 1]; - last._text = last._text.replace(/\.+$/, '.'); - last._text = last._text.replace(/!+$/, '!'); - last._text = last._text.replace(/\?+!?$/, '?'); //support '?!' - }); - return r; - }, - // turn Björk into Bjork - unicode: function unicode(r) { - r.list.forEach(function (ts) { - ts.terms.forEach(function (t) { - t.text = _unicode(t.text); - }); - }); - return r; - }, - //expand all contractions - contractions: function contractions(r) { - r.contractions().expand(); - return r; - }, - //remove periods from acronyms, like F.B.I. - acronyms: function acronyms(r) { - r.acronyms().stripPeriods(); - return r; - }, - //turn david's → david - possessives: function possessives(r) { - r.possessives().strip(); - return r; - }, - //strip out parts in (brackets) - parentheses: function parentheses(r) { - r.parentheses()["delete"](); - return r; - }, - //turn sandwhiches → sandwhich - plurals: function plurals(r) { - //todo:this has a non-cooperative bug - r.nouns().toSingular(); - return r; - }, - //turn ate → eat - verbs: function verbs(r) { - r.verbs().toInfinitive(); - return r; - }, - //turn 'Sergeant Pepper to 'Pepper' - honorifics: function honorifics(r) { - r = r["delete"]('#Honorific'); - return r; - } -}; + if (_rules$2.isPlural.find(function (reg) { + return reg.test(str); + })) { + return true; + } -var addMethods = function addMethods(Text) { - Text.prototype.normalize = function (options) { - var doc = this; //set defaults + return null; + }; - options = options || {}; - var obj = Object.assign({}, defaults); - var keys = Object.keys(options); - keys.forEach(function (k) { - obj[k] = options[k]; - }); //do each type of normalization + var isPlural_1$1 = isPlural$2; + + var exceptions = { + he: 'his', + she: 'hers', + they: 'theirs', + we: 'ours', + i: 'mine', + you: 'yours', + her: 'hers', + their: 'theirs', + our: 'ours', + my: 'mine', + your: 'yours' + }; // turn "David" to "David's" + + var toPossessive = function toPossessive(doc) { + var str = doc.text('text').trim(); // exceptions + + if (exceptions.hasOwnProperty(str)) { + doc.replaceWith(exceptions[str], true, true); + doc.tag('Possessive', 'toPossessive'); + return; + } // flanders' - Object.keys(obj).forEach(function (fn) { - if (obj[fn] && methods[fn] !== undefined) { - doc = methods[fn](doc); - } - }); - return doc; - }; -}; -module.exports = addMethods; + if (/s$/.test(str)) { + str += "'"; + doc.replaceWith(str, true, true); + doc.tag('Possessive', 'toPossessive'); + return; + } //normal form: -},{"../../term/methods/normalize/unicode":151}],197:[function(_dereq_,module,exports){ -'use strict'; -var _topk = _dereq_('./topk'); + str += "'s"; + doc.replaceWith(str, true, true); + doc.tag('Possessive', 'toPossessive'); + return; + }; -var offset = _dereq_('./offset'); + var toPossessive_1 = toPossessive; -var termIndex = _dereq_('./indexes'); + // .nouns() supports some noun-phrase-ish groupings + // pull these apart, if necessary + var parse$1 = function parse(doc) { + var res = { + main: doc + }; //support 'mayor of chicago' as one noun-phrase -var fns = _dereq_('../paths').fns; + if (doc.has('#Noun (of|by|for) .')) { + var m = doc.splitAfter('[#Noun+]'); + res.main = m.eq(0); + res.post = m.eq(1); + } -var methods = { - text: function text(r) { - return r.list.reduce(function (str, ts) { - str += ts.out('text'); - return str; - }, ''); - }, - match: function match(r) { - return r.list.reduce(function (str, ts) { - str += ts.out('match'); - return str; - }, ''); - }, - normal: function normal(r) { - return r.list.map(function (ts) { - var str = ts.out('normal'); - var last = ts.last(); + return res; + }; - if (last) { - var punct = ts.getPunctuation(); + var parse_1 = parse$1; - if (punct === '.' || punct === '!' || punct === '?') { - str += punct; - } + var methods$6 = { + /** overload the original json with noun information */ + json: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; } - return str; - }).join(' '); - }, - root: function root(r) { - return r.list.map(function (ts) { - return ts.out('root'); - }).join(' '); - }, + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + json.article = getArticle(doc); + res.push(json); + }); - /** output where in the original output string they are*/ - offsets: function offsets(r) { - return offset(r); - }, + if (n !== null) { + return res[n]; + } - /** output the tokenized location of this match*/ - index: function index(r) { - return termIndex(r); - }, - grid: function grid(r) { - return r.list.reduce(function (str, ts) { - str += ts.out('grid'); - return str; - }, ''); - }, - color: function color(r) { - return r.list.reduce(function (str, ts) { - str += ts.out('color'); - return str; - }, ''); - }, - array: function array(r) { - return r.list.map(function (ts) { - return ts.out('normal'); - }); - }, - csv: function csv(r) { - return r.list.map(function (ts) { - return ts.out('csv'); - }).join('\n'); - }, - newlines: function newlines(r) { - return r.list.map(function (ts) { - return ts.out('newlines'); - }).join('\n'); - }, - json: function json(r) { - return r.list.reduce(function (arr, ts) { - var terms = ts.terms.map(function (t) { - return { - text: t.text, - normal: t.normal, - tags: t.tag - }; - }); - arr.push(terms); - return arr; - }, []); - }, - html: function html(r) { - var html = r.list.reduce(function (str, ts) { - var sentence = ts.terms.reduce(function (sen, t) { - sen += '\n ' + t.out('html'); - return sen; - }, ''); - return str += '\n ' + sentence + '\n '; - }, ''); - return ' ' + html + '\n'; - }, - terms: function terms(r) { - var arr = []; - r.list.forEach(function (ts) { - ts.terms.forEach(function (t) { - arr.push({ - text: t.text, - normal: t.normal, - tags: Object.keys(t.tags) - }); + return res; + }, + isPlural: function isPlural() { + return this["if"]('#Plural'); //assume tagger has run? + }, + hasPlural: function hasPlural() { + return this.filter(function (d) { + return hasPlural_1(d); }); - }); - return arr; - }, - debug: function debug(r) { - console.log('===='); - r.list.forEach(function (ts) { - console.log(' --'); - ts.debug(); - }); - return r; - }, - topk: function topk(r) { - return _topk(r); - }, - custom: function custom(r, obj) { - return r.list.map(function (ts) { - return ts.out(obj); - }); - } -}; -methods.plaintext = methods.text; -methods.normalized = methods.normal; -methods.colors = methods.color; -methods.tags = methods.terms; -methods.offset = methods.offsets; -methods.idexes = methods.index; -methods.frequency = methods.topk; -methods.freq = methods.topk; -methods.arr = methods.array; - -var addMethods = function addMethods(Text) { - Text.prototype.out = function (fn) { - if (typeof fn === 'string') { - if (methods[fn]) { - return methods[fn](this); - } - } else if (fns.isObject(fn) === true) { - //support .out({}) - return methods.custom(this, fn); - } - - return methods.text(this); - }; - - Text.prototype.debug = function () { - return methods.debug(this); - }; - - return Text; -}; - -module.exports = addMethods; - -},{"../paths":201,"./indexes":198,"./offset":199,"./topk":200}],198:[function(_dereq_,module,exports){ -'use strict'; //find where in the original text this match is found, by term-counts - -var termIndex = function termIndex(r) { - var result = []; //find the ones we want - - var want = {}; - r.terms().list.forEach(function (ts) { - want[ts.terms[0].uid] = true; - }); //find their counts - - var sum = 0; - var parent = r.all(); - parent.list.forEach(function (ts, s) { - ts.terms.forEach(function (t, i) { - if (want[t.uid] !== undefined) { - result.push({ - text: t.text, - normal: t.normal, - term: sum, - sentence: s, - sentenceTerm: i - }); - } + }, + toPlural: function toPlural() { + var _this = this; - sum += 1; - }); - }); - return result; -}; + var toPlural = this.world.transforms.toPlural; + this.forEach(function (doc) { + if (doc.has('#Plural') || hasPlural_1(doc) === false) { + return; + } // double-check it isn't an un-tagged plural -module.exports = termIndex; -},{}],199:[function(_dereq_,module,exports){ -'use strict'; -/** say where in the original output string they are found*/ + var main = parse_1(doc).main; + var str = main.text(); -var findOffset = function findOffset(parent, term) { - var sum = 0; + if (!main.has('#Singular') && isPlural_1$1(str) === true) { + return; + } - for (var i = 0; i < parent.list.length; i++) { - for (var o = 0; o < parent.list[i].terms.length; o++) { - var t = parent.list[i].terms[o]; + str = toPlural(str, _this.world); + main.replace(str).tag('#Plural'); + }); + return this; + }, + toSingular: function toSingular() { + var _this2 = this; - if (t.uid === term.uid) { - return sum; - } else { - sum += t.whitespace.before.length + t._text.length + t.whitespace.after.length; - } - } - } + var toSingular = this.world.transforms.toSingular; + this.forEach(function (doc) { + if (doc.has('#Singular') || hasPlural_1(doc) === false) { + return; + } // double-check it isn't an un-tagged plural - return null; -}; //like 'text' for the middle, and 'normal' for the start+ends -//used for highlighting the actual words, without whitespace+punctuation + var main = parse_1(doc).main; + var str = main.text(); + + if (!main.has('#Plural') && isPlural_1$1(str) !== true) { + return; + } -var trimEnds = function trimEnds(ts) { - var terms = ts.terms; + str = toSingular(str, _this2.world); + main.replace(str).tag('#Singular'); + }); + return this; + }, + toPossessive: function toPossessive() { + this.forEach(function (d) { + toPossessive_1(d); + }); + return this; + } + }; + var methods_1 = methods$6; - if (terms.length <= 2) { - return ts.out('normal'); - } //the start + var addMethod$5 = function addMethod(Doc) { + /** */ + var Nouns = + /*#__PURE__*/ + function (_Doc) { + _inherits(Nouns, _Doc); + function Nouns() { + _classCallCheck(this, Nouns); - var str = terms[0].normal; //the middle + return _possibleConstructorReturn(this, _getPrototypeOf(Nouns).apply(this, arguments)); + } - for (var i = 1; i < terms.length - 1; i++) { - var t = terms[i]; - str += t.whitespace.before + t.text + t.whitespace.after; - } //the end + return Nouns; + }(Doc); // add-in our methods - str += ' ' + terms[ts.terms.length - 1].normal; - return str; -}; //map over all-dem-results + Object.assign(Nouns.prototype, methods_1); + Doc.prototype.nouns = function (n) { + var match = this.clauses(); + match = match.match('#Noun+ (of|by)? the? #Noun+?'); //nouns that we don't want in these results, for weird reasons -var allOffset = function allOffset(r) { - var parent = r.all(); - return r.list.map(function (ts) { - var words = []; + match = match.not('#Pronoun'); + match = match.not('(there|these)'); + match = match.not('(#Month|#WeekDay)'); //allow Durations, Holidays + // //allow possessives like "spencer's", but not generic ones like, - for (var i = 0; i < ts.terms.length; i++) { - words.push(ts.terms[i].normal); - } + match = match.not('(my|our|your|their|her|his)'); + match = match.not('(of|for|by|the)$'); - var nrml = trimEnds(ts); - var txt = ts.out('text'); - var startAt = findOffset(parent, ts.terms[0]); - var beforeWord = ts.terms[0].whitespace.before; - var wordStart = startAt + beforeWord.length; - return { - text: txt, - normal: ts.out('normal'), - //where we begin - offset: startAt, - length: txt.length, - wordStart: wordStart, - wordEnd: wordStart + nrml.length // wordLength: words.join(' ').length + if (typeof n === 'number') { + match = match.get(n); + } + return new Nouns(match.list, this, this.world); }; - }); -}; - -module.exports = allOffset; - -},{}],200:[function(_dereq_,module,exports){ -'use strict'; // - -var topk = function topk(r, n) { - //count occurance - var count = {}; - r.list.forEach(function (ts) { - var str = ts.out('root'); - count[str] = count[str] || 0; - count[str] += 1; - }); //turn into an array - - var all = []; - Object.keys(count).forEach(function (k) { - all.push({ - normal: k, - count: count[k] - }); - }); //add percentage - all.forEach(function (o) { - o.percent = parseFloat((o.count / r.list.length * 100).toFixed(2)); - }); //sort by freq + return Doc; + }; - all = all.sort(function (a, b) { - if (a.count > b.count) { - return -1; - } + var Nouns = addMethod$5; - return 1; - }); + var open = /\(/; + var close = /\)/; - if (n) { - all = all.splice(0, n); - } + var addMethod$6 = function addMethod(Doc) { + /** anything between (these things) */ + var Parentheses = + /*#__PURE__*/ + function (_Doc) { + _inherits(Parentheses, _Doc); - return all; -}; + function Parentheses() { + _classCallCheck(this, Parentheses); -module.exports = topk; + return _possibleConstructorReturn(this, _getPrototypeOf(Parentheses).apply(this, arguments)); + } -},{}],201:[function(_dereq_,module,exports){ -"use strict"; + _createClass(Parentheses, [{ + key: "unwrap", -module.exports = _dereq_('../paths'); + /** remove the parentheses characters */ + value: function unwrap() { + this.list.forEach(function (p) { + var first = p.terms(0); + first.pre = first.pre.replace(open, ''); + var last = p.lastTerm(); + last.post = last.post.replace(close, ''); + }); + return this; + } + }]); -},{"../paths":205}],202:[function(_dereq_,module,exports){ -'use strict'; + return Parentheses; + }(Doc); -var sorter = _dereq_('./methods'); + Doc.prototype.parentheses = function (n) { + var list = []; + this.list.forEach(function (p) { + var terms = p.terms(); //look for opening brackets + + for (var i = 0; i < terms.length; i += 1) { + var t = terms[i]; + + if (open.test(t.pre)) { + //look for the closing bracket.. + for (var o = i; o < terms.length; o += 1) { + if (close.test(terms[o].post)) { + var len = o - i + 1; + list.push(p.buildFrom(t.id, len)); + i = o; + break; + } + } + } + } + }); //support nth result -var addMethods = function addMethods(Text) { - var fns = { - /**reorder result.list alphabetically */ - sort: function sort(method) { - //default sort - method = method || 'alphabetical'; - method = method.toLowerCase(); + if (typeof n === 'number') { + if (list[n]) { + list = [list[n]]; + } else { + list = []; + } - if (!method || method === 'alpha' || method === 'alphabetical') { - return sorter.alpha(this, Text); + return new Parentheses(list, this, this.world); } - if (method === 'chron' || method === 'chronological') { - return sorter.chron(this, Text); - } + return new Parentheses(list, this, this.world); + }; - if (method === 'length') { - return sorter.lengthFn(this, Text); - } + return Doc; + }; - if (method === 'freq' || method === 'frequency') { - return sorter.freq(this, Text); - } + var Parentheses = addMethod$6; - if (method === 'wordcount') { - return sorter.wordCount(this, Text); - } + var addMethod$7 = function addMethod(Doc) { + /** */ + var Possessives = + /*#__PURE__*/ + function (_Doc) { + _inherits(Possessives, _Doc); - return this; - }, + function Possessives(list, from, world) { + var _this; - /**reverse the order of result.list */ - reverse: function reverse() { - this.list = this.list.reverse(); - return this; - }, - unique: function unique() { - var obj = {}; - this.list = this.list.filter(function (ts) { - var str = ts.out('root'); + _classCallCheck(this, Possessives); - if (obj.hasOwnProperty(str)) { - return false; - } + _this = _possibleConstructorReturn(this, _getPrototypeOf(Possessives).call(this, list, from, world)); + _this.contracted = null; + return _this; + } + /** turn didn't into 'did not' */ - obj[str] = true; - return true; - }); - return this; - } - }; //hook them into result.proto - Text.addMethods(Text, fns); - return Text; -}; + _createClass(Possessives, [{ + key: "strip", + value: function strip() { + this.list.forEach(function (p) { + var terms = p.terms(); + terms.forEach(function (t) { + var str = t.text.replace(/'s$/, ''); + t.set(str || t.text); + }); + }); + return this; + } + }]); + + return Possessives; + }(Doc); //find contractable, expanded-contractions + // const findExpanded = r => { + // let remain = r.not('#Contraction') + // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)') + // m.concat(remain.match('(they|we|you|i) have')) + // m.concat(remain.match('i am')) + // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')) + // return m + // } -module.exports = addMethods; -},{"./methods":203}],203:[function(_dereq_,module,exports){ -'use strict'; //perform sort on pre-computed values + Doc.prototype.possessives = function (n) { + //find currently-contracted + var found = this.match('#Noun+? #Possessive'); //todo: split consecutive contractions -var sortEm = function sortEm(arr) { - arr = arr.sort(function (a, b) { - if (a.index > b.index) { - return 1; - } + if (typeof n === 'number') { + found = found.get(n); + } - if (a.index === b.index) { - return 0; - } + return new Possessives(found.list, this, this.world); + }; - return -1; - }); //return ts objects + return Doc; + }; - return arr.map(function (o) { - return o.ts; - }); -}; //alphabetical sorting of a termlist array + var Possessives = addMethod$7; + + var pairs = { + "\"": "\"", + // 'StraightDoubleQuotes' + "\uFF02": "\uFF02", + // 'StraightDoubleQuotesWide' + "'": "'", + // 'StraightSingleQuotes' + "\u201C": "\u201D", + // 'CommaDoubleQuotes' + "\u2018": "\u2019", + // 'CommaSingleQuotes' + "\u201F": "\u201D", + // 'CurlyDoubleQuotesReversed' + "\u201B": "\u2019", + // 'CurlySingleQuotesReversed' + "\u201E": "\u201D", + // 'LowCurlyDoubleQuotes' + "\u2E42": "\u201D", + // 'LowCurlyDoubleQuotesReversed' + "\u201A": "\u2019", + // 'LowCurlySingleQuotes' + "\xAB": "\xBB", + // 'AngleDoubleQuotes' + "\u2039": "\u203A", + // 'AngleSingleQuotes' + // Prime 'non quotation' + "\u2035": "\u2032", + // 'PrimeSingleQuotes' + "\u2036": "\u2033", + // 'PrimeDoubleQuotes' + "\u2037": "\u2034", + // 'PrimeTripleQuotes' + // Prime 'quotation' variation + "\u301D": "\u301E", + // 'PrimeDoubleQuotes' + "`": "\xB4", + // 'PrimeSingleQuotes' + "\u301F": "\u301E" // 'LowPrimeDoubleQuotesReversed' + }; + var hasOpen = RegExp('(' + Object.keys(pairs).join('|') + ')'); -exports.alpha = function (r) { - r.list.sort(function (a, b) { - //#1 performance speedup - if (a === b) { - return 0; - } //#2 performance speedup + var addMethod$8 = function addMethod(Doc) { + /** "these things" */ + var Quotations = + /*#__PURE__*/ + function (_Doc) { + _inherits(Quotations, _Doc); + function Quotations() { + _classCallCheck(this, Quotations); - if (a.terms[0] && b.terms[0]) { - if (a.terms[0].root > b.terms[0].root) { - return 1; + return _possibleConstructorReturn(this, _getPrototypeOf(Quotations).apply(this, arguments)); } - if (a.terms[0].root < b.terms[0].root) { - return -1; - } - } //regular compare + _createClass(Quotations, [{ + key: "unwrap", + /** remove the quote characters */ + value: function unwrap() { + return this; + } + }]); - if (a.out('root') > b.out('root')) { - return 1; - } + return Quotations; + }(Doc); - return -1; - }); - return r; -}; //the order they were recieved (chronological~) + Doc.prototype.quotations = function (n) { + var list = []; + this.list.forEach(function (p) { + var terms = p.terms(); //look for opening quotes + + for (var i = 0; i < terms.length; i += 1) { + var t = terms[i]; + + if (hasOpen.test(t.pre)) { + var _char = (t.pre.match(hasOpen) || [])[0]; + var want = pairs[_char]; // if (!want) { + // console.warn('missing quote char ' + char) + // } + //look for the closing bracket.. + + for (var o = i; o < terms.length; o += 1) { + if (terms[o].post.indexOf(want) !== -1) { + var len = o - i + 1; + list.push(p.buildFrom(t.id, len)); + i = o; + break; + } + } + } + } + }); //support nth result + if (typeof n === 'number') { + if (list[n]) { + list = [list[n]]; + } else { + list = []; + } -exports.chron = function (r) { - //pre-compute indexes - var tmp = r.list.map(function (ts) { - return { - ts: ts, - index: ts.termIndex() - }; - }); - r.list = sortEm(tmp); - return r; -}; //shortest matches first + return new Quotations(list, this, this.world); + } + return new Quotations(list, this, this.world); + }; // alias -exports.lengthFn = function (r) { - //pre-compute indexes - var tmp = r.list.map(function (ts) { - return { - ts: ts, - index: ts.chars() - }; - }); - r.list = sortEm(tmp).reverse(); - return r; -}; //count the number of terms in each match + Doc.prototype.quotes = Doc.prototype.quotations; + return Doc; + }; -exports.wordCount = function (r) { - //pre-compute indexes - var tmp = r.list.map(function (ts) { - return { - ts: ts, - index: ts.length - }; - }); - r.list = sortEm(tmp); - return r; -}; //sort by frequency (like topk) - - -exports.freq = function (r) { - //get counts - var count = {}; - r.list.forEach(function (ts) { - var str = ts.out('root'); - count[str] = count[str] || 0; - count[str] += 1; - }); //pre-compute indexes - - var tmp = r.list.map(function (ts) { - var num = count[ts.out('root')] || 0; - return { - ts: ts, - index: num * -1 //quick-reverse it + var Quotations = addMethod$8; - }; - }); - r.list = sortEm(tmp); - return r; -}; + // walked => walk - turn a verb into it's root form + var toInfinitive$1 = function toInfinitive(parsed, world) { + var verb = parsed.verb; //1. if it's already infinitive -},{}],204:[function(_dereq_,module,exports){ -'use strict'; + var str = verb.text('normal'); -var splitMethods = function splitMethods(Text) { - var methods = { - /** turn result into two seperate results */ - splitAfter: function splitAfter(reg, verbose) { - var list = []; - this.list.forEach(function (ts) { - ts.splitAfter(reg, verbose).forEach(function (mts) { - list.push(mts); - }); - }); - this.list = list; - return this; - }, + if (verb.has('#Infinitive')) { + return str; + } // 2. world transform does the heavy-lifting - /** turn result into two seperate results */ - splitBefore: function splitBefore(reg, verbose) { - var list = []; - this.list.forEach(function (ts) { - ts.splitBefore(reg, verbose).forEach(function (mts) { - list.push(mts); - }); - }); - this.list = list; - return this; - }, - /** turn result into two seperate results */ - splitOn: function splitOn(reg, verbose) { - var list = []; - this.list.forEach(function (ts) { - ts.splitOn(reg, verbose).forEach(function (mts) { - list.push(mts); - }); - }); - this.list = list; - return this; + var tense = null; + + if (verb.has('#PastTense')) { + tense = 'PastTense'; + } else if (verb.has('#Gerund')) { + tense = 'Gerund'; + } else if (verb.has('#PresentTense')) { + tense = 'PresentTense'; + } else if (verb.has('#Participle')) { + tense = 'Participle'; + } else if (verb.has('#Actor')) { + tense = 'Actor'; } - }; //hook them into result.proto - Text.addMethods(Text, methods); - return Text; -}; + return world.transforms.toInfinitive(str, world, tense); + }; -module.exports = splitMethods; + var toInfinitive_1$1 = toInfinitive$1; -},{}],205:[function(_dereq_,module,exports){ -arguments[4][201][0].apply(exports,arguments) -},{"../paths":8,"dup":201}],206:[function(_dereq_,module,exports){ -'use strict'; + // spencer walks -> singular + // we walk -> plural + // the most-recent noun-phrase, before this verb. + var findNoun = function findNoun(vb) { + var noun = vb.lookBehind('#Noun+').last(); + return noun; + }; //sometimes you can tell if a verb is plural/singular, just by the verb + // i am / we were + // othertimes you need its subject 'we walk' vs 'i walk' -var isQuestion = _dereq_('../subset/sentences/isQuestion'); -var addSubsets = function addSubsets(Text) { - //these subsets have no instance methods, so are simply a 'find' method. - var subsets = { - clauses: function clauses(n) { - var r = this.splitAfter('#ClauseEnd'); + var isPlural$3 = function isPlural(parsed) { + var vb = parsed.verb; - if (typeof n === 'number') { - r = r.get(n); - } + if (vb.has('(are|were|does)') || parsed.auxiliary.has('(are|were|does)')) { + return true; + } - return r; - }, - hashTags: function hashTags(n) { - var r = this.match('#HashTag').terms(); + if (vb.has('(is|am|do|was)') || parsed.auxiliary.has('(is|am|do|was)')) { + return false; + } //consider its prior noun - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - organizations: function organizations(n) { - var r = this.splitAfter('#Comma'); - r = r.match('#Organization+'); + var noun = findNoun(vb); - if (typeof n === 'number') { - r = r.get(n); - } + if (noun.has('(we|they|you)')) { + return true; + } - return r; - }, - phoneNumbers: function phoneNumbers(n) { - var r = this.splitAfter('#Comma'); - r = r.match('#PhoneNumber+'); + if (noun.has('#Plural')) { + return true; + } - if (typeof n === 'number') { - r = r.get(n); - } + if (noun.has('#Singular')) { + return false; + } - return r; - }, - places: function places(n) { - var r = this.splitAfter('#Comma'); - r = r.match('#Place+'); + return null; + }; - if (typeof n === 'number') { - r = r.get(n); - } + var isPlural_1$2 = isPlural$3; - return r; - }, - quotations: function quotations(n) { - var matches = this.match('#Quotation+'); - var found = []; - matches.list.forEach(function (ts) { - var open = 0; - var start = null; //handle nested quotes - 'startQuote->startQuote->endQuote->endQuote' + // #Copula : is -> 'is not' + // #PastTense : walked -> did not walk + // #PresentTense : walks -> does not walk + // #Gerund : walking: -> not walking + // #Infinitive : walk -> do not walk - ts.terms.forEach(function (t, i) { - if (t.tags.StartQuotation === true) { - if (open === 0) { - start = i; - } + var toNegative = function toNegative(parsed, world) { + var vb = parsed.verb; // if it's already negative... - open += 1; - } + if (parsed.negative.found) { + return; + } // would walk -> would not walk - if (open > 0 && t.tags.EndQuotation === true) { - open -= 1; - } - if (open === 0 && start !== null) { - found.push(ts.slice(start, i + 1)); - start = null; - } - }); //maybe we messed something up.. + if (parsed.auxiliary.found) { + parsed.auxiliary.eq(0).append('not'); + return; + } // is walking -> is not walking - if (start !== null) { - found.push(ts.slice(start, ts.terms.length)); - } - }); - matches.list = found; - if (typeof n === 'number') { - matches = matches.get(n); - } + if (vb.has('(#Copula|will|has|had|do)')) { + vb.append('not'); + return; + } // walked -> did not walk - return matches; - }, - topics: function topics(n) { - var r = this.clauses(); // Find people, places, and organizations - var yup = r.people(); - yup.concat(r.places()); - yup.concat(r.organizations()); - var ignore = ['someone', 'man', 'woman', 'mother', 'brother', 'sister', 'father']; - yup = yup.not(ignore); //return them to normal ordering + if (vb.has('#PastTense')) { + var inf = toInfinitive_1$1(parsed, world); + vb.replaceWith(inf, true, true); + vb.prepend('did not'); + return; + } // walks -> does not walk - yup.sort('chronological'); // yup.unique() //? not sure - if (typeof n === 'number') { - yup = yup.get(n); - } + if (vb.has('#PresentTense')) { + var _inf = toInfinitive_1$1(parsed, world); - return yup; - }, - urls: function urls(n) { - var r = this.match('#Url'); + vb.replaceWith(_inf, true, true); - if (typeof n === 'number') { - r = r.get(n); + if (isPlural_1$2(parsed)) { + vb.prepend('do not'); + } else { + vb.prepend('does not'); } - return r; - }, - questions: function questions(n) { - var r = this.all(); + return; + } //walking -> not walking - if (typeof n === 'number') { - r = r.get(n); - } - var list = r.list.filter(function (ts) { - return isQuestion(ts); - }); - return new Text(list, this.world, this.parent); - }, - statements: function statements(n) { - var r = this.all(); + if (vb.has('#Gerund')) { + var _inf2 = toInfinitive_1$1(parsed, world); - if (typeof n === 'number') { - r = r.get(n); - } + vb.replaceWith(_inf2, true, true); + vb.prepend('not'); + return; + } //fallback 1: walk -> does not walk - var list = r.list.filter(function (ts) { - return isQuestion(ts) === false; - }); - return new Text(list, this.world, this.parent); - }, - parentheses: function parentheses(n) { - var r = this.match('#Parentheses+'); //split-up consecutive ones - r = r.splitAfter('#EndBracket'); + if (isPlural_1$2(parsed)) { + vb.prepend('does not'); + return; + } //fallback 2: walk -> do not walk - if (typeof n === 'number') { - r = r.get(n); - } - return r; - } + vb.prepend('do not'); + return; }; - Object.keys(subsets).forEach(function (k) { - Text.prototype[k] = subsets[k]; - }); - return Text; -}; -module.exports = addSubsets; + var toNegative_1 = toNegative; -},{"../subset/sentences/isQuestion":53}],207:[function(_dereq_,module,exports){ -//(Rule-based sentence boundary segmentation) - chop given text into its proper sentences. -// Ignore periods/questions/exclamations used in acronyms/abbreviations/numbers, etc. -// @spencermountain 2017 MIT -'use strict'; + // turn 'would not really walk up' into parts + var parseVerb = function parseVerb(vb) { + var parsed = { + adverb: vb.match('#Adverb+'), + // 'really' + negative: vb.match('#Negative'), + // 'not' + auxiliary: vb.match('#Auxiliary').not('(#Negative|#Adverb)'), + // 'will' of 'will go' + particle: vb.match('#Particle'), + // 'up' of 'pull up' + verb: vb.match('#Verb').not('(#Adverb|#Negative|#Auxiliary|#Particle)') + }; // fallback, if no verb found -var abbreviations = Object.keys(_dereq_('../world/more-data/abbreviations')); // \u203D - Interrobang -// \u2E18 - Inverted Interrobang -// \u203C - Double Exclamation Mark -// \u2047 - Double Question Mark -// \u2048 - Question Exclamation Mark -// \u2049 - Exclamation Question Mark -// \u2026 - Ellipses Character -//regs- + if (!parsed.verb.found) { + // blank-everything + Object.keys(parsed).forEach(function (k) { + parsed[k] = parsed[k].not('.'); + }); // it's all the verb -var abbrev_reg = new RegExp('\\b(' + abbreviations.join('|') + ")[.!?\u203D\u2E18\u203C\u2047-\u2049] *$", 'i'); -var acronym_reg = /[ .][A-Z]\.? *$/i; -var ellipses_reg = /(?:\u2026|\.{2,}) *$/; // Match different formats of new lines. (Mac: \r, Linux: \n, Windows: \r\n) + parsed.verb = vb; + return parsed; + } // -var new_line = /((?:\r?\n|\r)+)/; -var naiive_sentence_split = /(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g; -var letter_regex = /[a-z0-9\u0000-\u007F]/i; //support an all-unicode sentence, i guess -var not_ws_regex = /\S/; // Start with a regex: + if (parsed.adverb && parsed.adverb.found) { + var match = parsed.adverb.text('reduced') + '$'; -var naiive_split = function naiive_split(text) { - var all = []; //first, split by newline + if (vb.has(match)) { + parsed.adverbAfter = true; + } + } // console.log(parsed.adverb.json({ index: true })[0]) - var lines = text.split(new_line); - for (var i = 0; i < lines.length; i++) { - //split by period, question-mark, and exclamation-mark - var arr = lines[i].split(naiive_sentence_split); + return parsed; + }; - for (var o = 0; o < arr.length; o++) { - all.push(arr[o]); - } - } + var parse$2 = parseVerb; - return all; -}; + /** too many special cases for is/was/will be*/ -var sentence_parser = function sentence_parser(text) { - text = text || ''; - text = String(text); - var sentences = []; // First do a greedy-split.. + var toBe = function toBe(parsed) { + var isI = false; + var plural = isPlural_1$2(parsed); + var isNegative = parsed.negative.found; //account for 'i is' -> 'i am' irregular + // if (vb.parent && vb.parent.has('i #Adverb? #Copula')) { + // isI = true; + // } + // 'i look', not 'i looks' - var chunks = []; // Ensure it 'smells like' a sentence + if (parsed.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) { + isI = true; + } - if (!text || typeof text !== 'string' || not_ws_regex.test(text) === false) { - return sentences; - } // Start somewhere: + var obj = { + PastTense: 'was', + PresentTense: 'is', + FutureTense: 'will be', + Infinitive: 'is', + Gerund: 'being', + Actor: '', + PerfectTense: 'been', + Pluperfect: 'been' + }; //"i is" -> "i am" + if (isI === true) { + obj.PresentTense = 'am'; + obj.Infinitive = 'am'; + } - var splits = naiive_split(text); // Filter-out the grap ones + if (plural) { + obj.PastTense = 'were'; + obj.PresentTense = 'are'; + obj.Infinitive = 'are'; + } - for (var i = 0; i < splits.length; i++) { - var s = splits[i]; + if (isNegative) { + obj.PastTense += ' not'; + obj.PresentTense += ' not'; + obj.FutureTense = 'will not be'; + obj.Infinitive += ' not'; + obj.PerfectTense = 'not ' + obj.PerfectTense; + obj.Pluperfect = 'not ' + obj.Pluperfect; + obj.Gerund = 'not ' + obj.Gerund; + } - if (s === undefined || s === '') { - continue; - } //this is meaningful whitespace + return obj; + }; + var toBe_1 = toBe; - if (not_ws_regex.test(s) === false) { - //add it to the last one - if (chunks[chunks.length - 1]) { - chunks[chunks.length - 1] += s; - continue; - } else if (splits[i + 1]) { - //add it to the next one - splits[i + 1] = s + splits[i + 1]; - continue; - } - } //else, only whitespace, no terms, no sentence + var conjugate$2 = function conjugate(parsed, world) { + var verb = parsed.verb; //special handling of 'is', 'will be', etc. + if (verb.has('#Copula') || verb.out('normal') === 'be' && parsed.auxiliary.has('will')) { + return toBe_1(parsed); + } - chunks.push(s); - } //detection of non-sentence chunks: - //loop through these chunks, and join the non-sentence chunks back together.. + var infinitive = toInfinitive_1$1(parsed, world); + if (!infinitive) { + return {}; + } // console.log(infinitive) - for (var _i = 0; _i < chunks.length; _i++) { - var c = chunks[_i]; //should this chunk be combined with the next one? - if (chunks[_i + 1] && letter_regex.test(c) && (abbrev_reg.test(c) || acronym_reg.test(c) || ellipses_reg.test(c))) { - chunks[_i + 1] = c + (chunks[_i + 1] || ''); - } else if (c && c.length > 0 && letter_regex.test(c)) { - //this chunk is a proper sentence.. - sentences.push(c); - chunks[_i] = ''; - } - } //if we never got a sentence, return the given text + var forms = world.transforms.conjugate(infinitive, world); + forms.Infinitive = infinitive; // add particle to phrasal verbs ('fall over') + if (parsed.particle.found) { + var particle = parsed.particle.text(); + Object.keys(forms).forEach(function (k) { + return forms[k] += ' ' + particle; + }); + } //put the adverb at the end? - if (sentences.length === 0) { - return [text]; - } - return sentences; -}; + if (parsed.adverb.found) { + var adverb = parsed.adverb.text(); -module.exports = sentence_parser; // console.log(sentence_parser('john f. kennedy')); + if (parsed.adverbAfter === true) { + Object.keys(forms).forEach(function (k) { + return forms[k] += ' ' + adverb; + }); + } else { + Object.keys(forms).forEach(function (k) { + return forms[k] = adverb + ' ' + forms[k]; + }); + } + } //apply negative -},{"../world/more-data/abbreviations":216}],208:[function(_dereq_,module,exports){ -"use strict"; -module.exports = "{\"words\":\"Comparative\xA6better|Superlative\xA6earlier|PresentTense\xA6sounds|Value\xA6a few|Noun\xA6autumn,daylight9eom,here,no doubt,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Copula\xA6a1is,w0;as,ere;m,re|Condition\xA6if,unless|PastTense\xA6be2came,d1had,mea0sa1taken,we0;nt;id;en,gan|Gerund\xA6accord0be0develop0go0result0stain0;ing|Negative\xA6n0;ever,o0;!n,t|QuestionWord\xA6how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s|Singular\xA6a06bZcUdQeOfLgKhGici0Ajel07kitty,lFmDnCoBp8question mark,r7s4t1us 0;dollVstW; rex,a1h0ic,ragedy,v show;ere,i07;l03x return;ky,t0uper bowl,yst06;ri04u0;dIff;alZi02oom;a1robl02u0;dCrpo8;rt,tE;cean,thers;othiXumbG;ayfTeeNo0;del,nopoS;iRunch;ead start,o0;lPme1u0;se;! run;adfMirlIlaci8od,rand slam,ulM;amiLly,olLr1un0;diN;iGosD;conomy,gg,ner3v0xampG;ent;eath,inn2o0ragonfG;cument6g0iFlFor;gy;er;an3eiliFhocol2i0ottage,redit card;ty,vil w0;ar;ate;ary;ankiAel7les9o2reakfast,u0;n0tterf6;ti8;dy,tt2y0;fri0;end;le;d1l0noma0;ly; homin2verti0;si0;ng;em|Infinitive\xA60:6Y;1:7C;2:7A;3:79;4:5F;5:74;6:6D;7:6L;8:78;9:6W;A:73;B:76;C:6R;D:68;E:7D;F:60;a6Qb69c5Bd4Je43f3Qg3Jh3Ci2Zj2Xk2Tl2Km2Bn28o24p1Pques3Rr0Xs05tWuRvOwHyG;awn,ield;aJe24hist7iIoGre6H;nd0rG;k,ry;n,pe,sh,th0;lk,nHrGsh,tCve;n,raE;d0t;aHiGo8;ew,sA;l6Rry;nHpGr3se;gra4Wli49;dGi8lo65;erGo;go,mi5H;aNeMhKie,oJrHuGwi5;ne,rn;aGe0Ui60u5y;de,in,nsf0p,v5O;r37uC;ank,rG;eat2Vi2;nd,st;ke,lk,rg5Os8;a06c03eZhWi4Jkip,lVmUneTo56pQtJuGwitC;bmAck,ff0gge5ppHrGspe6;ge,pri1rou53vi2;ly,o3D;aLeKoJrHuG;dy,mb7;aDeGi2;ngth2Lss,tC;p,re;m,p;in,ke,r0Yy;iHlaFoil,rinG;g,k7;n,t;ak,e3E;aFe22i7o5B;am,e1Qip;aHiv0oG;ck,ut;re,ve;arCeIle6nHr2tG;!t7;d,se;k,m;aHo4rG;atCew;le,re;il,ve;a05eIisk,oHuG;b,in,le,n,sh;am,ll;a01cZdu9fYgXje6lUmTnt,pQquPsKtJvGwa5V;eGiew,o4U;al,l,rG;se,t;aDi4u42;eJi5oItG;!o4rG;i6uc20;l2rt;mb7nt,r2;e5i4;air,eHlGo40reseE;a9y;at;aDemb0i3Wo2;aHeGi2y;a1nt;te,x;a5Dr4A;act1Yer,le6u1;a12ei2k5PoGyc7;gni2Cnci7rd;ch,li2Bs5N;i1nG;ge,k;aTerSiRlPoNrIuG;b21ll,mp,rGsh,t;cha1s4Q;ai1eJiEoG;cHdu9greBhibAmi1te5vG;e,i2U;eBlaim;di6pa4ss,veE;iEp,rtr43sGur;e,t;a3RuG;g,n3;ck,le;fo32mAsi5;ck,iErt4Mss,u1y;bIccur,ff0pera8utweHverGwe;co47lap,ta3Qu1whelm;igh;ser2taD;eHotG;e,i9;ed,gle6;aLeKiIoHuG;ltip3Frd0;nit14ve;nGrr13;d,g7us;asu4lt,n0Qr3ssa3;intaDke d40na3rHtG;ch,t0;ch,k39ry;aMeLiIoGu1F;aGck,ok,ve;d,n;ft,ke,mAnHstGve;!en;e,k;a2Gc0Ht;b0Qck,uG;gh,nC;eIiHnoG;ck,w;ck,ll,ss;ep;am,oDuG;d3mp;gno4mQnGss3I;cOdica8flu0NhNsKtIvG;eGol2;nt,st;erGrodu9;a6fe4;i5tG;aGru6;ll;abAibA;lu1Fr1D;agi22pG;lemeEo20ro2;aKeIi4oHuG;nt,rry;ld fa5n03pe,st;aGlp;d,t;nd7ppGrm,te;en;aLet,loBoKrIuG;arGeBi14;ant39d;aGip,ow,umb7;b,sp;es,ve1I;in,th0ze;aQeaPiNlLoIracHuncG;ti3I;tu4;cus,lHrG;ce,eca5m,s30;d,l22;aFoG;at,od,w;gu4lGniFx;e,l;r,tu4;il,ll,vG;or;a13cho,dAle6mSnPstNvalua8xG;a0AcLerKi5pGte16;a15eHlaDoGreB;rt,se;ct,riG;en9;ci1t;el,han3;abGima8;liF;ab7couXdHfor9ga3han9j03riCsu4t0vG;isi2Vy;!u4;body,er3pG;hasiGow0;ze;a06eUiMoLrHuG;mp;aIeHiGop;ft;am,ss;g,in;!d3ubt;e,ff0p,re6sHvG;e,iXor9;aJcGli13miBpl18tinguiF;oGuB;uGv0;ra3;gr1YppG;ear,ro2;al,cNem,fLliv0ma0Cny,pKsHterG;mi0D;cribe,er2iHtrG;oy;gn,re;a08e07i6osA;eGi08y;at,ct;iIlHrG;ea1;a4i04;de;ma3n9re,te;a0Ae09h06i8l03oJrGut;aHeGoBuFy;a8dA;ck,ve;llYmSnHok,py,uGv0;gh,nt;cePdu6fMsKtIvG;eGin9;rt,y;aDin0XrG;a5ibu8ol;iGtitu8;d0st;iHoGroE;rm;gu4rm;rn;biKe,foJmaIpG;a4laD;re;nd;rt;ne;ap1e6;aHiGo1;ng,p;im,w;aHeG;at,ck,w;llen3n3r3se;a1nt0;ll,ncHrGt0u1;e,ry;el;aUeQloPoNrKuG;dgIlHrG;n,y;ly;et;aHuF;sh;ke;a5mb,o5rrGth0un9;ow;ck;ar,coSgDlHnefAtrG;ay;ie2ong;in;nGse;!g;band0Jc0Bd06ffo05gr04id,l01mu1nYppTrQsKttGvoid,waA;acIeHra6;ct;m0Fnd;h,k;k,sG;eIiHocia8uG;me;gn,st;mb7rt;le;chHgGri2;ue;!i2;eaJlIroG;aCve;ch;aud,y;l,r;noun9sw0tG;icipa8;ce;lHt0;er;e3ow;ee;rd;aRdIju5mAoR;it;st;!reB;ss;cJhie2knowled3tiva8;te;ge;ve;eIouEu1;se;nt;pt;on|Actor\xA6aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt|Honorific\xA6aObrigadiNcHdGexcellency,fiBking,liDmaAofficNp6queen,r3s0taoiseach,vice5;e0ultJ;c0rgeaC;ond liAretary;abbi,e0;ar0verend; adJ;astFr0;eside6i0ofessE;me ministEnce0;!ss;gistrate,r4yB;eld mar3rst l0;ady,i0;eutena0;nt;shA;oct5utchess;aptain,hance3o0;lonel,mmand4ngress0unci2;m0wom0;an;ll0;or;er;d0yatullah;mir0;al|SportsTeam\xA60:1M;1:1T;2:1U;a1Rb1Dc0Zd0Qfc dallas,g0Nhouston 0Mindiana0Ljacksonville jagua0k0Il0Fm02newVoRpKqueens parkJrIsAt5utah jazz,vancouver whitecaps,w3yY;ashington 3est ham0Xh16;natio21redski1wizar12;ampa bay 6e5o3;ronto 3ttenham hotspur;blu1Hrapto0;nnessee tita1xasD;buccanee0ra1G;a7eattle 5heffield0Qporting kansas13t3;. louis 3oke12;c1Srams;mari02s3;eah1IounI;cramento Sn 3;antonio spu0diego 3francisco gi0Bjose earthquak2;char0EpaB;eal salt lake,o04; ran0C;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat2steele0;il3oenix su1;adelphia 3li2;eagl2philNunE;dr2;akland 4klahoma city thunder,r3;i10lando magic;athle0Trai3;de0; 3castle05;england 6orleans 5york 3;city fc,giUje0Lkn02me0Lred bul19y3;anke2;pelica1sain0J;patrio0Irevolut3;ion;aBe9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Rvi3;kings;imberwolv2wi1;re0Cuc0W;dolphi1heat,marli1;mphis grizz3ts;li2;nchester 5r3vN;i3li1;ne0;c00u0H;a4eicesterYos angeles 3;clippe0dodFlaA; galaxy,ke0;ansas city 3nH;chiefs,ro3;ya0M; pace0polis colX;astr0Edynamo,rockeWtexa1;i4olden state warrio0reen bay pac3;ke0;anT;.c.Aallas 7e3i0Cod5;nver 5troit 3;lio1pisto1ti3;ge0;bronc06nuggeO;cowboUmav3;er3;ic06; uX;arCelNh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki2;brow1cavalie0india1;benga03re3;ds;arlotte horCicago 3;b4cubs,fire,wh3;iteE;ea0ulY;di3olina panthe0;ff3naW; c3;ity;altimore ElAoston 7r3uffalo bilT;av2e5ooklyn 3;ne3;ts;we0;cel4red3; sox;tics;ackburn rove0u3;e ja3;ys;rs;ori3rave1;ol2;rizona Ast8tlanta 3;brav2falco1h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls|Uncountable\xA60:1C;a1Hb1Bc12e0Wf0Qg0Mh0Gi0Dj0Cknowled1Gl07mYnXoWpRrOsCt8vi7w1;a5ea0Ai4o1;o2rld1;! seI;d,l;ldlife,ne;rmth,t0;neg0Xol08;e3hund0ime,oothpaste,r1una;affRou1;ble,sers,t;a,nnis;aAcene07e9h8il7now,o6p3te2u1;g0Rnshi0L;am,el;ace2e1;ciOed;!c12;ap,cc0ft0B;k,v0;eep,opp0O;riJ;d07fe0Wl1nd;m0Qt;ain,e1i0W;c1laxa0Csearch;ogni0Brea0B;a4e2hys0Elast9o1ress00;rk,w0;a1pp0trol;ce,nR;p0tiK;il,xygen;ews,oi0C;a7ea5i4o3u1;mps,s1;ic;nHo08;lk,st;sl1t;es;chine1il,themat00; learn02ry;aught0e3i2u1;ck,g07;ghtnZqu0CteratI;a1isH;th0;ewel7usti08;ce,mp1nformaOtself;ati1ortan06;en05;a4isto3o1;ck1mework,n1spitali01;ey;ry;ir,lib1ppi9;ut;o2r1um,ymnastJ;a7ound;l1ssip;d,f;i5lour,o2ruit,urnit1;ure;od,rgive1wl;ne1;ss;c6sh;conom9duca5lectriciMn3quip4th9very1;body,o1thB;ne;joy1tertain1;ment;tiC;a8elcius,h4iv3loth6o1urrency;al,ffee,ld w1nfusiAttA;ar;ics;aos,e1;e2w1;ing;se;ke,sh;a3eef,is2lood,read,utt0;er;on;g1ss;ga1;ge;c4dvi3irc2mnes1rt;ty;raft;ce;id|Unit\xA60:17;a12b10c0Md0Le0Jf0Fg0Bh08in07joule0k01lZmOnNoMpIqHsqCt7volts,w6y4z3\xB02\xB51;g,s;c,f,n;b,e2;a0Lb,d0Rears old,o1;tt0F;att0b;able4b3e2on1sp;!ne0;a2r0B;!l,sp;spo03; ft,uare 1;c0Gd0Ff3i0Dkilo0Hm1ya0C;e0Kil1;e0li0F;eet0o0B;t,uart0;a3e2i1ou0Nt;c0Knt0;rcent,t00;!scals;hms,uVz;an0GewtR;/s,b,e7g,i3l,m2p1\xB2,\xB3;h,s;!\xB2;!/h,cro3l1;e1li05;! DsC\xB2;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,\xB2;byYgWmeter1;! 2s1;! 1;per hour;\xB2,\xB3;e1g,z;ct1rtz0;aWogP;al2b,ig9ra1;in0m0;!l1;on0;a3emtOl1tG; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,l,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!\xB2,\xB3;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s|Pronoun\xA6'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s|Organization\xA60:44;a39b2Qc2Ad22e1Yf1Ug1Mh1Hi1Ej1Ak18l14m0Tn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0You1w0Y;gov,tu2R;a3e1orld trade organizati3Z;lls fargo,st1;fie23inghou17;l1rner br3B;-m12gree30l street journ25m12;an halNeriz3Uisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Qps;es33i1;lev2Wted natio2T; mobi2Jaco bePd bMeAgi frida9h3im horto2Smz,o1witt2V;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen31daily ma2Vguess w2holli0rolling st1Ns1w2;mashing pumpki2Nuprem0;ho;ea1lack eyed pe3Dyrds;ch bo1tl0;ys;l2s1;co,la m13;efoni08us;a6e4ieme2Fnp,o2pice gir5ta1ubaru;rbucks,to2L;ny,undgard1;en;a2Px pisto1;ls;few24insbu25msu1W;.e.m.,adiohead,b6e3oyal 1yan2V;b1dutch she4;ank;/max,aders dige1Ed 1vl30;bu1c1Thot chili peppe2Ilobst27;ll;c,s;ant2Tizno2D;an5bs,e3fiz23hilip morrBi2r1;emier25octer & gamb1Qudenti14;nk floyd,zza hut;psi26tro1uge09;br2Ochina,n2O; 2ason1Wda2E;ld navy,pec,range juli2xf1;am;us;aAb9e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0L;l,s;c,stl3tflix,w1; 1sweek;kids on the block,york09;e,\xE9;a,c;nd1Rs2t1;ional aca2Co,we0P;a,cYd0N;aAcdonald9e5i3lb,o1tv,yspace;b1Knsanto,ody blu0t1;ley crue,or0N;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt11z1V;'ore08a3e1g,ittle caesa1H;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1H;art;iffy lu0Jo3pmorgan1sa;! cha1;se;hnson & johns1Py d1O;bm,hop,n1tv;g,te1;l,rpol; & m,asbro,ewlett-packaSi3o1sbc,yundai;me dep1n1G;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Gu1;cci,ns n ros0;ldman sachs,o1;dye1g09;ar;axo smith kliYencore;electr0Gm1;oto0S;a3bi,da,edex,i1leetwood mac,oFrito-l08;at,nancial1restoU; tim0;cebook,nnie mae;b04sa,u3xxon1; m1m1;ob0E;!rosceptics;aiml08e5isney,o3u1;nkin donuts,po0Tran dur1;an;j,w j1;on0;a,f leppa2ll,peche mode,r spiegXstiny's chi1;ld;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra03;al;ca c5l4m1o08st03;ca2p1;aq;st;dplLgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Fy;dbury,pital o1rl's jr;ne;aFbc,eBf9l5mw,ni,o1p,rexiteeV;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roW;ckbuster video,omingda1;le; g1g1;oodriM;cht3e ge0n & jer2rkshire hathaw1;ay;ryG;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bWcRdidQerosmith,ig,lKmEnheuser-busDol,pple9r6s3t&t,v2y1;er;is,on;hland1sociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c|Demonym\xA60:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an|Region\xA60:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma|Possessive\xA6anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne|Currency\xA6$,aud,bRcPdKeurJfIgbp,hkd,inr,jpy,kGlEp8r7s3usd,x2y1z0\xA2,\xA3,\xA5,\u0434\u0435\u043D,\u043B\u0432,\u0440\u0443\u0431,\u0E3F,\u20A1,\u20A8,\u20AC,\u20AD,\uFDFC;lotyR\u0142;en,uanQ;af,of;h0t5;e0il5;k0q0;elL;iel,oubleKp,upeeK;e2ound st0;er0;lingH;n0soG;ceFn0;ies,y;e0i7;i,mpi6;n,r0wanzaByatB;!onaAw;ori7ranc9t;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s|Country\xA60:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an|City\xA6a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dell\xEDn,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0\u0307zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg|FemaleName\xA60:G0;1:G4;2:FT;3:FF;4:FE;5:ER;6:FU;7:ET;8:GH;9:F1;A:GD;B:E7;C:EI;D:FQ;E:GA;F:FN;G:C8;aE4bD6cB9dAJe9Hf92g8Ih85i7Uj6Wk61l4Pm3An2Vo2Sp2Hqu2Fr1Ps0Rt05ursu7vVwPyMzH;aKeIoH;e,la,ra;lHna;da,ma;da,ra;as7GeIol1UvH;et5onBA;le0sen3;an9endBPhiB5iH;lJnH;if3BniHo0;e,f3A;a,helmi0lHma;a,ow;aNeKiH;cIviH;an9YenG4;kD1tor3;da,l8Wnus,rH;a,nHoniD4;a,iDE;leHnesEF;nDOrH;i1y;aTeQhOiNoKrHu7y4;acG6iHu0F;c3na,sH;h9Nta;nIrH;a,i;i9Kya;a5KffaCIna,s6;al3eHomasi0;a,l8Ho6Zres1;g7Vo6YrIssH;!a,ie;eCi,ri8;bOliNmLnJrIs6tHwa0;ia0um;a,yn;iHya;a,ka,s6;a4e4iHmCCra;!ka;a,t6;at6it6;a06carlet2Ze05hViTkye,oRtNuIyH;bFMlvi1;e,sIzH;an2Uet5ie,y;anHi8;!a,e,nH;aFe;aJeH;fHl3EphH;an2;cFBr73;f3nHphi1;d4ia,ja,ya;er4lv3mon1nHobh76;dy;aLeHirlBNo0y7;ba,e0i7lJrH;iHrBRyl;!d71;ia,lBX;ki4nJrIu0w0yH;la,na;i,leAon,ron;a,da,ia,nHon;a,on;l60re0;bNdMi9lLmJndIrHs6vannaF;aFi0;ra,y;aHi4;nt6ra;lBPome;e,ie;in1ri0;a03eYhWiUoIuH;by,thBM;bRcQlPnOsIwe0xH;an95ie,y;aIeHie,lE;ann8ll1marBHtB;!lHnn1;iHyn;e,nH;a,d7X;da,i,na;an9;hel55io;bin,erByn;a,cHkki,na,ta;helC2ki;ea,iannE0oH;da,n13;an0bJgi0i0nHta,y0;aHee;!e,ta;a,eH;cATkaF;chHe,i0mo0n5FquCGvDy0;aCFelHi9;!e,le;een2iH;a0nn;aNeMhKoJrH;iHudenAX;scil1Uyamva9;lly,rt3;ilome0oebe,ylH;is,lis;arl,ggy,nelope,r7t4;ige,m0Fn4Po7rvaBDtIulH;a,et5in1;ricHsy,tA9;a,e,ia;ctav3deIf86lHph86;a,ga,iv3;l3t5;aReQiKoHy7;eIrH;aFeDma;ll1mi;aLcJkHla,na,s6ta;iHki;!ta;hoB4k8ColH;a,eBJ;!mh;l7Una,risC;dJi5PnIo23taH;li1s6;cy,et5;eAiCQ;a01ckenz2eViLoIrignayani,uriBIyrH;a,na,tAV;i4ll9ZnH;a,iH;ca,ka,qB7;a,chPkaOlKmi,nJrHtzi;aHiam;!n9;a,dy,erva,h,n2;a,dJi9LlH;iHy;cent,e;red;!e7;ae7el3I;ag4LgLi,lIrH;edi62isCyl;an2iHliC;nHsAP;a,da;!an,han;b09c9Gd07e,g05i04l02n00rLtKuIv6TxGyHz2;a,bell,ra;de,rH;a,eD;h77il9t2;a,cTgPiKjor2l6Jn2s6tJyH;!aHbe5RjaAlou;m,n9V;a,ha,i0;!aJbAOeIja,lEna,sHt54;!a,ol,sa;!l07;!h,m,nH;!a,e,n1;arJeIie,oHr3Lueri5;!t;!ry;et3JiB;elHi62y;a,l1;dHon,ue7;akranBy;iHlo97;a,ka,n9;a,re,s2;daHg2;!l2Y;alEd2elHge,isBJon0;eiAin1yn;el,le;a0Je09iXoRuLyH;d3la,nH;!a,dIe9VnHsAT;!a,e9U;a,sAR;aB4cKelJiClIna,pHz;e,iB;a,u;a,la;iHy;a2Ce,l27n9;is,l1IrItt2uH;el7is1;aJeIi8na,rH;aGi8;lei,n1tB;!in1;aRbQd3lMnJsIv3zH;!a,be4Let5z2;a,et5;a,dH;a,sHy;ay,ey,i,y;a,iaJlH;iHy;a8Je;!n4G;b7Verty;!n5T;aOda,e0iMla,nLoJslAUtHx2;iHt2;c3t3;la,nHra;a,ie,o4;a,or1;a,gh,laH;!ni;!h,nH;a,d4e,n4O;cOdon7Ui7kes6na,rNtLurJvIxHy7;mi;ern1in3;a,eHie,yn;l,n;as6is6oH;nya,ya;a,isC;ey,ie,y;a01eWhadija,iOoNrJyH;lHra;a,ee,ie;isHy5D;!tH;a,en,iHy;!e,n48;ri,urtn9C;aNerMl9BmJrHzzy;a,stH;en,in;!berlH;eHi,y;e,y;a,stD;!na,ra;el6QiKlJnIrH;a,i,ri;d4na;ey,i,l9Ss2y;ra,s6;c8Yi5YlPma7nyakumari,rNss5MtKviByH;!e,lH;a,eH;e,i7A;a5FeIhHi3PlEri0y;arGerGie,leDr9Hy;!lyn75;a,en,iHl4Vyn;!ma,n31sC;ei74i,l2;a05eWilUoNuH;anLdKliHstG;aIeHsC;!nAt0W;!n8Z;e,i2Ry;a,iB;!anMcelEd5Wel73han6JlKni,sIva0yH;a,ce;eHie;fi0lEphG;eHie;en,n1;!a,e,n36;!i10lH;!i0Z;anMle0nJrIsH;i5Rsi5R;i,ri;!a,el6Rif1RnH;a,et5iHy;!e,f1P;a,e74iInH;a,e73iH;e,n1;cMd1mi,nIqueliAsmin2Uvie4yAzH;min8;a8eIiH;ce,e,n1s;!lHsCt06;e,le;inIk2lEquelH;in1yn;da,ta;da,lQmOnNo0rMsIvaH;!na;aIiHob6W;do4;!belHdo4;!a,e,l2G;en1i0ma;a,di4es,gr5T;el9ogH;en1;a,eAia0o0se;aNeKilIoHyacin1N;ll2rten1H;a5HdHla5H;a,egard;ath0XiIlHnrietBrmiAst0X;en25ga;di;il78lLnKrHtt2yl78z6G;iHmo4Hri4I;etH;!te;aFnaF;ey,l2;aZeUiPlNold13rJwH;enHyne19;!dolE;acIetHisel9;a,chD;e,ieH;!la;adys,enHor3yn1Z;a,da,na;aKgi,lIna,ov74selH;a,e,le;da,liH;an;!n0;mZnJorgIrH;aldGi,m2Utru76;et5i5W;a,eHna;s1Ovieve;briel3Hil,le,rnet,yle;aSePio0loNrH;anIe9iH;da,e9;!cH;esIiHoi0H;n1s3X;!ca;!rH;a,en45;lIrnH;!an9;ec3ic3;rItiHy8;ma;ah,rah;d0GileDkBl01mVn4DrSsNtMuLvH;aJelIiH;e,ta;in0Byn;!ngelG;geni1la,ni3T;h55ta;meral9peranKtH;eIhHrel7;er;l2Rr;za;iHma,nestGyn;cHka,n;a,ka;eKilJmH;aHie,y;!liA;ee,i1y;lHrald;da,y;aUeSiNlMma,no4oKsJvH;a,iH;na,ra;a,ie;iHuiH;se;a,en,ie,y;a0c3da,nKsHzaI;aHe;!beH;th;!a,or;anor,nH;!a;in1na;en,iHna,wi0;e,th;aXeLiKoHul2W;lor54miniq41n32rHtt2;a,eDis,la,othHthy;ea,y;an0AnaFonAx2;anQbPde,eOiMja,lJmetr3nHsir4X;a,iH;ce,se;a,iIla,orHphiA;es,is;a,l5M;dHrdH;re;!d4Pna;!b2EoraFra;a,d4nH;!a,e;hl3i0mNnLphn1rIvi1YyH;le,na;a,by,cIia,lH;a,en1;ey,ie;a,et5iH;!ca,el1Cka;arHia;is;a0Se0Oh06i04lWoKrIynH;di,th3;istHy06;al,i0;lQnNrIurH;tn1F;aKdJiHnJriA;!nH;a,e,n1;el3;!l1T;n2sH;tanHuelo;ce,za;eHleD;en,t5;aJeoIotH;il4D;!pat4;ir8rJudH;et5iH;a,ne;a,e,iH;ce,sY;a4er4ndH;i,y;aQeNloe,rH;isIyH;stal;sy,tH;aIen,iHy;!an1e,n1;!l;lseIrH;!i8yl;a,y;nMrH;isKlImH;aiA;a,eHot5;n1t5;!sa;d4el1RtH;al,el1Q;cIlH;es5i3H;el3ilH;e,ia,y;iZlYmilXndWrOsMtHy7;aKeJhHri0;erGleDrEy;in1;ri0;li0ri0;a2IsH;a2Hie;a,iNlLmeJolIrH;ie,ol;!e,in1yn;lHn;!a,la;a,eHie,y;ne,y;na,sC;a0Ei0E;a,e,l1;isBl2;tlH;in,yn;arb0DeZianYlWoUrH;andSeQiJoIyH;an0nn;nwEok8;an2PdgLg0KtH;n29tH;!aInH;ey,i,y;ny;etH;!t8;an0e,nH;da,na;i8y;bbi8nH;iBn2;ancHossom,ythe;a,he;ca;aScky,lin9niBrOssNtJulaFvH;!erlH;ey,y;hIsy,tH;e,i11y8;!anH;ie,y;!ie;nHt6yl;adIiH;ce;et5iA;!triH;ce,z;a4ie,ra;aliy2Bb26d1Ng1Ji1Bl0Um0Pn03rYsPthe0uLvJyH;anHes6;a,na;a,eHr27;ry;drJgusIrH;el3o4;ti0;a,ey,i,y;hItrH;id;aLlHt1Q;eIi8yH;!n;e,iHy;gh;!nH;ti;iJleIpiB;ta;en,n1t5;an1AelH;le;aZdXeVgRiPja,nItoHya;inet5n3;!aKeIiHmJ;e,ka;!mHt5;ar2;!belIliCmU;sa;!le;ka,sHta;a,sa;elHie;a,iH;a,ca,n1qH;ue;!t5;te;je7rea;la;!bImHstas3;ar3;el;aJberIel3iHy;e,na;!ly;l3n9;da;aUba,eOiLlJma,ta,yH;a,c3sH;a,on,sa;iHys0K;e,s0J;a,cIna,sHza;a,ha,on,sa;e,ia;c3is6jaJna,ssaJxH;aHia;!nd4;nd4;ra;ia;i0nIyH;ah,na;a,is,naF;c6da,leDmMnslLsH;haFlH;inHyX;g,n;!h;ey;ee;en;at6g2nH;es;ie;ha;aWdiTelMrH;eJiH;anMenH;a,e,ne;an0;na;aLeKiIyH;nn;a,n1;a,e;!ne;!iH;de;e,lEsH;on;yn;!lH;iAyn;ne;agaKbIiH;!gaJ;ey,i8y;!e;il;ah|Place\xA6aMbKcIdHeFfEgBhAi9jfk,kul,l7m5new eng4ord,p2s1the 0upJyyz;bronx,hamptons;fo,oho,under2yd;acifMek,h0;l,x;land;a0co,idDuc;libu,nhattK;a0gw,hr;s,x;ax,cn,ndianGst;arlem,kg,nd;ay village,re0;at 0enwich;britain,lak2;co,ra;urope,verglad0;es;en,fw,own1xb;dg,gk,hina0lt;town;cn,e0kk,rooklyn;l air,verly hills;frica,m5ntar1r1sia,tl0;!ant1;ct0;ic0; oce0;an;ericas,s|Person\xA6a01bZcTdQeOfMgJhHinez,jFkEleDmAnettPo9p7r4s3t2uncle,v0womL;a0irgin maH;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussaQcarlett johanssRistZlobodan milosevic,omeone,tepGuC;ay romano,eese witherspoQo1ush limbau0;gh;d stewart,naldinho,sario;a0ipV;lmUris hiltM;prah winfrOra;an,essiaen,itt romnNo0ubarek;m0thR;!my;bron james,e;anye west,iefer sutherland,obe bryaN;aime,effersFk rowli0;ng;alle ber0ulk hog3;ry;astBentlem1irl,rand0uy;fa2mo2;an;a0ella;thF;ff0meril lagasse,zekiel;ie;a0enzel washingt4ick wolf,ude;d0lt3nte;!dy;ar2lint1ous0ruz;in;on;dinal wols1son0;! palm5;ey;arack obama,oy,ro0;!ck,th2;dolf hitl1shton kutch1u0;nt;er|WeekDay\xA6fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s|Date\xA6autumn,daylight9eom,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Time\xA6a6breakfast 5dinner5e3lunch5m2n0oclock,some5to7;i7o0;on,w;id4or1;od,ve0;ning;time;fternoon,go,ll day,t 0;ni0;ght|Holiday\xA60:1Q;1:1P;a1Fb1Bc12d0Ye0Of0Kg0Hh0Di09june07kwanzaa,l04m00nYoVpRrPsFt9v6w4xm03y2;om 2ule;hasho16kippur;hit2int0Xomens equalit8; 0Ss0T;alentines3e2ictor1E;r1Bteran1;! 0;-0ax 0h6isha bav,rinityMu2; b3rke2;y 0;ish2she2;vat;a0Xe prophets birth0;a6eptember14h4imchat tor0Ut 3u2;kk4mmer T;a8p7s6valentines day ;avu2mini atzeret;ot;int 2mhain;a4p3s2valentine1;tephen1;atrick1;ndrew1;amadan,ememberanc0Yos2;a park1h hashana;a3entecost,reside0Zur2;im,ple heart 0;lm2ssovE; s04;rthodox 2stara;christma1easter2goOhoJn0C;! m07;ational 2ew years09;freedom 0nurse1;a2emorial 0lHoOuharram;bMr2undy thurs0;ch0Hdi gr2tin luther k0B;as;a2itRughnassadh;bour 0g baom2ilat al-qadr;er; 2teenth;soliU;d aJmbolc,n2sra and miraj;augurGd2;ependen2igenous people1;c0Bt1;a3o2;ly satur0;lloween,nukkUrvey mil2;k 0;o3r2;ito de dolores,oundhoW;odW;a4east of 2;our lady of guadalupe,the immaculate concepti2;on;ther1;aster8id 3lectYmancip2piphany;atX;al-3u2;l-f3;ad3f2;itr;ha;! 2;m8s2;un0;ay of the dead,ecemb3i2;a de muertos,eciseis de septiembre,wali;er sol2;stice;anad8h4inco de mayo,o3yber m2;on0;lumbu1mmonwealth 0rpus christi;anuk4inese n3ristmas2;! N;ew year;ah;a 0ian tha2;nksgiving;astillCeltaine,lack4ox2;in2;g 0; fri0;dvent,ll 9pril fools,rmistic8s6u2;stral4tum2;nal2; equinox;ia 0;cens2h wednes0sumption of mary;ion 0;e 0;hallows 6s2;ai2oul1t1;nt1;s 0;day;eve|Month\xA6aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il|Duration\xA6centur4d2hour3m0seconds,week3year3;i0onth2;llisecond1nute1;ay0ecade0;!s;ies,y|FirstName\xA6aEblair,cCdevBj8k6lashawn,m3nelly,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0;ls7nyatta,rry;am0ess1;ie,m0;ie;an,on;as0heyenne;ey,sidy;lexis,ndra,ubr0;ey|LastName\xA60:35;1:3A;2:3C;3:2Z;4:2F;a3Bb31c2Od2Ee2Bf25g1Zh1Oi1Jj1Dk16l0Ym0Mn0Io0Fp04rXsLtGvEwBxAy7zh5;a5ou,u;ng,o;a5eun2Uoshi1Jun;ma5ng;da,guc1Zmo27sh21zaQ;iao,u;a6eb0il5o3right,u;li3Bs1;gn0lk0ng,tanabe;a5ivaldi;ssilj37zqu2;a8h7i2Go6r5sui,urn0;an,ynisI;lst0Orr1Uth;at1Uomps1;kah0Unaka,ylor;aDchCeBhimizu,iAmi9o8t6u5zabo;ar2lliv2AzuD;a5ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n6sa5to;ki;ch2dKtos,z;amAeag1Zi8o6u5;bio,iz,sC;b5dri1MgHj0Sme24osevelt,sZux;erts,ins1;c5ve0E;ci,hards1;ir2os;aDe9h7ic5ow20;as5hl0;so;a5illips;m,n1T;ders20et7r6t5;e0Nr4;ez,ry;ers;h21rk0t5vl4;el,te0J;baAg0Alivei00r5;t5w1O;ega,iz;a5eils1guy1Rix1owak,ym1E;gy,ka5var1K;ji5muV;ma;aDeBiAo7u5;ll0n5rr0Bssolini,\xF15;oz;lina,oJr5zart;al0Me5r0U;au,no;hhail4ll0;rci0s5y0;si;eVmmad4r5tsu07;in5tin2;!o;aBe7i5op2uo;!n5u;coln,dholm;fe6n0Qr5w0J;oy;bv5v5;re;mmy,rs14u;aAennedy,imu9le0Lo7u6wo5;k,n;mar,znets4;bay5vacs;asY;ra;hn,rl8to,ur,zl4;a9en8ha3imen2o5u3;h5nYu3;an5ns1;ss1;ki0Es0S;cks1nsse0D;glesi8ke7noue,shik6to,vano5;u,v;awa;da;as;aBe8it7o6u5;!a3b0ghNynh;a3ffmann,rvat;chcock,l0;mingw6nde5rM;rs1;ay;ns0ErrPs6y5;asCes;an4hi5;moI;a8il,o7r6u5;o,tierr2;ayli3ub0;m2nzal2;nd5o,rcia;hi;er9is8lor7o6uj5;ita;st0urni0;es;ch0;nand2;d6insteGsposi5vaK;to;is1wards;aBeAi8omin7u5;bo5rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw6vi5;es,s;in;aEhAlark9o5;hKl5op0rbyn,x;em6li5;ns;an;!e;an7e6iu,o5ristensFu3we;i,ng,u3w,y;!n,on5u3;!g;mpb6rt0st5;ro;ell;aAe7ha3lanco,oyko,r5yrne;ooks,yant;ng;ck6ethov5nnett;en;er,ham;ch,h7iley,rn5;es,i0;er;k,ng;dCl8nd5;ers5r9;en,on,s1;on;eks6iy7var2;ez;ej5;ev;ams|MaleName\xA60:CE;1:BK;2:C2;3:BS;4:B4;5:BZ;6:AT;7:9V;8:BC;9:AW;A:AO;B:8W;aB5bA9c98d88e7Hf6Zg6Hh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt07u06v01wOxavi3yHzC;aCor0;cCh8Jne;hDkC;!a5Z;ar51e5Y;ass2i,oDuC;sEu25;nFsEusC;oCsD;uf;ef;at0g;aKeIiDoCyaAQ;lfgang,odrow;lCn1O;bEey,frBJlC;aA6iC;am,e,s;e8Aur;i,nde7sC;!l6t1;de,lDrr5yC;l1ne;lCt3;a94y;aFern1iC;cDha0nceCrg9Cva0;!nt;ente,t5B;lentin49n8Zughn;lyss4Msm0;aTeOhLiJoFrDyC;!l3ro8s1;av9ReCist0oy,um0;nt9Jv55y;bEd7YmCny;!as,mCoharu;aAYie,y;iBy;mCt9;!my,othy;adDeoCia7EomB;!do7O;!de9;dFrC;en8JrC;an8IeCy;ll,n8H;!dy;dgh,ic9Unn3req,ts46;aScotQeOhKiIoGpenc3tCur1Pylve8Jzym1;anEeCua7D;f0phAGvCwa7C;e59ie;!islaw,l6;lom1nA4uC;leyma8ta;dClBm1;!n6;aEeC;lCrm0;d1t1;h6Une,qu0Vun,wn,y8;aCbasti0k1Yl42rg41th,ymo9J;m9n;!tC;!ie,y;lDmCnti22q4Kul;!mAu4;ik,vato6X;aXeThe94iPoGuDyC;an,ou;b6NdDf9pe6SssC;!elAK;ol2Vy;an,bJcIdHel,geGh0landA4mFnEry,sDyC;!ce;coe,s;!a96nA;an,eo;l3Kr;e4Sg3n6oA5ri6A;co,ky;bAe9V;cCl6;ar5Qc5PhDkCo;!ey,ie,y;a87ie;gDid,ub5x,yCza;ansh,nT;g8XiC;na8Ts;ch60fa4lEmDndCpha4sh6Wul,ymo72;alA0ol2Cy;i9Jon;f,ph;ent2inC;cy,t1;aGeEhilDier64ol,reC;st1;!ip,lip;d9Crcy,tC;ar,e2W;b3Udra6Ht46ul;ctav2Wliv3m97rGsDtCum8Vw5;is,to;aDc8TvC;al54;ma;i,l4BvK;athKeIiEoC;aCel,l0ma0r2Y;h,m;cDg4i3KkC;h6Wola;holBkColB;!olB;al,d,il,ls1vC;il52;anCy;!a4i4;aXeUiLoGuDyC;l22r1;hamDr61staC;fa,p4I;ed,mG;dibo,e,hamEis1YntDsCussa;es,he;e,y;ad,ed,mC;ad,ed;cHgu4kFlEnDtchC;!e7;a7Aik;o04t1;e,olC;aj;ah,hCk6;a4eC;al,l;hDlv2rC;le,ri7v2;di,met;ck,hOlMmPnu4rIs1tEuricDxC;!imilian87we7;e,io;eo,hDiBtC;!eo,hew,ia;eCis;us,w;cEio,k81lDqu6Isha7tCv2;i2Jy;in,on;!el,oLus;achCcolm,ik;ai,y;amCdi,moud;adC;ou;aSeOiNlo2ToJuDyC;le,nd1;cFiEkCth3;aCe;!s;gi,s;as,iaC;no;g0nn6SrenEuCwe7;!iC;e,s;!zo;am,on4;a7Cevi,la4UnEoCst3vi;!nC;!a62el;!ny;mDnCr16ur4Vwr4V;ce,d1;ar,o4P;aJeEhaled,iCrist4Xu4Ay3D;er0p,rC;by,k,ollos;en0iFnCrmit,v2;!dDnCt5E;e10y;a7ri4P;r,th;na69rCthem;im,l;aZeRiPoEuC;an,liCst2;an,o,us;aqu2eKhnJnHrFsC;eDhCi7Due;!ua;!ph;dCge;an,i,on;!aCny;h,s,th4Z;!ath4Yie,nA;!l,sCy;ph;an,e,mC;!mA;d,ffHrEsC;sCus;!e;a5KemDmai8oCry;me,ni0Q;i6Wy;!e07rC;ey,y;cId5kHmGrEsDvi3yC;!d5s1;on,p3;ed,od,rCv4O;e51od;al,es,is1;e,ob,ub;k,ob,quC;es;aObrahNchika,gLkeKlija,nuJrHsEtCv0;ai,sC;uki;aCha0i6Hma4sac;ac,iaC;h,s;a,vinCw2;!g;k,nngu53;!r;nacCor;io;im;in,n;aLeGina4WoEuCyd57;be27gCmber4EsE;h,o;m3ra35sCwa3Z;se2;aFctEitEnDrC;be22m0;ry;or;th;bLlKmza,nJo,rEsDyC;a44d5;an,s0;lFo4FrEuCv6;hi41ki,tC;a,o;is1y;an,ey;k,s;!im;ib;aReNiMlenLoJrFuC;illerDsC;!tavo;mo;aEegCov3;!g,orC;io,y;dy,h58nt;nzaCrd1;lo;!n;lbe4Qno,ovan4S;ne,oErC;aCry;ld,rd4O;ffr6rge;bri4l5rCv2;la20r3Fth,y;aSeOiMlKorr0JrC;anEedCitz;!dAeCri25;ri24;cEkC;!ie,lC;in,yn;esKisC;!co,zek;etch3oC;yd;d4lConn;ip;deriEliDng,rnC;an02;pe,x;co;bi0di;ar00dVfrUit0lOmHnGo2rDsteb0th0uge8vCym5zra;an,ere2W;gi,iDnCrol,v2w2;est3Zie;c08k;och,rique,zo;aHerGiDmC;aGe2Q;lDrC;!h0;!io;s1y;nu4;be0Ad1iFliEmDt1viCwood;n,s;er,o;ot1Us;!as,j44sC;ha;a2en;!dAg32mFuDwC;a26in;arC;do;o0Tu0T;l,nC;est;aZePiMoFrEuDwCyl0;ay8ight;a8dl6nc0st2;ag0ew;minGnEri0ugDyC;le;!lB;!a29nCov0;e7ie,y;go,icC;!k;armuDeCll1on,rk;go;id;anJj0lbeImetri9nGon,rFsEvDwCxt3;ay8ey;en,in;hawn,mo09;ek,ri0G;is,nCv3;is,y;rt;!dC;re;lLmJnIrEvC;e,iC;!d;en,iEne7rCyl;eCin,yl;l2Wn;n,o,us;!e,i4ny;iCon;an,en,on;e,lB;as;a07e05hXiar0lMoHrFuDyrC;il,us;rtC;!is;aCistobal;ig;dy,lFnDrC;ey,neli9y;or,rC;ad;by,e,in,l2t1;aHeEiCyJ;fCnt;fo0Dt1;meDt9velaC;nd;nt;rEuDyC;!t1;de;enC;ce;aGeFrisDuC;ck;!tC;i0oph3;st3;d,rlCs;eCie;s,y;cCdric,s11;il;lFmer1rC;ey,lDro7y;ll;!os,t1;eb,v2;ar03eVilUlaToQrDuCyr1;ddy,rtJ;aKeFiEuDyC;an,ce,on;ce,no;an,ce;nDtC;!t;dDtC;!on;an,on;dDndC;en,on;!foCl6y;rd;bDrCyd;is;!by;i8ke;al,lA;nGrCshoi;at,nDtC;!r11;aCie;rd0M;!edict,iDjam2nA;ie,y;to;n6rCt;eCy;tt;ey;ar0Yb0Od0Kgust2hm0Hid5ja0FlZmXnPputsiOrFsaEuCya0ziz;gust9st2;us;hi;aJchIi4jun,maGnEon,tCy0;hCu07;ur;av,oC;ld;an,nd05;el;ie;ta;aq;dHgel00tC;hoFoC;i8nC;!iXy;ne;ny;reCy;!as,s,w;ir,mCos;ar;an,bePd5eJfGi,lFonEphonIt1vC;aNin;on;so,zo;an,en;onDrC;edK;so;c,jaFksandEssaFxC;!and3;er;ar,er;ndC;ro;rtC;!o;ni;en;ad,eC;d,t;in;aDoCri0vik;lfo;mCn;!a;dGeFraDuC;!bakr,lfazl;hCm;am;!l;allFel,oulaye,ulC;!lDrahm0;an;ah,o;ah;av,on|Verb\xA6awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en|PhrasalVerb\xA60:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut|Modal\xA6c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld|Adjective\xA60:73;1:7I;2:7O;3:7H;4:7A;5:5A;6:47;7:48;8:4Q;9:5Z;A:7F;B:6X;C:5V;D:6Y;E:71;a6Hb63c5Pd55e4Rf48g40h3Pi34j32k31l2Qm2Fn26o1Qp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6A;d6Czy;despr73s5E;!sa7;eGlFste25;co1Hl o4J;!k5;aGiFola4A;b7Rce versa,ol53;ca2gabo61nilla;ltWnJpGrb58su4tterF;!moB; f33b1NpGsFti1G;ca7et,ide dMtairs;er,i3M;aPbeco6Pconvin26deMeLfair,ivers4knKprecedYrIsGwF;iel1Zritt5X;i1UuF;pervis0specti3;eFu5;cognLgul6Fl6F;own;ndi3v5Rxpect0;cid0rF;!grou5MsF;iz0tood;b7ppeaLssu6EuthorF;iz0;i23ra;aJeHhough4NoGrF;i1oubl0;geth8p,rpD;en5OlFm4Yrr2Tst0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3DoPpOqueami3DtJuFymb62;bHi gener53pFrprisi3;erFre0K;! dup8b,i28;du0seq4S;anda6SeIi0OrFy37;aightFip0; fFfF;or59;adfaBreotyp0;aCec2Fir1IlendDot on; call0le,mb8phist1WrFu0Wvi40;dDry;gnifica2nF;ceCg7;am2Oe8ocki3ut;cFda1em5lfi2Xni1Vpa67re6;o1Fr3U;at56ient27reec56;cr0me,ns serif;aMeIiGoF;buBtt4SuSy4;ghtFv4;!-28f9;ar,bel,condi1du61fres50lHpublic3UsFtard0;is46oF;lu1na2;e1Duc44;bDciF;al,st;aPeNicayu6lacDopuliBrGuF;bl58mp0;eJiGoF;!b09fuEmi30p8;mGor,sFva1;ti6;a4Ue;ciEmF;a0Hi5I;ac20rFti1;feAma2Tplexi3v33;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Lsi45;en,posi1; boa5Fg2Jli6;!ay; gua5DbFli6;eat;eHsF;cFer0Hole1;e6uC;d2Sse;ak0eMiLoFua4O;nJrGtF;ab7;thF;!eF;rn;chala2descri4Zstop;ght5;arby,cessa3Wighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuC;di4EnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abCho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3C;!-0C;nguDst,tt8;ap1Sind5no0A;agg0uF;niOstifi0veni7;de4gno4Blleg4mSnHpso 1VrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenEoxF;ic36;a6i2R;a1er,oce2;iGoF;or;reA;deq3Jppr2Y;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0Q;d2QnE;aKelJiHoFumdr3B;neBok0rrFs07ur5;if2S;ghfalut1OspF;an2Q;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Jiga22lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Dob4;aUeOinNlMoHrF;a1TeFoz1K;e2Dq12tf9;oHrF; keeps,eFm8tuna1;g04ign;liF;sh;ag2Zue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lEr Fux,vori1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiC;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erE;creHeas0gruntl0honeBordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarClJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraDg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainBgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerE;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt|Comparable\xA60:41;1:4I;2:45;3:4B;4:2Y;5:3X;a4Ob44c3Od3De35f2Rg2Fh24i1Vj1Uk1Rl1Im1Cn16o14p0Tqu0Rr0IsRtKuIvFw7y6za12;ell27ou3;aBe9hi1Yi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Mt;k,ry;n1Tr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Mse5;like0ti1;aAen9hi8i7ough,r6;anqu2Qen1ue;dy,g3Ume0ny,r09;ck,n,rs2R;d42se;ll,me,rt,s6wd47;te5;aVcarUeThRiQkin0GlMmKoHpGqua1HtAu7w6;eet,ift;b7dd15per0Hr6;e,re2J;sta2Ht4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Hn0W;a1ep,rn;le,rk;e24i3Hright0;ci2Aft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g37m6;!y;ek,nd3F;ck,l0mp4;a6iUort,rill,y;dy,ll0Zrp;cu0Tve0Txy;ce,ed,y;d,fe,int0l1Xv16;aBe9i8o6ude;mantic,o1Ksy,u6;gh,nd;ch,pe,tzy;a6d,mo0J;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aFhoEi1SlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fou00ud;ey,k0;li06or,te1D;a6easa2;in,nt;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd|Adverb\xA6a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori|Expression\xA6a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la|Preposition\xA6'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut|Conjunction\xA6aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh|Determiner\xA6aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er\",\"conjugations\":\"t:ake,ook,,,aken|:can,could,can,_|free:_,,,ing|puk:e,,,ing|ar:ise,ose,,,isen|babys:it,at|:be,was,is,am,been|:is,was,is,being|beat:_,,,ing,en|beg:in,an,,inning,un|ban:_,ned,,ning|bet:_,,,,_|bit:e,_,,ing,ten|ble:ed,d,,,d|bre:ed,d|br:ing,ought,,,ought|broadcast:_,_|buil:d,t,,,t|b:uy,ought,,,ought|cho:ose,se,,osing,sen|cost:_,_|deal:_,t,,,t|d:ie,ied,,ying|d:ig,ug,,igging,ug|dr:aw,ew,,,awn|dr:ink,ank,,,unk|dr:ive,ove,,iving,iven|:eat,ate,,eating,eaten|f:all,ell,,,allen|fe:ed,d,,,d|fe:el,lt|f:ight,ought,,,ought|f:ind,ound|fl:y,ew,,,own|bl:ow,ew,,,own|forb:id,ade|edit:_,,,ing|forg:et,ot,,eting,otten|forg:ive,ave,,iving,iven|fr:eeze,oze,,eezing,ozen|g:et,ot|g:ive,ave,,iving,iven|:go,went,goes,,gone|h:ang,ung,,,ung|ha:ve,d,s,ving,d|hear:_,d,,,d|hid:e,_,,,den|h:old,eld,,,eld|hurt:_,_,,,_|la:y,id,,,id|le:ad,d,,,d|le:ave,ft,,,ft|l:ie,ay,,ying|li:ght,t,,,t|los:e,t,,ing|ma:ke,de,,,de|mean:_,t,,,t|me:et,t,,eting,t|pa:y,id,,,id|read:_,_,,,_|r:ing,ang,,,ung|r:ise,ose,,ising,isen|r:un,an,,unning,un|sa:y,id,ys,,id|s:ee,aw,,eeing,een|s:ell,old,,,old|sh:ine,one,,,one|sho:ot,t,,,t|show:_,ed|s:ing,ang,,,ung|s:ink,ank|s:it,at|slid:e,_,,,_|sp:eak,oke,,,oken|sp:in,un,,inning,un|st:and,ood|st:eal,ole|st:ick,uck|st:ing,ung|:stream,,,,|str:ike,uck,,iking|sw:ear,ore|sw:im,am,,imming|sw:ing,ung|t:each,aught,eaches|t:ear,ore|t:ell,old|th:ink,ought|underst:and,ood|w:ake,oke|w:ear,ore|w:in,on,,inning|withdr:aw,ew|wr:ite,ote,,iting,itten|t:ie,ied,,ying|ski:_,ied|:boil,,,,|miss:_,,_|:act,,,,|compet:e,ed,,ing|:being,were,are,are|impl:y,ied,ies|ic:e,ed,,ing|develop:_,ed,,ing|wait:_,ed,,ing|aim:_,ed,,ing|spil:l,t,,,led|drop:_,ped,,ping|log:_,ged,,ging|rub:_,bed,,bing|smash:_,,es|egg:_,ed|suit:_,ed,,ing|age:_,d,s,ing|shed:_,_,s,ding|br:eak,oke|ca:tch,ught|d:o,id,oes|b:ind,ound|spread:_,_|become:_,,,,_|ben:d,,,,t|br:ake,,,,oken|burn:_,,,,ed|burst:_,,,,_|cl:ing,,,,ung|c:ome,ame,,,ome|cre:ep,,,,pt|cut:_,,,,_|dive:_,,,,d|dream:_,,,,t|fle:e,,,eing,d|fl:ing,,,,ung|got:_,,,,ten|grow:_,,,,n|hit:_,,,,_|ke:ep,,,,pt|kne:el,,,,lt|know:_,,,,n|leap:_,,,,t|len:d,,,,t|lo:ose,,,,st|prove:_,,,,n|put:_,,,,_|quit:_,,,,_|rid:e,,,,den|s:eek,,,,ought|sen:d,,,,t|set:_,,,,_|sew:_,,,,n|shake:_,,,,n|shave:_,,,,d|shut:_,,,,_|s:eat,,,,at|sla:y,,,,in|sle:ep,,,,pt|sn:eak,,,,uck|spe:ed,,,,d|spen:d,,,,t|sp:it,,,,at|split:_,,,,_|spr:ing,,,,ung|st:ink,unk,,,unk|strew:_,,,,n|sw:are,,,,orn|swe:ep,,,,pt|thrive:_,,,,d|undergo:_,,,,ne|upset:_,,,,_|w:eave,,,,oven|we:ep,,,,pt|w:ind,,,,ound|wr:ing,,,,ung\",\"plurals\":\"addend|um|a,alga|e,alumna|e,alumn|us|i,appendi|x|ces,avocado|s,bacill|us|i,barracks|,beau|x,bus|es,cact|us|i,chateau|x,analys|is|es,diagnos|is|es,parenthes|is|es,prognos|is|es,synops|is|es,thes|is|es,child|ren,circus|es,clothes|,corp|us|ora,criteri|on|a,curricul|um|a,database|s,deer|,echo|es,embargo|es,epoch|s,f|oot|eet,gen|us|era,g|oose|eese,halo|s,hippopotam|us|i,ind|ex|ices,larva|e,lea|f|ves,librett|o|i,loa|f|ves,m|an|en,matri|x|ces,memorand|um|a,modul|us|i,mosquito|es,move|s,op|us|era,ov|um|a,ox|en,pe|rson|ople,phenomen|on|a,quiz|zes,radi|us|i,referend|um|a,rodeo|s,sex|es,shoe|s,sombrero|s,stomach|s,syllab|us|i,tableau|x,thie|f|ves,t|ooth|eeth,tornado|s,tuxedo|s,zero|s\",\"patterns\":{\"Person\":[\"master of #Noun\",\"captain of the #Noun\"]},\"regex\":{\"HashTag\":[\"^#[a-z]+\"],\"Gerund\":[\"^[a-z]+n['\u2019]$\"],\"PhoneNumber\":[\"^[0-9]{3}-[0-9]{4}$\",\"^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$\"],\"Time\":[\"^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$\",\"^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$\",\"^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$\",\"^[PMCE]ST$\",\"^utc ?[+-]?[0-9]+?$\",\"^[a-z0-9]*? o'?clock$\"],\"Date\":[\"^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$\",\"^[0-9]{1,4}/[0-9]{1,2}/[0-9]{1,4}$\"],\"Money\":[\"^[-+]?[$\u20AC\xA5\xA3][0-9]+(.[0-9]{1,2})?$\",\"^[-+]?[$\u20AC\xA5\xA3][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$\"],\"Value\":[\"^[-+]?[$\u20AC\xA5\xA3][0-9]+(.[0-9]{1,2})?$\",\"^[-+]?[$\u20AC\xA5\xA3][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$\",\"^[0-9.]{1,2}[-\u2013][0-9]{1,2}$\"],\"NumberRange\":[\"^[0-9.]{1,4}(st|nd|rd|th)?[-\u2013][0-9.]{1,4}(st|nd|rd|th)?$\",\"^[0-9.]{1,2}[-\u2013][0-9]{1,2}$\"],\"NiceNumber\":[\"^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$\"],\"NumericValue\":[\"^[-+]?[0-9]+(.[0-9]+)?$\",\"^.?[0-9]+([0-9,.]+)?%$\"],\"Percent\":[\"^.?[0-9]+([0-9,.]+)?%$\"],\"Cardinal\":[\"^.?[0-9]+([0-9,.]+)?%$\"],\"Fraction\":[\"^[0-9]{1,4}/[0-9]{1,4}$\"],\"LastName\":[\"^ma?c'.*\",\"^o'[drlkn].*\"]}}"; + var isNegative = parsed.negative.found; -},{}],209:[function(_dereq_,module,exports){ -'use strict'; + if (isNegative) { + forms.PastTense = 'did not ' + forms.Infinitive; + forms.PresentTense = 'does not ' + forms.Infinitive; + forms.Gerund = 'not ' + forms.Gerund; + } //future Tense is pretty straightforward -var conjugate = _dereq_('../subset/verbs/methods/conjugate/faster.js'); //extend our current irregular conjugations, overwrite if exists -//also, map the irregulars for easy infinitive lookup - {bought: 'buy'} + if (!forms.FutureTense) { + if (isNegative) { + forms.FutureTense = 'will not ' + forms.Infinitive; + } else { + forms.FutureTense = 'will ' + forms.Infinitive; + } + } -var addConjugations = function addConjugations(obj) { - var _this = this; + if (isNegative) { + forms.Infinitive = 'not ' + forms.Infinitive; + } - Object.keys(obj).forEach(function (inf) { - _this.conjugations[inf] = _this.conjugations[inf] || {}; //add it to the lexicon + return forms; + }; - _this.words[inf] = _this.words[inf] || 'Infinitive'; - Object.keys(obj[inf]).forEach(function (tag) { - var word = obj[inf][tag]; //add this to our conjugations + var conjugate_1$1 = conjugate$2; - _this.conjugations[inf][tag] = word; //add it to the lexicon, too + var methods$7 = { + /** overload the original json with verb information */ + json: function json(options) { + var _this = this; - _this.words[word] = _this.words[word] || tag; //also denormalize to cache.toInfinitive + var n = null; - _this.cache.toInfinitive[obj[inf][tag]] = inf; - }); //guess the other conjugations + if (typeof options === 'number') { + n = options; + options = null; + } - var forms = conjugate(inf, _this); - Object.keys(forms).forEach(function (k) { - var word = forms[k]; + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (p) { + var json = p.json(options)[0]; + var parsed = parse$2(p); + json.parts = {}; + Object.keys(parsed).forEach(function (k) { + json.parts[k] = parsed[k].text('normal'); + }); + json.isNegative = p.has('#Negative'); + json.conjugations = conjugate_1$1(parsed, _this.world); + res.push(json); + }); - if (_this.words.hasOwnProperty(word) === false) { - _this.words[word] = k; + if (n !== null) { + return res[n]; } - }); - }); - return obj; -}; -module.exports = addConjugations; + return res; + }, -},{"../subset/verbs/methods/conjugate/faster.js":79}],210:[function(_dereq_,module,exports){ -"use strict"; + /** grab the adverbs describing these verbs */ + adverbs: function adverbs() { + var list = []; // look at internal adverbs -// -var addPatterns = function addPatterns(obj) { - var _this = this; + this.forEach(function (vb) { + var advb = parse$2(vb).adverb; - Object.keys(obj).forEach(function (k) { - _this.patterns[k] = obj[k]; - }); - return obj; -}; + if (advb.found) { + list = list.concat(advb.list); + } + }); // look for leading adverbs -module.exports = addPatterns; + var m = this.lookBehind('#Adverb$'); -},{}],211:[function(_dereq_,module,exports){ -'use strict'; //put singular->plurals in world, the reverse in cache, -//and both forms in the lexicon + if (m.found) { + list = m.list.concat(list); + } // look for trailing adverbs -var addPlurals = function addPlurals(obj) { - var _this = this; - Object.keys(obj).forEach(function (sing) { - var plur = obj[sing]; - _this.plurals[sing] = plur; //add them both to the lexicon + m = this.lookAhead('^#Adverb'); - _this.words[plur] = _this.words[plur] || 'Plural'; - _this.words[sing] = _this.words[sing] || 'Singular'; //denormalize them in cache.toPlural + if (m.found) { + list = list.concat(m.list); + } - _this.cache.toSingular[plur] = sing; - }); - return obj; -}; + return this.buildFrom(list); + }, -module.exports = addPlurals; + /**return verbs like 'we walk' and not 'spencer walks' */ + isPlural: function isPlural() { + var _this2 = this; -},{}],212:[function(_dereq_,module,exports){ -"use strict"; + var list = []; + this.forEach(function (vb) { + var parsed = parse$2(vb); -// -var addRegex = function addRegex(obj) { - var _this = this; + if (isPlural_1$2(parsed, _this2.world) === true) { + list.push(vb.list[0]); + } + }); + return this.buildFrom(list); + }, - Object.keys(obj).forEach(function (k) { - _this.regex.push({ - reg: new RegExp(k, 'i'), - tag: obj[k] - }); - }); -}; + /** return verbs like 'spencer walks' and not 'we walk' */ + isSingular: function isSingular() { + var _this3 = this; -module.exports = addRegex; + var list = []; + this.forEach(function (vb) { + var parsed = parse$2(vb); -},{}],213:[function(_dereq_,module,exports){ -'use strict'; //add 'downward' tags (that immediately depend on this one) + if (isPlural_1$2(parsed, _this3.world) === false) { + list.push(vb.list[0]); + } + }); + return this.buildFrom(list); + }, -var addDownword = _dereq_('../tags/addDownward'); //extend our known tagset with these new ones + /** */ + conjugate: function conjugate() { + var _this4 = this; + var result = []; + this.forEach(function (vb) { + var parsed = parse$2(vb); -var addTags = function addTags(tags) { - var _this = this; + var forms = conjugate_1$1(parsed, _this4.world); - Object.keys(tags).forEach(function (tag) { - var obj = tags[tag]; - obj.notA = obj.notA || []; - obj.downward = obj.downward || []; - _this.tags[tag] = obj; - }); - addDownword(this.tags); - return tags; -}; + result.push(forms); + }); + return result; + }, -module.exports = addTags; + /** */ + toPastTense: function toPastTense() { + var _this5 = this; -},{"../tags/addDownward":135}],214:[function(_dereq_,module,exports){ -'use strict'; + this.forEach(function (vb) { + var parsed = parse$2(vb); -var normalize = _dereq_('../term/methods/normalize/normalize').normalize; + var str = conjugate_1$1(parsed, _this5.world).PastTense; -var inflect = _dereq_('../subset/nouns/methods/pluralize'); + if (str) { + vb.replaceWith(str, false, true); // vb.tag('PastTense') + } + }); + return this; + }, -var conjugate = _dereq_('../subset/verbs/methods/conjugate/faster.js'); + /** */ + toPresentTense: function toPresentTense() { + var _this6 = this; -var adjFns = _dereq_('../subset/adjectives/methods'); + this.forEach(function (vb) { + var parsed = parse$2(vb); -var wordReg = / /; + var obj = conjugate_1$1(parsed, _this6.world); -var cleanUp = function cleanUp(str) { - str = normalize(str); //extra whitespace + var str = obj.PresentTense; // 'i look', not 'i looks' - str = str.replace(/\s+/, ' '); //remove sentence-punctuaion too + if (vb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) { + str = obj.Infinitive; + } - str = str.replace(/[.\?,;\!]/g, ''); - return str; -}; // + if (str) { + vb.replaceWith(str, false, true); + vb.tag('PresentTense'); + } + }); + return this; + }, + /** */ + toFutureTense: function toFutureTense() { + var _this7 = this; -var addWords = function addWords(words) { - var _this = this; + this.forEach(function (vb) { + var parsed = parse$2(vb); - //go through each word - Object.keys(words).forEach(function (word) { - var tag = words[word]; - word = cleanUp(word); - _this.words[word] = tag; //add it to multi-word cache, + var str = conjugate_1$1(parsed, _this7.world).FutureTense; - if (wordReg.test(word) === true) { - var arr = word.split(wordReg); - _this.cache.firstWords[arr[0]] = true; - } //turn singulars into plurals + if (str) { + vb.replaceWith(str, false, true); + vb.tag('FutureTense'); + } + }); + return this; + }, + /** */ + toInfinitive: function toInfinitive() { + var _this8 = this; - if (tag === 'Singular') { - var plural = inflect(word, {}); + this.forEach(function (vb) { + var parsed = parse$2(vb); - if (plural && plural !== word) { - _this.words[plural] = 'Plural'; - } + var str = toInfinitive_1$1(parsed, _this8.world); - return; - } //turn infinitives into all conjugations + if (str) { + vb.replaceWith(str, false, true); + vb.tag('Infinitive'); + } + }); + return this; + }, + /** */ + toGerund: function toGerund() { + var _this9 = this; - if (tag === 'Infinitive') { - var conj = conjugate(word, _this); - Object.keys(conj).forEach(function (k) { - _this.words[conj[k]] = k; - }); - return; - } //phrasals like 'pull out' get conjugated too + this.forEach(function (vb) { + var parsed = parse$2(vb); + var str = conjugate_1$1(parsed, _this9.world).Gerund; - if (tag === 'PhrasalVerb') { - var _arr = word.split(/ /); + if (str) { + vb.replaceWith(str, false, true); + vb.tag('Gerund'); + } + }); + return this; + }, - var _conj = conjugate(_arr[0], _this); + /** return only verbs with 'not'*/ + isNegative: function isNegative() { + return this["if"]('#Negative'); + }, - Object.keys(_conj).forEach(function (k) { - var form = _conj[k] + ' ' + _arr[1]; - _this.words[form] = 'PhrasalVerb'; //add it to cache, too + /** return only verbs without 'not'*/ + isPositive: function isPositive() { + return this.ifNo('#Negative'); + }, - _this.cache.firstWords[_conj[k]] = true; - }); - return; - } //turn some adjectives into superlatives + /** add a 'not' to these verbs */ + toNegative: function toNegative() { + var _this10 = this; + this.list.forEach(function (p) { + var doc = _this10.buildFrom([p]); - if (tag === 'Comparable') { - var comp = adjFns.toComparative(word); + var parsed = parse$2(doc); - if (comp && word !== comp) { - _this.words[comp] = 'Comparative'; - } + toNegative_1(parsed, doc.world); + }); + return this; + }, - var supr = adjFns.toSuperlative(word); + /** remove 'not' from these verbs */ + toPositive: function toPositive() { + var m = this.match('do not #Verb'); - if (supr && word !== supr) { - _this.words[supr] = 'Superlative'; + if (m.found) { + m.remove('do not'); } + + return this.remove('#Negative'); } - }); - return words; -}; + }; -module.exports = addWords; + var addMethod$9 = function addMethod(Doc) { + /** */ + var Verbs = + /*#__PURE__*/ + function (_Doc) { + _inherits(Verbs, _Doc); -},{"../subset/adjectives/methods":11,"../subset/nouns/methods/pluralize":44,"../subset/verbs/methods/conjugate/faster.js":79,"../term/methods/normalize/normalize":149}],215:[function(_dereq_,module,exports){ -'use strict'; // const addWords = require('./addWords'); + function Verbs() { + _classCallCheck(this, Verbs); -var fns = _dereq_('../fns'); + return _possibleConstructorReturn(this, _getPrototypeOf(Verbs).apply(this, arguments)); + } -var data = _dereq_('./_data'); + return Verbs; + }(Doc); // add-in our methods -var moreData = _dereq_('./more-data'); -var tags = _dereq_('../tags'); + Object.assign(Verbs.prototype, methods$7); // aliases -var unpack = _dereq_('./unpack'); + Verbs.prototype.negate = Verbs.prototype.toNegative; -var addTags = _dereq_('./addTags'); + Doc.prototype.verbs = function (n) { + var match = this.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); // try to ignore leading and trailing adverbs -var addWords = _dereq_('./addWords'); + match = match.not('^#Adverb+'); + match = match.not('#Adverb+$'); // handle commas: + // don't split 'really, really' -var addRegex = _dereq_('./addRegex'); + var keep = match.match('(#Adverb && @hasComma) #Adverb'); // // but split the other commas -var addConjugations = _dereq_('./addConjugations'); + var m = match.not(keep).splitAfter('@hasComma'); // // combine them back together -var addPatterns = _dereq_('./addPatterns'); + m = m.concat(keep); + m.sort('index'); //handle slashes? + //ensure there's actually a verb -var addPlurals = _dereq_('./addPlurals'); + m = m["if"]('#Verb'); //grab (n)th result -var misc = _dereq_('./more-data/misc'); //lazier/faster object-merge + if (typeof n === 'number') { + m = m.get(n); + } + var vb = new Verbs(m.list, this, this.world); + return vb; + }; -var extend = function extend(main, obj) { - var keys = Object.keys(obj); + return Doc; + }; - for (var i = 0; i < keys.length; i++) { - main[keys[i]] = obj[keys[i]]; - } + var Verbs = addMethod$9; - return main; -}; //class World + var addMethod$a = function addMethod(Doc) { + /** */ + var People = + /*#__PURE__*/ + function (_Doc) { + _inherits(People, _Doc); + function People() { + _classCallCheck(this, People); -var World = function World() { - this.words = {}; - this.tags = tags; - this.regex = []; - this.patterns = {}; - this.conjugations = {}; - this.plurals = {}; //denormalized data for faster-lookups + return _possibleConstructorReturn(this, _getPrototypeOf(People).apply(this, arguments)); + } - this.cache = { - firstWords: {}, - toInfinitive: {}, - toSingular: {} - }; -}; + return People; + }(Doc); -World.prototype.addTags = addTags; -World.prototype.addWords = addWords; -World.prototype.addRegex = addRegex; -World.prototype.addConjugations = addConjugations; -World.prototype.addPlurals = addPlurals; -World.prototype.addPatterns = addPatterns; //make a no-reference copy of all the data + Doc.prototype.people = function (n) { + var match = this.splitAfter('@hasComma'); + match = match.match('#Person+'); //grab (n)th result -World.prototype.clone = function () { - var _this = this; + if (typeof n === 'number') { + match = match.get(n); + } - var w2 = new World(); - ['words', 'firstWords', 'tagset', 'regex', 'patterns', 'conjugations', 'plurals'].forEach(function (k) { - if (_this[k]) { - w2[k] = fns.copy(_this[k]); - } - }); - return w2; -}; //add all the things, in all the places + return new People(match.list, this, this.world); + }; + return Doc; + }; -World.prototype.plugin = function (obj) { - //untangle compromise-plugin - obj = unpack(obj); //add all-the-things to this world object - //(order may matter) + var People = addMethod$a; - if (obj.tags) { - this.addTags(obj.tags); - } + var subclass = [Abbreviations, Acronyms, Clauses, Contractions, Lists, Nouns, Parentheses, Possessives, Quotations, Verbs, People]; - if (obj.regex) { - this.addRegex(obj.regex); - } + var extend = function extend(Doc) { + // add basic methods + Object.keys(_simple).forEach(function (k) { + return Doc.prototype[k] = _simple[k]; + }); // add subclassed methods - if (obj.patterns) { - this.addPatterns(obj.patterns); - } + subclass.forEach(function (addFn) { + return addFn(Doc); + }); + return Doc; + }; - if (obj.conjugations) { - this.addConjugations(obj.conjugations); - } + var Subset = extend; - if (obj.plurals) { - this.addPlurals(obj.plurals); - } + var methods$8 = { + misc: methods$4, + selections: _simple + }; + /** a parsed text object */ - if (obj.words) { - this.addWords(obj.words); - } -}; //export a default world - - -var w = new World(); -w.plugin(data); -w.addWords(misc); -moreData.forEach(function (obj) { - extend(w.words, obj); -}); -module.exports = { - w: w, - reBuild: function reBuild() { - //export a default world - var w2 = new World(); - w2.plugin(data); - w2.addWords(misc); - moreData.forEach(function (obj) { - extend(w2.words, obj); - }); - return w2; - } -}; - -},{"../fns":3,"../tags":137,"./_data":208,"./addConjugations":209,"./addPatterns":210,"./addPlurals":211,"./addRegex":212,"./addTags":213,"./addWords":214,"./more-data":217,"./more-data/misc":219,"./unpack":223}],216:[function(_dereq_,module,exports){ -//these are common word shortenings used in the lexicon and sentence segmentation methods -//there are all nouns,or at the least, belong beside one. -"use strict"; //common abbreviations - -var compact = { - Noun: ["arc", "al", "exp", "fy", "pd", "pl", "plz", "tce", "bl", "ma", "ba", "lit", "ex", "eg", "ie", "ca", "cca", "vs", "etc", "esp", "ft", //these are too ambiguous - "bc", "ad", "md", "corp", "col"], - Organization: ["dept", "univ", "assn", "bros", "inc", "ltd", "co", //proper nouns with exclamation marks - "yahoo", "joomla", "jeopardy"], - Place: ["rd", "st", "dist", "mt", "ave", "blvd", "cl", "ct", "cres", "hwy", //states - "ariz", "cal", "calif", "colo", "conn", "fla", "fl", "ga", "ida", "ia", "kan", "kans", "minn", "neb", "nebr", "okla", "penna", "penn", "pa", "dak", "tenn", "tex", "ut", "vt", "va", "wis", "wisc", "wy", "wyo", "usafa", "alta", "ont", "que", "sask"], - Month: ["jan", "feb", "mar", "apr", "jun", "jul", "aug", "sep", "sept", "oct", "nov", "dec"], - Date: ["circa"], - //Honorifics - Honorific: ["adj", "adm", "adv", "asst", "atty", "bldg", "brig", "capt", "cmdr", "comdr", "cpl", "det", "dr", "esq", "gen", "gov", "hon", "jr", "llb", "lt", "maj", "messrs", "mister", "mlle", "mme", "mr", "mrs", "ms", "mstr", "op", "ord", "phd", "prof", "pvt", "rep", "reps", "res", "rev", "sen", "sens", "sfc", "sgt", "sir", "sr", "supt", "surg" //miss - //misses - ], - Value: ["no"] -}; //unpack the compact terms into the misc lexicon.. - -var abbreviations = {}; -var keys = Object.keys(compact); - -for (var i = 0; i < keys.length; i++) { - var arr = compact[keys[i]]; - - for (var i2 = 0; i2 < arr.length; i2++) { - abbreviations[arr[i2]] = [keys[i], "Abbreviation"]; - } -} - -module.exports = abbreviations; - -},{}],217:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = [_dereq_('./abbreviations'), _dereq_('./irregularAdjectives').lexicon, _dereq_('./numbers').lexicon, _dereq_('./orgWords')]; - -},{"./abbreviations":216,"./irregularAdjectives":218,"./numbers":220,"./orgWords":221}],218:[function(_dereq_,module,exports){ -'use strict'; //adjectives that have irregular conjugations to adverb, comparative, and superlative forms - -var toAdverb = { - bad: 'badly', - best: 'best', - early: 'early', - fast: 'fast', - good: 'well', - hard: 'hard', - icy: 'icily', - idle: 'idly', - late: 'late', - latter: 'latter', - little: 'little', - "long": 'long', - low: 'low', - male: 'manly', - "public": 'publicly', - simple: 'simply', - single: 'singly', - special: 'especially', - straight: 'straight', - vague: 'vaguely', - well: 'well', - whole: 'wholly', - wrong: 'wrong' -}; -var toComparative = { - grey: 'greyer', - gray: 'grayer', - green: 'greener', - yellow: 'yellower', - red: 'redder', - good: 'better', - well: 'better', - bad: 'worse', - sad: 'sadder', - big: 'bigger' -}; -var toSuperlative = { - nice: 'nicest', - late: 'latest', - hard: 'hardest', - inner: 'innermost', - outer: 'outermost', - far: 'furthest', - worse: 'worst', - bad: 'worst', - good: 'best', - big: 'biggest', - large: 'largest' -}; - -var combine = function combine(lexicon, obj, tag) { - var keys = Object.keys(obj); + var Doc = + /*#__PURE__*/ + function () { + function Doc(list, from, world) { + var _this = this; - for (var i = 0; i < keys.length; i++) { - lexicon[keys[i]] = 'Comparable'; + _classCallCheck(this, Doc); - if (lexicon[obj[keys[i]]] === undefined) { - lexicon[obj[keys[i]]] = tag; - } - } + this.list = list; //quiet these properties in console.logs - return lexicon; -}; - -var lexicon = combine({}, toSuperlative, 'Superlative'); -lexicon = combine(lexicon, toComparative, 'Comparative'); -lexicon = combine(lexicon, toAdverb, 'Adverb'); -module.exports = { - lexicon: lexicon, - toAdverb: toAdverb, - toComparative: toComparative, - toSuperlative: toSuperlative -}; - -},{}],219:[function(_dereq_,module,exports){ -"use strict"; - -//words that can't be compressed, for whatever reason -module.exports = { - '20th century fox': 'Organization', - '3m': 'Organization', - '7 eleven': 'Organization', - '7-eleven': 'Organization', - g8: 'Organization', - 'motel 6': 'Organization', - vh1: 'Organization', - q1: 'Date', - q2: 'Date', - q3: 'Date', - q4: 'Date', - //misc - records: 'Plural', - '&': 'Conjunction', - was: ['Copula', 'PastTense'] -}; - -},{}],220:[function(_dereq_,module,exports){ -'use strict'; - -var cardinal = { - ones: { - // 'a': 1, - zero: 0, - one: 1, - two: 2, - three: 3, - four: 4, - five: 5, - six: 6, - seven: 7, - eight: 8, - nine: 9 - }, - teens: { - ten: 10, - eleven: 11, - twelve: 12, - thirteen: 13, - fourteen: 14, - fifteen: 15, - sixteen: 16, - seventeen: 17, - eighteen: 18, - nineteen: 19 - }, - tens: { - twenty: 20, - thirty: 30, - forty: 40, - fourty: 40, - //support typo - fifty: 50, - sixty: 60, - seventy: 70, - eighty: 80, - ninety: 90 - }, - multiples: { - hundred: 1e2, - thousand: 1e3, - // grand: 1e3, - million: 1e6, - billion: 1e9, - trillion: 1e12, - quadrillion: 1e15, - quintillion: 1e18, - sextillion: 1e21, - septillion: 1e24 - } -}; -var ordinal = { - ones: { - zeroth: 0, - first: 1, - second: 2, - third: 3, - fourth: 4, - fifth: 5, - sixth: 6, - seventh: 7, - eighth: 8, - ninth: 9 - }, - teens: { - tenth: 10, - eleventh: 11, - twelfth: 12, - thirteenth: 13, - fourteenth: 14, - fifteenth: 15, - sixteenth: 16, - seventeenth: 17, - eighteenth: 18, - nineteenth: 19 - }, - tens: { - twentieth: 20, - thirtieth: 30, - fortieth: 40, - fourtieth: 40, - //support typo - fiftieth: 50, - sixtieth: 60, - seventieth: 70, - eightieth: 80, - ninetieth: 90 - }, - multiples: { - hundredth: 1e2, - thousandth: 1e3, - millionth: 1e6, - billionth: 1e9, - trillionth: 1e12, - quadrillionth: 1e15, - quintillionth: 1e18, - sextillionth: 1e21, - septillionth: 1e24 - } -}; //used for the units - -var prefixes = { - yotta: 1, - zetta: 1, - exa: 1, - peta: 1, - tera: 1, - giga: 1, - mega: 1, - kilo: 1, - hecto: 1, - deka: 1, - deci: 1, - centi: 1, - milli: 1, - micro: 1, - nano: 1, - pico: 1, - femto: 1, - atto: 1, - zepto: 1, - yocto: 1, - square: 1, - cubic: 1, - quartic: 1 -}; //create an easy mapping between ordinal-cardinal - -var toOrdinal = {}; -var toCardinal = {}; -var lexicon = {}; -Object.keys(ordinal).forEach(function (k) { - var ord = Object.keys(ordinal[k]); - var card = Object.keys(cardinal[k]); - - for (var i = 0; i < card.length; i++) { - toOrdinal[card[i]] = ord[i]; - toCardinal[ord[i]] = card[i]; - lexicon[ord[i]] = ['Ordinal', 'TextValue']; - lexicon[card[i]] = ['Cardinal', 'TextValue']; - - if (k === 'multiples') { - lexicon[ord[i]].push('Multiple'); - lexicon[card[i]].push('Multiple'); - } - } -}); -module.exports = { - toOrdinal: toOrdinal, - toCardinal: toCardinal, - cardinal: cardinal, - ordinal: ordinal, - prefixes: prefixes, - lexicon: lexicon -}; + Object.defineProperty(this, 'from', { + enumerable: false, + value: from, + writable: true + }); //borrow some missing data from parent -},{}],221:[function(_dereq_,module,exports){ -"use strict"; + if (world === undefined && from !== undefined) { + world = from.world; + } //'world' getter -//nouns that also signal the title of an unknown organization -//todo remove/normalize plural forms -var orgWords = ['administration', 'agence', 'agences', 'agencies', 'agency', 'airlines', 'airways', 'army', 'assoc', 'associates', 'association', 'assurance', 'authority', 'autorite', 'aviation', 'bank', 'banque', 'board', 'boys', 'brands', 'brewery', 'brotherhood', 'brothers', 'building society', 'bureau', 'cafe', 'caisse', 'capital', 'care', 'cathedral', 'center', 'central bank', 'centre', 'chemicals', 'choir', 'chronicle', 'church', 'circus', 'clinic', 'clinique', 'club', 'co', 'coalition', 'coffee', 'collective', 'college', 'commission', 'committee', 'communications', 'community', 'company', 'comprehensive', 'computers', 'confederation', 'conference', 'conseil', 'consulting', 'containers', 'corporation', 'corps', 'corp', 'council', 'crew', 'daily news', 'data', 'departement', 'department', 'department store', 'departments', 'design', 'development', 'directorate', 'division', 'drilling', 'education', 'eglise', 'electric', 'electricity', 'energy', 'ensemble', 'enterprise', 'enterprises', 'entertainment', 'estate', 'etat', 'evening news', 'faculty', 'federation', 'financial', 'fm', 'foundation', 'fund', 'gas', 'gazette', 'girls', 'government', 'group', 'guild', 'health authority', 'herald', 'holdings', 'hospital', 'hotel', 'hotels', 'inc', 'industries', 'institut', 'institute', 'institute of technology', 'institutes', 'insurance', 'international', 'interstate', 'investment', 'investments', 'investors', 'journal', 'laboratory', 'labs', // 'law', -'liberation army', 'limited', 'local authority', 'local health authority', 'machines', 'magazine', 'management', 'marine', 'marketing', 'markets', 'media', 'memorial', 'mercantile exchange', 'ministere', 'ministry', 'military', 'mobile', 'motor', 'motors', 'musee', 'museum', // 'network', -'news', 'news service', 'observatory', 'office', 'oil', 'optical', 'orchestra', 'organization', 'partners', 'partnership', // 'party', -'people\'s party', 'petrol', 'petroleum', 'pharmacare', 'pharmaceutical', 'pharmaceuticals', 'pizza', 'plc', 'police', 'polytechnic', 'post', 'power', 'press', 'productions', 'quartet', 'radio', 'regional authority', 'regional health authority', 'reserve', 'resources', 'restaurant', 'restaurants', 'savings', 'school', 'securities', 'service', 'services', 'social club', 'societe', 'society', 'sons', 'standard', 'state police', 'state university', 'stock exchange', 'subcommittee', 'syndicat', 'systems', 'telecommunications', 'telegraph', 'television', 'times', 'tribunal', 'tv', 'union', 'university', 'utilities', 'workers']; -module.exports = orgWords.reduce(function (h, str) { - h[str] = 'Noun'; - return h; -}, {}); -},{}],222:[function(_dereq_,module,exports){ -'use strict'; //supported verb forms: + Object.defineProperty(this, 'world', { + enumerable: false, + value: world // writable: true, //todo: add me? -var forms = [null, 'PastTense', 'PresentTense', 'Gerund', 'Participle']; // + }); //fast-scans for our data + //'found' getter -var unpackVerbs = function unpackVerbs(str) { - var verbs = str.split('|'); - return verbs.reduce(function (h, s) { - var parts = s.split(':'); - var prefix = parts[0]; - var ends = parts[1].split(','); //grab the infinitive + Object.defineProperty(this, 'found', { + get: function get() { + return _this.list.length > 0; + } + }); //'length' getter - var inf = prefix + ends[0]; + Object.defineProperty(this, 'length', { + get: function get() { + return _this.list.length; + } + }); // this is way easier than .constructor.name... - if (ends[0] === '_') { - inf = prefix; + Object.defineProperty(this, 'isA', { + get: function get() { + return 'Doc'; + } + }); } + /** run part-of-speech tagger on all results*/ - h[inf] = {}; //we did the infinitive, now do the rest: - for (var i = 1; i < forms.length; i++) { - var word = parts[0] + ends[i]; - - if (ends[i] === '_') { - word = parts[0]; - } - - if (ends[i]) { - h[inf][forms[i]] = word; + _createClass(Doc, [{ + key: "tagger", + value: function tagger() { + return _02Tagger(this); } - } + /** pool is stored on phrase objects */ - return h; - }, {}); -}; + }, { + key: "pool", + value: function pool() { + if (this.list.length > 0) { + return this.list[0].pool; + } -module.exports = unpackVerbs; + return this.all().list[0].pool; + } + }]); -},{}],223:[function(_dereq_,module,exports){ -'use strict'; + return Doc; + }(); + /** create a new Document object */ -var unpack = { - words: _dereq_('efrt-unpack'), - plurals: _dereq_('./plurals'), - conjugations: _dereq_('./conjugations'), - keyValue: _dereq_('./key-value') -}; -/* - == supported plugin fields == - name - words - efrt packed - tags - stringified - regex - key-value - patterns - key-value - plurals - plural-unpack - conjugations - conjugation-unpack -*/ -var unpackPlugin = function unpackPlugin(str) { - var obj = str; + Doc.prototype.buildFrom = function (list) { + list = list.map(function (p) { + return p.clone(true); + }); // new this.constructor() - if (typeof str === 'string') { - obj = JSON.parse(str); - } //words is packed with efrt + var doc = new Doc(list, this, this.world); + return doc; + }; + /** create a new Document from plaintext. */ - if (obj.words && typeof obj.words === 'string') { - obj.words = unpack.words(obj.words); - } //patterns is pivoted as key-value + Doc.prototype.fromText = function (str) { + var list = _01Tokenizer.fromText(str, this.world, this.pool()); + return this.buildFrom(list); + }; + Object.assign(Doc.prototype, methods$8.misc); + Object.assign(Doc.prototype, methods$8.selections); //add sub-classes - if (obj.patterns) { - obj.patterns = unpack.keyValue(obj.patterns); - } //regex, too + Subset(Doc); //aliases + var aliases$1 = { + untag: 'unTag', + and: 'match', + notIf: 'ifNo', + only: 'if', + onlyIf: 'if' + }; + Object.keys(aliases$1).forEach(function (k) { + return Doc.prototype[k] = Doc.prototype[aliases$1[k]]; + }); + var Doc_1 = Doc; - if (obj.regex) { - obj.regex = unpack.keyValue(obj.regex); - } //plurals is packed in a ad-hoc way + var world = new World_1(); + /** parse and tag text into a compromise object */ + var nlp = function nlp() { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var lexicon = arguments.length > 1 ? arguments[1] : undefined; - if (obj.plurals && typeof obj.plurals === 'string') { - obj.plurals = unpack.plurals(obj.plurals); - } //conjugations is packed in another ad-hoc way + if (lexicon) { + world.addWords(lexicon); + } + var list = _01Tokenizer.fromText(text, world); + var doc = new Doc_1(list, null, world); + doc.tagger(); + return doc; + }; + /** parse text into a compromise object, without running POS-tagging */ - if (obj.conjugations && typeof obj.conjugations === 'string') { - obj.conjugations = unpack.conjugations(obj.conjugations); - } - return obj; -}; + nlp.tokenize = function () { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var lexicon = arguments.length > 1 ? arguments[1] : undefined; -module.exports = unpackPlugin; + if (lexicon) { + world.addWords(lexicon); + } -},{"./conjugations":222,"./key-value":224,"./plurals":225,"efrt-unpack":1}],224:[function(_dereq_,module,exports){ -'use strict'; //pivot k:[val,val] -> val:k, val:k + var list = _01Tokenizer.fromText(text, world); + var doc = new Doc_1(list, null, world); + return doc; + }; + /** mix in a compromise-plugin */ -var keyValue = function keyValue(obj) { - var keys = Object.keys(obj); - var isCompressed = true; - if (keys[0] && typeof obj[keys[0]] === 'string') { - isCompressed = false; - } + nlp.extend = function (fn) { + fn(Doc_1, world); + return this; + }; + /** make a deep-copy of the library state */ - return keys.reduce(function (h, k) { - if (isCompressed === true) { - var arr = obj[k]; - arr.forEach(function (a) { - if (h[a]) { - //convert val to an array - if (typeof h[a] === 'string') { - h[a] = [h[a]]; - } //add it + nlp.clone = function () { + world = world.clone(); + return this; + }; + /** re-generate a Doc object from .json() results */ - h[a].push(k); - } else { - h[a] = k; - } - }); - } else { - h[k] = obj[k]; - } - return h; - }, {}); -}; + nlp.load = function (json) { + var list = _01Tokenizer.fromJSON(json, world); + return new Doc_1(list, null, world); + }; + /** log our decision-making for debugging */ -module.exports = keyValue; -},{}],225:[function(_dereq_,module,exports){ -'use strict'; + nlp.verbose = function () { + var bool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + world.verbose(bool); + return this; + }; + /** current version of the library */ -var unpackPlurals = function unpackPlurals(str) { - return str.split(/,/g).reduce(function (h, s) { - var arr = s.split(/\|/g); - if (arr.length === 3) { - h[arr[0] + arr[1]] = arr[0] + arr[2]; - } else if (arr.length === 2) { - h[arr[0]] = arr[0] + arr[1]; - } else { - h[arr[0]] = arr[0]; - } + nlp.version = _version; // alias - return h; - }, {}); -}; + nlp["import"] = nlp.load; + var src = nlp; -module.exports = unpackPlurals; + return src; -},{}]},{},[4])(4) -}); +}))); +//# sourceMappingURL=compromise.js.map diff --git a/builds/compromise.js.map b/builds/compromise.js.map new file mode 100644 index 000000000..6f5669a27 --- /dev/null +++ b/builds/compromise.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise.js","sources":["../src/Term/_id.js","../src/Term/normalize/unicode.js","../src/Term/normalize/isAcronym.js","../src/Term/normalize/clean.js","../src/Term/normalize/reduce.js","../src/Term/parse.js","../src/Term/methods/01-case.js","../src/Term/methods/02-punctuation.js","../src/Term/methods/_doesMatch.js","../src/Term/methods/03-misc.js","../src/Term/methods/04-text.js","../src/Term/methods/_bestTag.js","../src/Term/methods/05-json.js","../src/Term/methods/index.js","../src/Term/tag/fns.js","../src/Term/tag/add.js","../src/Term/tag/unTag.js","../src/Term/tag/canBe.js","../src/Term/tag/index.js","../src/Term/Term.js","../src/Phrase/methods/01-utils.js","../src/Phrase/methods/02-text.js","../src/Phrase/methods/03-change.js","../src/Phrase/insert/append.js","../src/Phrase/insert/prepend.js","../src/Phrase/insert/delete.js","../src/Phrase/methods/04-insert.js","../src/Phrase/methods/05-json.js","../src/Phrase/methods/06-lookahead.js","../src/Phrase/methods/index.js","../src/Phrase/match/02-failFast.js","../src/Phrase/match/03-tryMatch.js","../src/Doc/match/parseToken.js","../src/Doc/match/syntax.js","../src/Phrase/match/01-matchAll.js","../src/Phrase/match/not.js","../src/Phrase/match/index.js","../src/Phrase/Phrase.js","../src/01-tokenizer/Pool.js","../src/01-tokenizer/01-sentences.js","../src/01-tokenizer/02-words.js","../src/01-tokenizer/index.js","../src/_version.js","../src/World/_data.js","../src/World/tags/tags/nouns.js","../src/World/tags/tags/verbs.js","../src/World/tags/tags/values.js","../src/World/tags/tags/misc.js","../src/World/tags/inference/_color.js","../src/World/tags/inference/_isA.js","../src/World/tags/inference/_notA.js","../src/World/tags/inference/_lineage.js","../src/World/tags/inference/index.js","../src/World/tags/index.js","../node_modules/efrt-unpack/efrt-unpack.min.js","../src/World/addWords.js","../src/World/addIrregulars.js","../src/World/data/misc.js","../src/World/data/plurals.js","../src/World/data/conjugations.js","../src/transforms/conjugate/suffixes.js","../src/transforms/conjugate/01-suffixes.js","../src/transforms/conjugate/02-generic.js","../src/transforms/conjugate/index.js","../src/transforms/adjectives/toSuperlative.js","../src/transforms/adjectives/toComparative.js","../src/transforms/adjectives/index.js","../src/transforms/toPlural/_rules.js","../src/transforms/toPlural/index.js","../src/transforms/toSingular/_rules.js","../src/transforms/toSingular/index.js","../src/transforms/toInfinitive/_transform.js","../src/transforms/toInfinitive/_guess.js","../src/transforms/toInfinitive/index.js","../src/World/World.js","../src/Doc/methods/01-utils.js","../src/Doc/methods/02-accessors.js","../src/Doc/methods/03-match.js","../src/Doc/methods/_setTag.js","../src/Doc/methods/04-tag.js","../src/Doc/methods/05-loops.js","../src/Doc/methods/06-lookup.js","../src/Doc/methods/insert/01-replace.js","../src/Doc/methods/insert/02-insert.js","../src/Doc/methods/output/01-text.js","../src/Doc/methods/output/02-json.js","../src/world/tags/tags/nouns.js","../src/world/tags/tags/verbs.js","../src/world/tags/tags/values.js","../src/world/tags/tags/misc.js","../src/world/tags/inference/_color.js","../src/world/tags/inference/_isA.js","../src/world/tags/inference/_notA.js","../src/world/tags/inference/_lineage.js","../src/world/tags/inference/index.js","../src/world/tags/index.js","../src/Doc/methods/_debug.js","../src/Doc/methods/output/_topk.js","../src/Doc/methods/output/03-out.js","../src/Doc/methods/output/04-export.js","../src/Doc/methods/transform/01-sort.js","../src/Doc/methods/transform/_methods.js","../src/Doc/methods/transform/02-normalize.js","../src/Doc/methods/transform/03-split.js","../src/Doc/methods/transform/04-case.js","../src/Doc/methods/transform/05-whitespace.js","../src/Doc/methods/transform/06-join.js","../src/Doc/methods/transform/07-contract.js","../src/Doc/methods/index.js","../src/Subset/_simple.js","../src/02-tagger/01-init/01-lexicon.js","../src/02-tagger/01-init/02-punctuation.js","../src/02-tagger/01-init/data/startsWith.js","../src/02-tagger/01-init/03-prefixes.js","../src/02-tagger/01-init/data/endsWith.js","../src/02-tagger/01-init/data/suffixMap.js","../src/02-tagger/01-init/04-suffixes.js","../src/02-tagger/01-init/data/emoticons.js","../src/02-tagger/01-init/05-emoji.js","../src/02-tagger/01-init/index.js","../src/02-tagger/02-fallbacks/data/markov.js","../src/02-tagger/02-fallbacks/01-neighbours.js","../src/02-tagger/02-fallbacks/02-case.js","../src/02-tagger/02-fallbacks/03-stem.js","../src/02-tagger/02-fallbacks/data/isPlural.js","../src/02-tagger/02-fallbacks/04-plurals.js","../src/02-tagger/02-fallbacks/data/organizations.js","../src/02-tagger/02-fallbacks/05-organizations.js","../src/02-tagger/02-fallbacks/index.js","../src/02-tagger/03-contractions/01-negative.js","../src/02-tagger/03-contractions/02-simple.js","../src/02-tagger/03-contractions/03-irregulars.js","../src/02-tagger/03-contractions/04-possessive.js","../src/02-tagger/03-contractions/05-perfectTense.js","../src/02-tagger/03-contractions/06-ranges.js","../src/02-tagger/03-contractions/index.js","../src/02-tagger/04-correction/fixMisc.js","../src/02-tagger/04-correction/fixThe.js","../src/02-tagger/04-correction/fixNouns.js","../src/02-tagger/04-correction/fixPerson.js","../src/02-tagger/04-correction/fixVerb.js","../src/02-tagger/04-correction/fixAdjective.js","../src/02-tagger/04-correction/fixValue.js","../src/02-tagger/04-correction/fixDates.js","../src/02-tagger/04-correction/index.js","../src/02-tagger/index.js","../src/Subset/Abbreviations.js","../src/Subset/Acronyms.js","../src/Subset/Clauses.js","../src/Subset/Contractions.js","../src/Subset/Lists.js","../src/Subset/Nouns/plural/hasPlural.js","../src/Subset/Nouns/getArticle.js","../src/Subset/Nouns/plural/isPlural/_rules.js","../src/Subset/Nouns/plural/isPlural/index.js","../src/Subset/Nouns/toPossessive.js","../src/Subset/Nouns/parse.js","../src/Subset/Nouns/methods.js","../src/Subset/Nouns/index.js","../src/Subset/Parentheses.js","../src/Subset/Possessives.js","../src/Subset/Quotations.js","../src/Subset/Verbs/toInfinitive/index.js","../src/Subset/Verbs/isPlural.js","../src/Subset/Verbs/toNegative.js","../src/Subset/Verbs/parse.js","../src/Subset/Verbs/conjugate/toBe.js","../src/Subset/Verbs/conjugate/index.js","../src/Subset/Verbs/methods.js","../src/Subset/Verbs/index.js","../src/Subset/People.js","../src/Subset/index.js","../src/Doc/Doc.js","../src/index.js"],"sourcesContent":["//this is a not-well-thought-out way to reduce our dependence on `object===object` stuff\nconst chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('')\n\n//generates a unique id for this term\nfunction makeId(str) {\n str = str || '_'\n let text = str + '-'\n for (let i = 0; i < 7; i++) {\n text += chars[Math.floor(Math.random() * chars.length)]\n }\n return text\n}\n\nmodule.exports = makeId\n","//a hugely-ignorant, and widely subjective transliteration of latin, cryllic, greek unicode characters to english ascii.\n//approximate visual (not semantic or phonetic) relationship between unicode and ascii characters\n//http://en.wikipedia.org/wiki/List_of_Unicode_characters\n//https://docs.google.com/spreadsheet/ccc?key=0Ah46z755j7cVdFRDM1A2YVpwa1ZYWlpJM2pQZ003M0E\nlet compact = {\n '!': '¡',\n '?': '¿Ɂ',\n '\"': '“”\"❝❞',\n \"'\": '‘‛❛❜',\n '-': '—–',\n a: 'ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАадѦѧӐӑӒӓƛɅæ',\n b: 'ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬвъьѢѣҌҍ',\n c: '¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾСсєҀҁҪҫ',\n d: 'ÐĎďĐđƉƊȡƋƌǷ',\n e: 'ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ',\n f: 'ƑƒϜϝӺӻҒғſ',\n g: 'ĜĝĞğĠġĢģƓǤǥǦǧǴǵ',\n h: 'ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ',\n I: 'ÌÍÎÏ',\n i: 'ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії',\n j: 'ĴĵǰȷɈɉϳЈј',\n k: 'ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ',\n l: 'ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ',\n m: 'ΜϺϻМмӍӎ',\n n: 'ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ',\n o: 'ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ',\n p: 'ƤƿΡρϷϸϼРрҎҏÞ',\n q: 'Ɋɋ',\n r: 'ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ',\n s: 'ŚśŜŝŞşŠšƧƨȘșȿЅѕ',\n t: 'ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮТт',\n u: 'µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύ',\n v: 'νѴѵѶѷ',\n w: 'ŴŵƜωώϖϢϣШЩшщѡѿ',\n x: '×ΧχϗϰХхҲҳӼӽӾӿ',\n y: 'ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ',\n z: 'ŹźŻżŽžƩƵƶȤȥɀΖζ',\n}\n//decompress data into two hashes\nlet unicode = {}\nObject.keys(compact).forEach(function(k) {\n compact[k].split('').forEach(function(s) {\n unicode[s] = k\n })\n})\n\nconst killUnicode = str => {\n let chars = str.split('')\n chars.forEach((s, i) => {\n if (unicode[s]) {\n chars[i] = unicode[s]\n }\n })\n return chars.join('')\n}\nmodule.exports = killUnicode\n// console.log(killUnicode('bjŏȒk—Ɏó'));\n","const periodAcronym = /([A-Z]\\.)+[A-Z]?,?$/\nconst oneLetterAcronym = /^[A-Z]\\.,?$/\nconst noPeriodAcronym = /[A-Z]{2,}('s|,)?$/\nconst lowerCaseAcronym = /([a-z]\\.){2,}[a-z]\\.?$/\n\nconst isAcronym = function(str) {\n //like N.D.A\n if (periodAcronym.test(str) === true) {\n return true\n }\n //like c.e.o\n if (lowerCaseAcronym.test(str) === true) {\n return true\n }\n //like 'F.'\n if (oneLetterAcronym.test(str) === true) {\n return true\n }\n //like NDA\n if (noPeriodAcronym.test(str) === true) {\n return true\n }\n return false\n}\nmodule.exports = isAcronym\n","const killUnicode = require('./unicode')\nconst isAcronym = require('./isAcronym')\nconst hasSlash = /[a-z\\u00C0-\\u00FF] ?\\/ ?[a-z\\u00C0-\\u00FF]/\n\n/** some basic operations on a string to reduce noise */\nconst clean = function(str) {\n str = str || ''\n str = str.toLowerCase()\n str = str.trim()\n let original = str\n //(very) rough ASCII transliteration - bjŏrk -> bjork\n str = killUnicode(str)\n //rough handling of slashes - 'see/saw'\n if (hasSlash.test(str) === true) {\n str = str.replace(/\\/.*/, '')\n }\n //#tags, @mentions\n str = str.replace(/^[#@]/, '')\n //punctuation\n str = str.replace(/[,;.!?]+$/, '')\n // coerce single curly quotes\n str = str.replace(/[\\u0027\\u0060\\u00B4\\u2018\\u2019\\u201A\\u201B\\u2032\\u2035\\u2039\\u203A]+/g, \"'\")\n // coerce double curly quotes\n str = str.replace(\n /[\\u0022\\u00AB\\u00BB\\u201C\\u201D\\u201E\\u201F\\u2033\\u2034\\u2036\\u2037\\u2E42\\u301D\\u301E\\u301F\\uFF02]+/g,\n '\"'\n )\n //coerce Unicode ellipses\n str = str.replace(/\\u2026/g, '...')\n //en-dash\n str = str.replace(/\\u2013/g, '-')\n //lookin'->looking (make it easier for conjugation)\n if (/[a-z][^aeiou]in['’]$/.test(str) === true) {\n str = str.replace(/in['’]$/, 'ing')\n }\n //turn re-enactment to reenactment\n if (/^(re|un)-?[^aeiou]./.test(str) === true) {\n str = str.replace('-', '')\n }\n //strip leading & trailing grammatical punctuation\n if (/^[:;]/.test(str) === false) {\n str = str.replace(/\\.{3,}$/g, '')\n str = str.replace(/[\",\\.!:;\\?\\)]+$/g, '')\n str = str.replace(/^['\"\\(]+/g, '')\n }\n //do this again..\n str = str.trim()\n //oh shucks,\n if (str === '') {\n str = original\n }\n //compact acronyms\n if (isAcronym(str)) {\n str = str.replace(/\\./g, '')\n }\n //nice-numbers\n str = str.replace(/([0-9]),([0-9])/g, '$1$2')\n return str\n}\n\nmodule.exports = clean\n// console.log(normalize('Dr. V Cooper'));\n","/** reduced is one step further than clean */\nconst reduced = function(str) {\n // remove apostrophes\n str = str.replace(/['’]s$/, '')\n str = str.replace(/s['’]$/, 's')\n return str\n}\nmodule.exports = reduced\n","const normalize = require('./normalize/clean')\nconst reduce = require('./normalize/reduce')\n// basically, tokenize for terms.\n\n//all punctuation marks, from https://en.wikipedia.org/wiki/Punctuation\n//we have slightly different rules for start/end - like #hashtags.\nconst startings = /^[ \\n\\t\\.’'\\[\\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\\-?‘’;\\/⁄·\\&*\\•^†‡°¡¿※№÷׺ª%‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\\u0022|\\uFF02|\\u0027|\\u201C|\\u2018|\\u201F|\\u201B|\\u201E|\\u2E42|\\u201A|\\u00AB|\\u2039|\\u2035|\\u2036|\\u2037|\\u301D|\\u0060|\\u301F]+/\nconst endings = /[ \\n\\t\\.’'\\[\\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\\-?‘’;\\/⁄·\\&*@\\•^†‡°¡¿※#№÷׺ª‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\\u0022|\\uFF02|\\u0027|\\u201D|\\u2019|\\u201D|\\u2019|\\u201D|\\u201D|\\u2019|\\u00BB|\\u203A|\\u2032|\\u2033|\\u2034|\\u301E|\\u00B4|\\u301E]+$/\n\n//money = ₵¢₡₢$₫₯֏₠€ƒ₣₲₴₭₺₾ℳ₥₦₧₱₰£៛₽₹₨₪৳₸₮₩¥\nconst hasSlash = /\\//\nconst hasApostrophe = /['’]/\nconst minusNumber = /^[-+\\.][0-9]/\n\n/** turn given text into a parsed-up object\n * seperate the 'meat' of the word from the whitespace+punctuation\n */\nconst parseTerm = str => {\n let original = str\n let pre = ''\n let post = ''\n str = str.replace(startings, found => {\n pre = found\n // support '-40'\n if ((pre === '-' || pre === '+' || pre === '.') && minusNumber.test(str)) {\n pre = ''\n return found\n }\n return ''\n })\n str = str.replace(endings, found => {\n post = found\n // keep s-apostrophe - \"flanders'\" or \"chillin'\"\n if (hasApostrophe.test(found) && /[sn]['’]$/.test(original) && hasApostrophe.test(pre) === false) {\n post = post.replace(hasApostrophe, '')\n return `'`\n }\n return ''\n })\n //we went too far..\n if (str === '') {\n // do a very mild parse, and hope for the best.\n original = original.replace(/ *$/, after => {\n post = after || ''\n return ''\n })\n str = original\n pre = ''\n post = post\n }\n\n // create the various forms of our text,\n let clean = normalize(str)\n const parsed = {\n text: str,\n clean: clean,\n reduced: reduce(clean),\n pre: pre,\n post: post,\n }\n // support aliases for slashes\n if (hasSlash.test(str)) {\n str.split(hasSlash).forEach(word => {\n parsed.alias = parsed.alias || {}\n parsed.alias[word.trim()] = true\n })\n }\n return parsed\n}\nmodule.exports = parseTerm\n","const titleCase = /^[A-Z][a-z'\\u00C0-\\u00FF]/\nconst upperCase = /^[A-Z]+s?$/\n\n/** convert all text to uppercase */\nexports.toUpperCase = function() {\n this.text = this.text.toUpperCase()\n return this\n}\n\n/** convert all text to lowercase */\nexports.toLowerCase = function() {\n this.text = this.text.toLowerCase()\n return this\n}\n\n/** only set the first letter to uppercase\n * leave any existing uppercase alone\n */\nexports.toTitleCase = function() {\n this.text = this.text.replace(/^ *[a-z\\u00C0-\\u00FF]/, x => x.toUpperCase()) //support unicode?\n return this\n}\n\n/** if all letters are uppercase */\nexports.isUpperCase = function() {\n return upperCase.test(this.text)\n}\n/** if the first letter is uppercase, and the rest are lowercase */\nexports.isTitleCase = function() {\n return titleCase.test(this.text)\n}\nexports.titleCase = exports.isTitleCase\n","// these methods are called with '@hasComma' in the match syntax\n// various unicode quotation-mark formats\nconst startQuote =\n '(\\u0022|\\uFF02|\\u0027|\\u201C|\\u2018|\\u201F|\\u201B|\\u201E|\\u2E42|\\u201A|\\u00AB|\\u2039|\\u2035|\\u2036|\\u2037|\\u301D|\\u0060|\\u301F)'\nconst endQuote =\n '(\\u0022|\\uFF02|\\u0027|\\u201D|\\u2019|\\u201D|\\u2019|\\u201D|\\u201D|\\u2019|\\u00BB|\\u203A|\\u2032|\\u2033|\\u2034|\\u301E|\\u00B4|\\u301E)'\n\n/** search the term's 'post' punctuation */\nexports.hasPost = function(punct) {\n return this.post.indexOf(punct) !== -1\n}\n/** search the term's 'pre' punctuation */\nexports.hasPre = function(punct) {\n return this.pre.indexOf(punct) !== -1\n}\n\n/** does it have a quotation symbol? */\nexports.hasQuote = function() {\n return startQuote.test(this.pre) || endQuote.test(this.post)\n}\n\n/** does it have a comma? */\nexports.hasComma = function() {\n return this.hasPost(',')\n}\n\n/** does it end in a period? */\nexports.hasPeriod = function() {\n return this.hasPost('.') === true && this.hasPost('...') === false\n}\n\n/** does it end in an exclamation */\nexports.hasExclamation = function() {\n return this.hasPost('!')\n}\n\n/** does it end with a question mark? */\nexports.hasQuestionMark = function() {\n return this.hasPost('?') || this.hasPost('¿')\n}\n\n/** is there a ... at the end? */\nexports.hasEllipses = function() {\n return this.hasPost('..') || this.hasPost('…')\n}\n\n/** is there a semicolon after this word? */\nexports.hasSemicolon = function() {\n return this.hasPost(';')\n}\n\n/** is there a slash '/' in this word? */\nexports.hasSlash = function() {\n return /\\//.test(this.text)\n}\n\n/** a hyphen connects two words like-this */\nexports.hasHyphen = function() {\n const hyphen = /(-|–|—)/\n return hyphen.test(this.post) || hyphen.test(this.pre)\n}\n/** a dash separates words - like that */\nexports.hasDash = function() {\n const hyphen = / (-|–|—) /\n return hyphen.test(this.post) || hyphen.test(this.pre)\n}\n\n/** is it multiple words combinded */\nexports.hasContraction = function() {\n return Boolean(this.implicit)\n}\n\n/** try to sensibly put this punctuation mark into the term */\nexports.addPunctuation = function(punct) {\n // dont add doubles\n if (punct === ',' || punct === ';') {\n this.post = this.post.replace(punct, '')\n }\n this.post = punct + this.post\n return this\n}\n","//declare it up here\nlet wrapMatch = function() {}\n\n/** ignore optional/greedy logic, straight-up term match*/\nconst doesMatch = function(t, reg, index, length) {\n // support id matches\n if (reg.id === t.id) {\n return true\n }\n // support '.'\n if (reg.anything === true) {\n return true\n }\n // support '^' (in parentheses)\n if (reg.start === true && index !== 0) {\n return false\n }\n // support '$' (in parentheses)\n if (reg.end === true && index !== length - 1) {\n return false\n }\n //support a text match\n if (reg.word !== undefined) {\n //match contractions\n if (t.implicit !== null && t.implicit === reg.word) {\n return true\n }\n // term aliases for slashes and things\n if (t.alias !== undefined && t.alias.hasOwnProperty(reg.word)) {\n return true\n }\n // support ~ match\n if (reg.soft === true && reg.word === t.root) {\n return true\n }\n //match either .clean or .text\n return reg.word === t.clean || reg.word === t.text || reg.word === t.reduced\n }\n //support #Tag\n if (reg.tag !== undefined) {\n return t.tags[reg.tag] === true\n }\n //support @method\n if (reg.method !== undefined) {\n if (typeof t[reg.method] === 'function' && t[reg.method]() === true) {\n return true\n }\n return false\n }\n //support /reg/\n if (reg.regex !== undefined) {\n return reg.regex.test(t.clean)\n }\n //support (one|two)\n if (reg.choices !== undefined) {\n // try to support && operator\n if (reg.operator === 'and') {\n // must match them all\n return reg.choices.every(r => wrapMatch(t, r, index, length))\n }\n // or must match one\n return reg.choices.some(r => wrapMatch(t, r, index, length))\n }\n return false\n}\n\n// wrap result for !negative match logic\nwrapMatch = function(t, reg, index, length) {\n let result = doesMatch(t, reg, index, length)\n if (reg.negative === true) {\n return !result\n }\n return result\n}\n\nmodule.exports = wrapMatch\n","const doesMatch = require('./_doesMatch')\nconst isAcronym = require('../normalize/isAcronym')\n\n// these tags aren't juicy-enough\nconst boring = {}\n\n/** check a match object against this term */\nexports.doesMatch = function(reg, index, length) {\n return doesMatch(this, reg, index, length)\n}\n\n/** does this term look like an acronym? */\nexports.isAcronym = function() {\n return isAcronym(this.text)\n}\n\n/** is this term implied by a contraction? */\nexports.isImplicit = function() {\n return this.text === '' && Boolean(this.implicit)\n}\n\n/** does the term have at least one good tag? */\nexports.isKnown = function() {\n return Object.keys(this.tags).some(t => boring[t] !== true)\n}\n\n/** cache the root property of the term */\nexports.setRoot = function(world) {\n let transform = world.transforms\n let str = this.implicit || this.clean\n if (this.tags.Plural) {\n str = transform.toSingular(str, world)\n }\n if (this.tags.Verb && !this.tags.Negative && !this.tags.Infinitive) {\n let tense = null\n if (this.tags.PastTense) {\n tense = 'PastTense'\n } else if (this.tags.Gerund) {\n tense = 'Gerund'\n } else if (this.tags.PresentTense) {\n tense = 'PresentTense'\n } else if (this.tags.Participle) {\n tense = 'Participle'\n } else if (this.tags.Actor) {\n tense = 'Actor'\n }\n str = transform.toInfinitive(str, world, tense)\n }\n this.root = str\n}\n","const killUnicode = require('../normalize/unicode')\nconst hasSpace = /[\\s-]/\nconst isUpperCase = /^[A-Z-]+$/\n\n// const titleCase = str => {\n// return str.charAt(0).toUpperCase() + str.substr(1)\n// }\n\n/** return various text formats of this term */\nexports.textOut = function(options, showPre, showPost) {\n options = options || {}\n let word = this.text\n let before = this.pre\n let after = this.post\n\n // -word-\n if (options.reduced === true) {\n word = this.reduced || ''\n }\n if (options.root === true) {\n word = this.root || ''\n }\n if (options.implicit === true && this.implicit) {\n word = this.implicit || ''\n }\n if (options.normal === true) {\n word = this.clean || this.text || ''\n }\n if (options.root === true) {\n word = this.root || this.reduced || ''\n }\n if (options.unicode === true) {\n word = killUnicode(word)\n }\n // cleanup case\n if (options.titlecase === true) {\n if (this.tags.ProperNoun && !this.titleCase()) {\n // word = titleCase(word)\n } else if (this.tags.Acronym) {\n word = word.toUpperCase() //uppercase acronyms\n } else if (isUpperCase.test(word) && !this.tags.Acronym) {\n // lowercase everything else\n word = word.toLowerCase()\n }\n }\n if (options.lowercase === true) {\n word = word.toLowerCase()\n }\n // remove the '.'s from 'F.B.I.' (safely)\n if (options.acronyms === true && this.tags.Acronym) {\n word = word.replace(/\\./g, '')\n }\n\n // -before/after-\n if (options.whitespace === true || options.root) {\n before = ''\n after = ' '\n if ((hasSpace.test(this.post) === false || options.last) && !this.implicit) {\n after = ''\n }\n }\n if (options.punctuation === true && !options.root) {\n //normalized end punctuation\n if (this.hasPost('.') === true) {\n after = '.' + after\n } else if (this.hasPost('?') === true) {\n after = '?' + after\n } else if (this.hasPost('!') === true) {\n after = '!' + after\n } else if (this.hasPost(',') === true) {\n after = ',' + after\n } else if (this.hasEllipses() === true) {\n after = '...' + after\n }\n }\n if (showPre !== true) {\n before = ''\n }\n if (showPost !== true) {\n // let keep = after.match(/\\)/) || ''\n after = '' //keep //after.replace(/[ .?!,]+/, '')\n }\n // remove the '.' from 'Mrs.' (safely)\n if (options.abbreviations === true && this.tags.Abbreviation) {\n after = after.replace(/^\\./, '')\n }\n return before + word + after\n}\n","const boringTags = {\n Auxiliary: 1,\n Possessive: 1,\n}\n\n/** a subjective ranking of tags kinda tfidf-based */\nconst rankTags = function(term, world) {\n let tags = Object.keys(term.tags)\n const tagSet = world.tags\n tags = tags.sort((a, b) => {\n //bury the tags we dont want\n if (boringTags[b] || !tagSet[b]) {\n return -1\n }\n // unknown tags are interesting\n if (!tagSet[b]) {\n return 1\n }\n if (!tagSet[a]) {\n return 0\n }\n // then sort by #of parent tags (most-specific tags first)\n if (tagSet[a].lineage.length > tagSet[b].lineage.length) {\n return 1\n }\n if (tagSet[a].isA.length > tagSet[b].isA.length) {\n return -1\n }\n return 0\n })\n return tags\n}\nmodule.exports = rankTags\n","const rankTags = require('./_bestTag')\n\nconst jsonDefault = {\n text: true,\n tags: true,\n implicit: true,\n\n clean: false,\n id: false,\n index: false,\n offset: false,\n whitespace: false,\n bestTag: false,\n}\n\n/** return various metadata for this term */\nexports.json = function(options, world) {\n options = options || {}\n options = Object.assign({}, jsonDefault, options)\n let result = {}\n\n // default on\n if (options.text) {\n result.text = this.text\n }\n if (options.normal) {\n result.normal = this.normal\n }\n\n if (options.tags) {\n result.tags = Object.keys(this.tags)\n }\n\n // default off\n if (options.clean) {\n result.clean = this.clean\n }\n if (options.id || options.offset) {\n result.id = this.id\n }\n if (options.implicit && this.implicit !== null) {\n result.implicit = this.implicit\n }\n if (options.whitespace) {\n result.pre = this.pre\n result.post = this.post\n }\n if (options.bestTag) {\n result.bestTag = rankTags(this, world)[0]\n }\n\n return result\n}\n","module.exports = Object.assign(\n {},\n require('./01-case'),\n require('./02-punctuation'),\n require('./03-misc'),\n require('./04-text'),\n require('./05-json')\n)\n","/** add spaces at the end */\nconst padEnd = function(str, width) {\n str = str.toString()\n while (str.length < width) {\n str += ' '\n }\n return str\n}\n\n/** output for verbose-mode */\nexports.logTag = function(t, tag, reason) {\n let log = '\\x1b[33m' + padEnd(t.clean, 15) + '\\x1b[0m + \\x1b[32m' + tag + '\\x1b[0m '\n if (reason) {\n log = padEnd(log, 35) + ' ' + reason + ''\n }\n console.log(log)\n}\n\n/** output for verbose mode */\nexports.logUntag = function(t, tag, reason) {\n let log = '\\x1b[33m' + padEnd(t.clean, 3) + ' \\x1b[31m - #' + tag + '\\x1b[0m '\n if (reason) {\n log = padEnd(log, 35) + ' ' + reason\n }\n console.log(log)\n}\n\nexports.isArray = function(arr) {\n return Object.prototype.toString.call(arr) === '[object Array]'\n}\n\nexports.titleCase = str => {\n return str.charAt(0).toUpperCase() + str.substr(1)\n}\n","const fns = require('./fns')\n\n/** add a tag, and its descendents, to a term */\nconst addTag = function(t, tag, reason, world) {\n let tagset = world.tags\n //support '.' or '-' notation for skipping the tag\n if (tag === '' || tag === '.' || tag === '-') {\n return\n }\n if (tag[0] === '#') {\n tag = tag.replace(/^#/, '')\n }\n tag = fns.titleCase(tag)\n //if we already got this one\n if (t.tags[tag] === true) {\n return\n }\n // log it?\n const isVerbose = world.isVerbose()\n if (isVerbose === true) {\n fns.logTag(t, tag, reason)\n }\n //add tag\n t.tags[tag] = true //whee!\n\n //check tagset for any additional things to do...\n if (tagset.hasOwnProperty(tag) === true) {\n //add parent Tags\n tagset[tag].isA.forEach(down => {\n t.tags[down] = true\n if (isVerbose === true) {\n fns.logTag(t, '→ ' + down)\n }\n })\n //remove any contrary tags\n t.unTag(tagset[tag].notA, '←', world)\n }\n}\n\n/** support an array of tags */\nconst addTags = function(term, tags, reason, world) {\n if (fns.isArray(tags) === true) {\n tags.forEach(tag => addTag(term, tag, reason, world))\n } else {\n addTag(term, tags, reason, world)\n }\n}\nmodule.exports = addTags\n","const fns = require('./fns')\n\n/** remove this tag, and its descentents from the term */\nconst unTag = function(t, tag, reason, world) {\n const isVerbose = world.isVerbose()\n //support '*' for removing all tags\n if (tag === '*') {\n t.tags = {}\n return t\n }\n // remove the tag\n if (t.tags[tag] === true && t.tags.hasOwnProperty(tag) === true) {\n delete t.tags[tag]\n //log in verbose-mode\n if (isVerbose === true) {\n fns.logUntag(t, tag, reason)\n }\n }\n //delete downstream tags too\n const tagset = world.tags\n if (tagset[tag]) {\n let lineage = tagset[tag].lineage\n for (let i = 0; i < lineage.length; i++) {\n // unTag(t, also[i], ' - - - ', world) //recursive\n if (t.tags[lineage[i]] === true) {\n delete t.tags[lineage[i]]\n if (isVerbose === true) {\n fns.logUntag(t, ' - ' + lineage[i])\n }\n }\n }\n }\n return t\n}\n\n//handle an array of tags\nconst untagAll = function(term, tags, reason, world) {\n if (fns.isArray(tags) === true) {\n tags.forEach(tag => unTag(term, tag, reason, world))\n } else {\n unTag(term, tags, reason, world)\n }\n}\nmodule.exports = untagAll\n","'use strict'\n\n//recursively-check compatibility of this tag and term\nconst canBe = function(term, tag, world) {\n const tagset = world.tags\n // cleanup tag\n if (tag[0] === '#') {\n tag = tag.replace(/^#/, '')\n }\n //fail-fast\n if (tagset[tag] === undefined) {\n return true\n }\n //loop through tag's contradictory tags\n let enemies = tagset[tag].notA || []\n for (let i = 0; i < enemies.length; i++) {\n if (term.tags[enemies[i]] === true) {\n return false\n }\n }\n if (tagset[tag].isA !== undefined) {\n return canBe(term, tagset[tag].isA, world) //recursive\n }\n return true\n}\n\nmodule.exports = canBe\n","const add = require('./add')\nconst unTag = require('./unTag')\nconst canBe = require('./canBe')\n\n/** add a tag or tags, and their descendents to this term\n * @param {string | string[]} tags - a tag or tags\n * @param {string?} [reason] a clue for debugging\n */\nexports.tag = function(tags, reason, world) {\n add(this, tags, reason, world)\n return this\n}\n\n/** only tag this term if it's consistent with it's current tags */\nexports.tagSafe = function(tags, reason, world) {\n if (canBe(this, tags, world)) {\n add(this, tags, reason, world)\n }\n return this\n}\n\n/** remove a tag or tags, and their descendents from this term\n * @param {string | string[]} tags - a tag or tags\n * @param {string?} [reason] a clue for debugging\n */\nexports.unTag = function(tags, reason, world) {\n unTag(this, tags, reason, world)\n return this\n}\n\n/** is this tag consistent with the word's current tags?\n * @param {string | string[]} tags - a tag or tags\n * @returns {boolean}\n */\nexports.canBe = function(tags, world) {\n return canBe(this, tags, world)\n}\n","const makeId = require('./_id')\nconst parseTerm = require('./parse')\nconst methods = require('./methods')\nconst tagMethods = require('./tag')\n\nclass Term {\n constructor(text = '') {\n text = String(text)\n let obj = parseTerm(text)\n // the various forms of our text\n this.text = obj.text || ''\n this.clean = obj.clean\n this.reduced = obj.reduced\n this.root = obj.root || null\n this.implicit = obj.implicit || null\n\n this.pre = obj.pre || ''\n this.post = obj.post || ''\n this.tags = {}\n this.prev = null\n this.next = null\n this.id = makeId(obj.clean)\n this.isA = 'Term' // easier than .constructor...\n // support alternative matches\n if (obj.alias) {\n this.alias = obj.alias\n }\n }\n /** set the text of the Term to something else*/\n set(str) {\n let obj = parseTerm(str)\n this.text = obj.text\n this.clean = obj.clean\n return this\n }\n}\n\n/** create a deep-copy of this term */\nTerm.prototype.clone = function() {\n let term = new Term(this.text)\n term.pre = this.pre\n term.post = this.post\n term.tags = Object.assign({}, this.tags)\n //use the old id, so it can be matched with .match(doc)\n // term.id = this.id\n return term\n}\n\nObject.assign(Term.prototype, methods)\nObject.assign(Term.prototype, tagMethods)\n\nmodule.exports = Term\n","/** return a flat array of Term objects */\nexports.terms = function(n) {\n let terms = [this.pool.get(this.start)]\n if (this.length === 0) {\n return []\n }\n for (let i = 0; i < this.length - 1; i += 1) {\n let id = terms[terms.length - 1].next\n if (id === null) {\n // throw new Error('linked-list broken')\n console.error(\"Compromise error: Linked list broken in phrase '\" + this.start + \"'\")\n break\n }\n let term = this.pool.get(id)\n terms.push(term)\n //return this one?\n if (n !== undefined && n === i) {\n return terms[n]\n }\n }\n if (n !== undefined) {\n return terms[n]\n }\n return terms\n}\n\n/** return a shallow or deep copy of this phrase */\nexports.clone = function(isShallow) {\n if (isShallow) {\n return this.buildFrom(this.start, this.length)\n }\n //how do we clone part of the pool?\n let terms = this.terms()\n let newTerms = terms.map(t => t.clone())\n //connect these new ids up\n newTerms.forEach((t, i) => {\n //add it to the pool..\n this.pool.add(t)\n if (newTerms[i + 1]) {\n t.next = newTerms[i + 1].id\n }\n if (newTerms[i - 1]) {\n t.prev = newTerms[i - 1].id\n }\n })\n return this.buildFrom(newTerms[0].id, newTerms.length)\n}\n\n/** return last term object */\nexports.lastTerm = function() {\n let terms = this.terms()\n return terms[terms.length - 1]\n}\n\n/** quick lookup for a term id */\nexports.hasId = function(wantId) {\n if (this.length === 0 || !wantId) {\n return false\n }\n if (this.start === wantId) {\n return true\n }\n let lastId = this.start\n for (let i = 0; i < this.length - 1; i += 1) {\n let term = this.pool.get(lastId)\n if (term === undefined) {\n console.error(`Compromise error: Linked list broken. Missing term '${lastId}' in phrase '${this.start}'\\n`)\n // throw new Error('linked List error')\n return false\n }\n if (term.next === wantId) {\n return true\n }\n lastId = term.next\n }\n return false\n}\n\n/** how many seperate, non-empty words is it? */\nexports.wordCount = function() {\n return this.terms().filter(t => t.text !== '').length\n}\n","const trimEnd = function(str) {\n return str.replace(/ +$/, '')\n}\n\n/** produce output in the given format */\nexports.text = function(options = {}, isFirst, isLast) {\n if (typeof options === 'string') {\n if (options === 'normal') {\n options = {\n whitespace: true,\n unicode: true,\n lowercase: true,\n punctuation: true,\n acronyms: true,\n abbreviations: true,\n implicit: true,\n normal: true,\n }\n } else if (options === 'clean') {\n options = {\n titlecase: false,\n lowercase: true,\n punctuation: true,\n whitespace: true,\n unicode: true,\n implicit: true,\n }\n } else if (options === 'reduced') {\n options = {\n titlecase: false,\n lowercase: true,\n punctuation: false, //FIXME: reversed\n whitespace: true,\n unicode: true,\n implicit: true,\n reduced: true,\n }\n } else if (options === 'root') {\n options = {\n titlecase: false,\n lowercase: true,\n punctuation: true,\n whitespace: true,\n unicode: true,\n implicit: true,\n root: true,\n }\n } else {\n options = {}\n }\n }\n let terms = this.terms()\n //this this phrase a complete sentence?\n let isFull = false\n if (terms[0] && terms[0].prev === null && terms[terms.length - 1].next === null) {\n isFull = true\n }\n let text = terms.reduce((str, t, i) => {\n options.last = isLast && i === terms.length - 1\n let showPre = true\n let showPost = true\n if (isFull === false) {\n // dont show beginning whitespace\n if (i === 0 && isFirst) {\n showPre = false\n }\n // dont show end-whitespace\n if (i === terms.length - 1 && isLast) {\n showPost = false\n }\n }\n let txt = t.textOut(options, showPre, showPost)\n // if (options.titlecase && i === 0) {\n // txt = titleCase(txt)\n // }\n return str + txt\n }, '')\n //full-phrases show punctuation, but not whitespace\n if (isFull === true && isLast) {\n text = trimEnd(text)\n }\n if (options.trim) {\n text = text.trim()\n }\n return text\n}\n","/** remove start and end whitespace */\nexports.trim = function() {\n let terms = this.terms()\n if (terms.length > 0) {\n //trim starting\n terms[0].pre = terms[0].pre.replace(/^\\s+/, '')\n //trim ending\n let lastTerm = terms[terms.length - 1]\n lastTerm.post = lastTerm.post.replace(/\\s+$/, '')\n }\n return this\n}\n","const endOfSentence = /[.?!]\\s*$/\n\n// replacing a 'word.' with a 'word!'\nconst combinePost = function(before, after) {\n //only transfer the whitespace\n if (endOfSentence.test(after)) {\n let whitespace = before.match(/\\s*$/)\n return after + whitespace\n }\n return before\n}\n\n//add whitespace to the start of the second bit\nconst addWhitespace = function(beforeTerms, newTerms) {\n // add any existing pre-whitespace to beginning\n newTerms[0].pre = beforeTerms[0].pre\n let lastTerm = beforeTerms[beforeTerms.length - 1]\n\n //add any existing punctuation to end of our new terms\n let newTerm = newTerms[newTerms.length - 1]\n newTerm.post = combinePost(lastTerm.post, newTerm.post)\n // remove existing punctuation\n lastTerm.post = ''\n\n //before ←[space] - after\n if (lastTerm.post === '') {\n lastTerm.post += ' '\n }\n}\n\n//insert this segment into the linked-list\nconst stitchIn = function(main, newPhrase) {\n // console.log(main.text(), newPhrase.text())\n let afterId = main.lastTerm().next\n //connect ours in (main → newPhrase)\n main.lastTerm().next = newPhrase.start\n //stich the end in (newPhrase → after)\n newPhrase.lastTerm().next = afterId\n //do it backwards, too\n if (afterId) {\n // newPhrase ← after\n let afterTerm = main.pool.get(afterId)\n afterTerm.prev = newPhrase.lastTerm().id\n }\n // before ← newPhrase\n let beforeId = main.terms(0).id\n if (beforeId) {\n let newTerm = newPhrase.terms(0)\n newTerm.prev = beforeId\n }\n}\n\n// avoid stretching a phrase twice.\nconst unique = function(list) {\n return list.filter((o, i) => {\n return list.indexOf(o) === i\n })\n}\n\n//append one phrase onto another.\nconst appendPhrase = function(before, newPhrase, doc) {\n let beforeTerms = before.terms()\n //spruce-up the whitespace issues\n addWhitespace(beforeTerms, newPhrase.terms())\n //insert this segment into the linked-list\n stitchIn(before, newPhrase)\n\n // stretch!\n // make each effected phrase longer\n let toStretch = [before]\n let hasId = before.start\n let docs = [doc]\n\n docs = docs.concat(doc.parents()) // find them all!\n\n docs.forEach(parent => {\n // only the phrases that should change\n let shouldChange = parent.list.filter(p => {\n return p.hasId(hasId)\n })\n toStretch = toStretch.concat(shouldChange)\n })\n // don't double-count a phrase\n toStretch = unique(toStretch)\n // console.log(toStretch)\n toStretch.forEach(p => {\n p.length += newPhrase.length\n })\n return before\n}\nmodule.exports = appendPhrase\n","const hasSpace = / /\n\n//a new space needs to be added, either on the new phrase, or the old one\n// '[new] [◻old]' -or- '[old] [◻new] [old]'\nconst addWhitespace = function(newTerms) {\n //add a space before our new text?\n\n // add a space after our text\n let lastTerm = newTerms[newTerms.length - 1]\n if (hasSpace.test(lastTerm.post) === false) {\n lastTerm.post += ' '\n }\n\n // let term = original.pool.get(original.start)\n // if (term.prev) {\n // //add our space ahead of our new terms\n // let firstWord = newTerms[0]\n // if (hasSpace.test(firstWord.post) === false) {\n // firstWord.post += ' '\n // }\n // return\n // }\n\n //otherwise, add our space to the start of original\n // if (hasSpace.test(term.pre) === false) {\n // term.pre = ' ' + term.pre\n // }\n return\n}\n\n//insert this segment into the linked-list\nconst stitchIn = function(main, newPhrase, newTerms) {\n // [newPhrase] → [main]\n let lastTerm = newTerms[newTerms.length - 1]\n lastTerm.next = main.start\n // [before] → [main]\n let pool = main.pool\n let start = pool.get(main.start)\n if (start.prev) {\n let before = pool.get(start.prev)\n before.next = newPhrase.start\n }\n //do it backwards, too\n // before ← newPhrase\n newTerms[0].prev = main.terms(0).prev\n // newPhrase ← main\n main.terms(0).prev = lastTerm.id\n}\n\n//recursively increase the length of all parent phrases\n// const stretchAll = function(doc, oldStart, newPhrase) {\n// //find our phrase to stretch\n// let phrase = doc.list.find(p => p.hasId(oldStart) || p.hasId(newPhrase.start))\n// if (phrase === undefined) {\n// console.error('compromise error: Prepend missing start - ' + oldStart)\n// return\n// }\n// //should we update the phrase's starting?\n// if (phrase.start === oldStart) {\n// phrase.start = newPhrase.start\n// }\n// // console.log(newPhrase)\n// phrase.length += newPhrase.length\n// if (doc.from) {\n// stretchAll(doc.from, oldStart, newPhrase)\n// }\n// }\nconst unique = function(list) {\n return list.filter((o, i) => {\n return list.indexOf(o) === i\n })\n}\n\n//append one phrase onto another\nconst joinPhrase = function(original, newPhrase, doc) {\n const starterId = original.start\n let newTerms = newPhrase.terms()\n //spruce-up the whitespace issues\n addWhitespace(newTerms, original)\n //insert this segment into the linked-list\n stitchIn(original, newPhrase, newTerms)\n //increase the length of our phrases\n let toStretch = [original]\n let docs = [doc]\n docs = docs.concat(doc.parents())\n docs.forEach(d => {\n // only the phrases that should change\n let shouldChange = d.list.filter(p => {\n return p.hasId(starterId) || p.hasId(newPhrase.start)\n })\n toStretch = toStretch.concat(shouldChange)\n })\n // don't double-count\n toStretch = unique(toStretch)\n // stretch these phrases\n toStretch.forEach(p => {\n p.length += newPhrase.length\n // change the start too, if necessary\n if (p.start === starterId) {\n p.start = newPhrase.start\n }\n })\n return original\n}\nmodule.exports = joinPhrase\n","//recursively decrease the length of all the parent phrases\nconst shrinkAll = function(doc, id, deleteLength, after) {\n let arr = doc.parents()\n arr.push(doc)\n\n arr.forEach(d => {\n //find our phrase to shrink\n let phrase = d.list.find(p => p.hasId(id))\n if (!phrase) {\n return\n }\n phrase.length -= deleteLength\n // does it start with this soon-removed word?\n if (phrase.start === id) {\n phrase.start = after.id\n }\n })\n // cleanup empty phrase objects\n doc.list = doc.list.filter(p => {\n if (!p.start || !p.length) {\n return false\n }\n return true\n })\n}\n\n/** wrap the linked-list around these terms\n * so they don't appear any more\n */\nconst deletePhrase = function(phrase, doc) {\n let pool = doc.pool()\n let terms = phrase.terms()\n\n //grab both sides of the chain,\n let prev = pool.get(terms[0].prev) || {}\n let after = pool.get(terms[terms.length - 1].next) || {}\n\n if (terms[0].implicit && prev.implicit) {\n prev.set(prev.implicit)\n prev.post += ' '\n }\n\n // //first, change phrase lengths\n shrinkAll(doc, phrase.start, phrase.length, after)\n\n // connect [prev]->[after]\n if (prev) {\n prev.next = after.id\n }\n // connect [prev]<-[after]\n if (after) {\n after.prev = prev.id\n }\n\n // lastly, actually delete the terms from the pool?\n // for (let i = 0; i < terms.length; i++) {\n // pool.remove(terms[i].id)\n // }\n}\nmodule.exports = deletePhrase\n","const append = require('../insert/append')\nconst prepend = require('../insert/prepend')\nconst deletePhrase = require('../insert/delete')\n// const tokenize = require('../../01-tokenizer')\n\n/** put this text at the end */\nexports.append = function(newPhrase, doc) {\n append(this, newPhrase, doc)\n return this\n}\n\n/** add this text to the beginning */\nexports.prepend = function(newPhrase, doc) {\n prepend(this, newPhrase, doc)\n return this\n}\n\nexports.delete = function(doc) {\n deletePhrase(this, doc)\n return this\n}\n\n// stich-in newPhrase, stretch 'doc' + parents\nexports.replace = function(newPhrase, doc) {\n // doc.debug()\n //add it do the end\n let firstLength = this.length\n append(this, newPhrase, doc)\n\n //delete original terms\n let tmp = this.buildFrom(this.start, this.length)\n tmp.length = firstLength\n // console.log(tmp)\n deletePhrase(tmp, doc)\n // return doc\n}\n\n/**\n * Turn this phrase object into 3 phrase objects\n */\nexports.splitOn = function(p) {\n let terms = this.terms()\n let result = {\n before: null,\n match: null,\n after: null,\n }\n let index = terms.findIndex(t => t.id === p.start)\n if (index === -1) {\n return result\n }\n //make all three sections into phrase-objects\n let start = terms.slice(0, index)\n if (start.length > 0) {\n result.before = this.buildFrom(start[0].id, start.length)\n }\n let match = terms.slice(index, index + p.length)\n if (match.length > 0) {\n result.match = this.buildFrom(match[0].id, match.length)\n }\n let end = terms.slice(index + p.length, terms.length)\n if (end.length > 0) {\n result.after = this.buildFrom(end[0].id, end.length, this.pool)\n }\n return result\n}\n","/** return json metadata for this phrase */\nexports.json = function(options = {}, world) {\n let res = {}\n // text data\n if (options.text) {\n res.text = this.text()\n }\n if (options.normal) {\n res.normal = this.text('normal')\n }\n if (options.clean) {\n res.clean = this.text('clean')\n }\n if (options.reduced) {\n res.reduced = this.text('reduced')\n }\n if (options.root) {\n res.root = this.text('root')\n }\n if (options.trim) {\n if (res.text) {\n res.text = res.text.trim()\n }\n if (res.normal) {\n res.normal = res.normal.trim()\n }\n if (res.reduced) {\n res.reduced = res.reduced.trim()\n }\n }\n // terms data\n if (options.terms) {\n if (options.terms === true) {\n options.terms = {}\n }\n res.terms = this.terms().map(t => t.json(options.terms, world))\n }\n return res\n}\n","/** match any terms after this phrase */\nexports.lookAhead = function(regs) {\n // if empty match string, return everything after\n if (!regs) {\n regs = '.*'\n }\n let pool = this.pool\n // get a list of all terms preceding our start\n let terms = []\n const getAfter = function(id) {\n let term = pool.get(id)\n if (!term) {\n return\n }\n terms.push(term)\n if (term.prev) {\n getAfter(term.next) //recursion\n }\n }\n let all = this.terms()\n let lastTerm = all[all.length - 1]\n getAfter(lastTerm.next)\n if (terms.length === 0) {\n return []\n }\n // got the terms, make a phrase from them\n let p = this.buildFrom(terms[0].id, terms.length)\n return p.match(regs)\n}\n\n/** match any terms before this phrase */\nexports.lookBehind = function(regs) {\n // if empty match string, return everything before\n if (!regs) {\n regs = '.*'\n }\n let pool = this.pool\n // get a list of all terms preceding our start\n let terms = []\n const getBefore = function(id) {\n let term = pool.get(id)\n if (!term) {\n return\n }\n terms.push(term)\n if (term.prev) {\n getBefore(term.prev) //recursion\n }\n }\n let term = pool.get(this.start)\n getBefore(term.prev)\n if (terms.length === 0) {\n return []\n }\n // got the terms, make a phrase from them\n let p = this.buildFrom(terms[terms.length - 1].id, terms.length)\n return p.match(regs)\n}\n","module.exports = Object.assign(\n {},\n require('./01-utils'),\n require('./02-text'),\n require('./03-change'),\n require('./04-insert'),\n require('./05-json'),\n require('./06-lookahead')\n)\n","// try to avoid doing the match\nconst failFast = function(p, regs) {\n if (regs.length === 0) {\n return true\n }\n for (let i = 0; i < regs.length; i += 1) {\n let reg = regs[i]\n\n // //logical quick-ones\n if (reg.optional !== true && reg.negative !== true) {\n //start/end impossibilites\n if (reg.start === true && i > 0) {\n return true\n }\n // has almost no effect\n if (p.cache.words !== undefined && reg.word !== undefined && p.cache.words.hasOwnProperty(reg.word) !== true) {\n // console.log('skip')\n return true\n }\n }\n //this is not possible\n if (reg.anything === true && reg.negative === true) {\n return true\n }\n }\n return false\n}\nmodule.exports = failFast\n","// i formally apologize for how complicated this is.\n\n//found a match? it's greedy? keep going!\nconst getGreedy = function(terms, t, reg, until, index, length) {\n let start = t\n for (; t < terms.length; t += 1) {\n //stop for next-reg match\n if (until && terms[t].doesMatch(until, index + t, length)) {\n return t\n }\n let count = t - start + 1\n // is it max-length now?\n if (reg.max !== undefined && count === reg.max) {\n return t\n }\n //stop here\n if (terms[t].doesMatch(reg, index + t, length) === false) {\n // is it too short?\n if (reg.min !== undefined && count < reg.min) {\n return null\n }\n return t\n }\n }\n return t\n}\n\n//'unspecific greedy' is a weird situation.\nconst greedyTo = function(terms, t, nextReg, index, length) {\n //if there's no next one, just go off the end!\n if (!nextReg) {\n return terms.length\n }\n //otherwise, we're looking for the next one\n for (; t < terms.length; t += 1) {\n if (terms[t].doesMatch(nextReg, index + t, length) === true) {\n return t\n }\n }\n //guess it doesn't exist, then.\n return null\n}\n\n/** tries to match a sequence of terms, starting from here */\nconst tryHere = function(terms, regs, index, length) {\n let captures = []\n let t = 0\n // we must satisfy each rule in 'regs'\n for (let r = 0; r < regs.length; r += 1) {\n let reg = regs[r]\n\n //should we fail here?\n if (!terms[t]) {\n //are all remaining regs optional?\n const hasNeeds = regs.slice(r).some(remain => !remain.optional)\n if (hasNeeds === false) {\n break\n }\n // have unmet needs\n return false\n }\n\n //support 'unspecific greedy' .* properly\n if (reg.anything === true && reg.greedy === true) {\n let skipto = greedyTo(terms, t, regs[r + 1], reg, index, length)\n // ensure it's long enough\n if (reg.min !== undefined && skipto - t < reg.min) {\n return false\n }\n // reduce it back, if it's too long\n if (reg.max !== undefined && skipto - t > reg.max) {\n t = t + reg.max\n continue\n }\n //TODO: support [*] properly\n if (skipto === null) {\n return false //couldn't find it\n }\n t = skipto\n continue\n }\n\n //if it looks like a match, continue\n if (reg.anything === true || terms[t].doesMatch(reg, index + t, length) === true) {\n let startAt = t\n // okay, it was a match, but if it optional too,\n // we should check the next reg too, to skip it?\n if (reg.optional && regs[r + 1]) {\n // does the next reg match it too?\n if (terms[t].doesMatch(regs[r + 1], index + t, length) === true) {\n // but does the next reg match the next term??\n // only skip if it doesn't\n if (!terms[t + 1] || terms[t + 1].doesMatch(regs[r + 1], index + t, length) === false) {\n r += 1\n }\n }\n }\n //advance to the next term!\n t += 1\n //check any ending '$' flags\n if (reg.end === true) {\n //if this isn't the last term, refuse the match\n if (t !== terms.length && reg.greedy !== true) {\n return false\n }\n }\n //try keep it going!\n if (reg.greedy === true) {\n t = getGreedy(terms, t, reg, regs[r + 1], index, length)\n if (t === null) {\n return false //greedy was too short\n }\n }\n if (reg.capture) {\n captures.push(startAt)\n //add greedy-end to capture\n if (t > 1 && reg.greedy) {\n captures.push(t - 1)\n }\n }\n continue\n }\n\n //bah, who cares, keep going\n if (reg.optional === true) {\n continue\n }\n // should we skip-over an implicit word?\n if (terms[t].isImplicit() && regs[r - 1] && terms[t + 1]) {\n // does the next one match?\n if (terms[t + 1].doesMatch(reg, index + t, length)) {\n t += 2\n continue\n }\n }\n // console.log(' ❌\\n\\n')\n return false\n }\n\n //we got to the end of the regs, and haven't failed!\n //try to only return our [captured] segment\n if (captures.length > 0) {\n //make sure the array is the full-length we'd return anyways\n let arr = terms.slice(captures[0], captures[captures.length - 1] + 1)\n //make sure the array is t-length (so we skip ahead full-length)\n for (let tmp = 0; tmp < t; tmp++) {\n arr[tmp] = arr[tmp] || null //these get cleaned-up after\n }\n return arr\n }\n //return our result\n return terms.slice(0, t)\n}\nmodule.exports = tryHere\n","/* break-down a match expression into this:\n{\n word:'',\n tag:'',\n regex:'',\n\n start:false,\n end:false,\n negative:false,\n anything:false,\n greedy:false,\n optional:false,\n\n capture:false,\n choices:[],\n}\n*/\nconst hasMinMax = /\\{([0-9]+,?[0-9]*)\\}/\nconst andSign = /&&/\n\nconst titleCase = str => {\n return str.charAt(0).toUpperCase() + str.substr(1)\n}\n\nconst end = function(str) {\n return str[str.length - 1]\n}\nconst start = function(str) {\n return str[0]\n}\nconst stripStart = function(str) {\n return str.substr(1)\n}\nconst stripEnd = function(str) {\n return str.substr(0, str.length - 1)\n}\nconst stripBoth = function(str) {\n str = stripStart(str)\n str = stripEnd(str)\n return str\n}\n\n//\nconst parseToken = function(w) {\n let obj = {}\n //collect any flags (do it twice)\n for (let i = 0; i < 2; i += 1) {\n //back-flags\n if (end(w) === '+') {\n obj.greedy = true\n w = stripEnd(w)\n }\n if (w !== '*' && end(w) === '*' && w !== '\\\\*') {\n obj.greedy = true\n w = stripEnd(w)\n }\n if (end(w) === '?') {\n obj.optional = true\n w = stripEnd(w)\n }\n if (end(w) === '$') {\n obj.end = true\n w = stripEnd(w)\n }\n //front-flags\n if (start(w) === '^') {\n obj.start = true\n w = stripStart(w)\n }\n if (start(w) === '!') {\n obj.negative = true\n w = stripStart(w)\n }\n //wrapped-flags\n if (start(w) === '(' && end(w) === ')') {\n // support (one && two)\n if (andSign.test(w)) {\n obj.choices = w.split(andSign)\n obj.operator = 'and'\n } else {\n obj.choices = w.split('|')\n obj.operator = 'or'\n }\n //remove '(' and ')'\n obj.choices[0] = stripStart(obj.choices[0])\n let last = obj.choices.length - 1\n obj.choices[last] = stripEnd(obj.choices[last])\n // clean up the results\n obj.choices = obj.choices.map(s => s.trim())\n obj.choices = obj.choices.filter(s => s)\n //recursion alert!\n obj.choices = obj.choices.map(parseToken)\n w = ''\n }\n //capture group (this one can span multiple-terms)\n if (start(w) === '[' || end(w) === ']') {\n obj.capture = true\n w = w.replace(/^\\[/, '')\n w = w.replace(/\\]$/, '')\n }\n //regex\n if (start(w) === '/' && end(w) === '/') {\n w = stripBoth(w)\n obj.regex = new RegExp(w)\n return obj\n }\n //soft-match\n if (start(w) === '~' && end(w) === '~') {\n w = stripBoth(w)\n obj.soft = true\n obj.word = w\n return obj\n }\n }\n // support #Tag{0,9}\n if (hasMinMax.test(w) === true) {\n w = w.replace(hasMinMax, (a, b) => {\n let arr = b.split(/,/g)\n if (arr.length === 1) {\n // '{3}'\tExactly three times\n obj.min = Number(arr[0])\n obj.max = Number(arr[0])\n } else {\n // '{2,4}' Two to four times\n // '{3,}' Three or more times\n obj.min = Number(arr[0])\n obj.max = Number(arr[1] || 999)\n }\n obj.greedy = true\n return ''\n })\n }\n\n //do the actual token content\n if (start(w) === '#') {\n obj.tag = stripStart(w)\n obj.tag = titleCase(obj.tag)\n return obj\n }\n //dynamic function on a term object\n if (start(w) === '@') {\n obj.method = stripStart(w)\n return obj\n }\n if (w === '.') {\n obj.anything = true\n return obj\n }\n //support alone-astrix\n if (w === '*') {\n obj.anything = true\n obj.greedy = true\n obj.optional = true\n return obj\n }\n if (w) {\n //somehow handle encoded-chars?\n w = w.replace('\\\\*', '*')\n w = w.replace('\\\\.', '.')\n obj.word = w.toLowerCase()\n }\n return obj\n}\nmodule.exports = parseToken\n","const parseToken = require('./parseToken')\n\nconst isArray = function(arr) {\n return Object.prototype.toString.call(arr) === '[object Array]'\n}\n\n//split-up by (these things)\nconst byParentheses = function(str) {\n let arr = str.split(/([\\^\\[\\!]*\\(.*?\\)[?+*]*\\]?\\$?)/)\n arr = arr.map(s => s.trim())\n return arr\n}\n\nconst byWords = function(arr) {\n let words = []\n arr.forEach(a => {\n //keep brackets lumped together\n if (/^[[^_/]?\\(/.test(a[0])) {\n words.push(a)\n return\n }\n let list = a.split(' ')\n list = list.filter(w => w)\n words = words.concat(list)\n })\n return words\n}\n\n//turn an array into a 'choices' list\nconst byArray = function(arr) {\n return [\n {\n choices: arr.map(s => {\n return {\n word: s,\n }\n }),\n },\n ]\n}\n\nconst postProcess = function(tokens) {\n //ensure there's only one consecutive capture group.\n let count = tokens.filter(t => t.capture === true).length\n if (count > 1) {\n let captureArr = tokens.map(t => t.capture)\n let first = captureArr.indexOf(true)\n let last = captureArr.length - 1 - captureArr.reverse().indexOf(true)\n //'fill in' capture groups between start-end\n for (let i = first; i < last; i++) {\n tokens[i].capture = true\n }\n }\n return tokens\n}\n\nconst fromDoc = function(doc) {\n if (!doc || !doc.list || !doc.list[0]) {\n return []\n }\n let ids = []\n doc.list.forEach(p => {\n p.terms().forEach(t => {\n ids.push({ id: t.id })\n })\n })\n return [{ choices: ids, greedy: true }]\n}\n\n/** parse a match-syntax string into json */\nconst syntax = function(input) {\n // fail-fast\n if (input === null || input === undefined || input === '') {\n return []\n }\n //try to support a ton of different formats:\n if (typeof input === 'object') {\n if (isArray(input)) {\n if (input.length === 0 || !input[0]) {\n return []\n }\n\n //is it a pre-parsed reg-list?\n if (typeof input[0] === 'object') {\n return input\n }\n //support a flat array of normalized words\n if (typeof input[0] === 'string') {\n return byArray(input)\n }\n }\n //support passing-in a compromise object as a match\n if (input && input.isA === 'Doc') {\n return fromDoc(input)\n }\n return []\n }\n if (typeof input === 'number') {\n input = String(input) //go for it?\n }\n let tokens = byParentheses(input)\n tokens = byWords(tokens)\n tokens = tokens.map(parseToken)\n //clean up anything weird\n tokens = postProcess(tokens)\n // console.log(JSON.stringify(tokens, null, 2))\n return tokens\n}\nmodule.exports = syntax\n","const failFast = require('./02-failFast')\nconst tryMatch = require('./03-tryMatch')\nconst syntax = require('../../Doc/match/syntax')\n\n/** returns a simple array of arrays */\nconst matchAll = function(p, regs, matchOne = false) {\n //if we forgot to parse it..\n if (typeof regs === 'string') {\n regs = syntax(regs)\n }\n //try to dismiss it, at-once\n if (failFast(p, regs) === true) {\n return []\n }\n\n //any match needs to be this long, at least\n const minLength = regs.filter(r => r.optional !== true).length\n let terms = p.cache.terms || p.terms()\n let matches = []\n\n //optimisation for '^' start logic\n if (regs[0].start === true) {\n let match = tryMatch(terms, regs, 0, terms.length)\n if (match !== false && match.length > 0) {\n matches.push(match)\n }\n // remove (intentional) null results\n matches = matches.map(arr => {\n return arr.filter(t => t)\n })\n return matches\n }\n //try starting, from every term\n for (let i = 0; i < terms.length; i += 1) {\n // slice may be too short\n if (i + minLength > terms.length) {\n break\n }\n //try it!\n\n let match = tryMatch(terms.slice(i), regs, i, terms.length)\n if (match !== false && match.length > 0) {\n //zoom forward!\n i += match.length - 1\n //[capture-groups] return some null responses\n match = match.filter(m => m)\n matches.push(match)\n //ok, maybe that's enough?\n if (matchOne === true) {\n return matches\n }\n }\n }\n return matches\n}\nmodule.exports = matchAll\n","const matchAll = require('./01-matchAll')\n\n/** return anything that doesn't match.\n * returns a simple array of arrays\n */\nconst notMatch = function(p, regs) {\n let found = {}\n let arr = matchAll(p, regs)\n arr.forEach(ts => {\n ts.forEach(t => {\n found[t.id] = true\n })\n })\n //return anything not found\n let terms = p.terms()\n let result = []\n let current = []\n terms.forEach(t => {\n if (found[t.id] === true) {\n if (current.length > 0) {\n result.push(current)\n current = []\n }\n return\n }\n current.push(t)\n })\n if (current.length > 0) {\n result.push(current)\n }\n return result\n}\nmodule.exports = notMatch\n","const matchAll = require('./01-matchAll')\nconst notMatch = require('./not')\n\n/** return an array of matching phrases */\nexports.match = function(str) {\n let matches = matchAll(this, str)\n //make them phrase objects\n matches = matches.map(list => {\n return this.buildFrom(list[0].id, list.length)\n })\n return matches\n}\n\n/** return boolean if one match is found */\nexports.has = function(str) {\n let matches = matchAll(this, str, true)\n return matches.length > 0\n}\n\n/** remove all matches from the result */\nexports.not = function(str) {\n let matches = notMatch(this, str)\n //make them phrase objects\n matches = matches.map(list => {\n return this.buildFrom(list[0].id, list.length)\n })\n return matches\n}\n\n/** return a list of phrases that can have this tag */\nexports.canBe = function(tag, world) {\n let results = []\n let terms = this.terms()\n let previous = false\n for (let i = 0; i < terms.length; i += 1) {\n let can = terms[i].canBe(tag, world)\n if (can === true) {\n if (previous === true) {\n //add it to the end\n results[results.length - 1].push(terms[i])\n } else {\n results.push([terms[i]]) //make a new one\n }\n previous = can\n }\n }\n //turn them into Phrase objects\n results = results\n .filter(a => a.length > 0)\n .map(arr => {\n return this.buildFrom(arr[0].id, arr.length)\n })\n return results\n}\n","const methods = require('./methods')\nconst matchMethods = require('./match')\n// const tokenize = require('../01-tokenizer')\n\nclass Phrase {\n constructor(id, length, pool) {\n this.start = id\n this.length = length\n this.isA = 'Phrase' // easier than .constructor...\n Object.defineProperty(this, 'pool', {\n enumerable: false,\n writable: true,\n value: pool,\n })\n Object.defineProperty(this, 'cache', {\n enumerable: false,\n writable: true,\n value: {},\n })\n }\n}\n\n/** create a new Phrase object from an id and length */\nPhrase.prototype.buildFrom = function(id, length) {\n let p = new Phrase(id, length, this.pool)\n if (this.cache) {\n p.cache = this.cache\n p.cache.terms = null\n }\n return p\n}\n// Phrase.prototype.fromString = function(str) {\n// console.log(tokenize)\n// return tokenize.fromText(str)\n// }\n\n//apply methods\nObject.assign(Phrase.prototype, matchMethods)\nObject.assign(Phrase.prototype, methods)\n\n//apply aliases\nconst aliases = {\n term: 'terms',\n}\nObject.keys(aliases).forEach(k => (Phrase.prototype[k] = Phrase.prototype[aliases[k]]))\n\nmodule.exports = Phrase\n","/** a key-value store of all terms in our Document */\nclass Pool {\n constructor(words = {}) {\n //quiet this property in console.logs\n Object.defineProperty(this, 'words', {\n enumerable: false,\n value: words,\n })\n }\n /** throw a new term object in */\n add(term) {\n this.words[term.id] = term\n return this\n }\n /** find a term by it's id */\n get(id) {\n return this.words[id]\n }\n /** find a term by it's id */\n remove(id) {\n delete this.words[id]\n }\n merge(pool) {\n Object.assign(this.words, pool.words)\n return this\n }\n /** helper method */\n stats() {\n return {\n words: Object.keys(this.words).length,\n }\n }\n}\n\n/** make a deep-copy of all terms */\nPool.prototype.clone = function() {\n let keys = Object.keys(this.words)\n let words = keys.reduce((h, k) => {\n let t = this.words[k].clone()\n h[t.id] = t\n return h\n }, {})\n return new Pool(words)\n}\n\nmodule.exports = Pool\n","//(Rule-based sentence boundary segmentation) - chop given text into its proper sentences.\n// Ignore periods/questions/exclamations used in acronyms/abbreviations/numbers, etc.\n// @spencermountain 2017 MIT\n\n//proper nouns with exclamation marks\n// const blacklist = {\n// yahoo: true,\n// joomla: true,\n// jeopardy: true,\n// }\n\n//regs-\nconst initSplit = /(\\S.+?[.!?\\u203D\\u2E18\\u203C\\u2047-\\u2049])(?=\\s+|$)/g\nconst hasSomething = /\\S/\n\nconst isAcronym = /[ .][A-Z]\\.? *$/i\nconst hasEllipse = /(?:\\u2026|\\.{2,}) *$/\nconst newLine = /((?:\\r?\\n|\\r)+)/ // Match different new-line formats\nconst hasLetter = /[a-z0-9\\u00C0-\\u00FF\\u00a9|\\u00ae|[\\u2000-\\u3300]|\\ud83c[\\ud000-\\udfff]|\\ud83d[\\ud000-\\udfff]|\\ud83e[\\ud000-\\udfff]/i\n\nconst startWhitespace = /^\\s+/\n\n// Start with a regex:\nconst naiive_split = function(text) {\n let all = []\n //first, split by newline\n let lines = text.split(newLine)\n for (let i = 0; i < lines.length; i++) {\n //split by period, question-mark, and exclamation-mark\n let arr = lines[i].split(initSplit)\n for (let o = 0; o < arr.length; o++) {\n all.push(arr[o])\n }\n }\n return all\n}\n\n/** does this look like a sentence? */\nconst isSentence = function(str, abbrevs) {\n // check for 'F.B.I.'\n if (isAcronym.test(str) === true) {\n return false\n }\n //check for '...'\n if (hasEllipse.test(str) === true) {\n return false\n }\n // must have a letter\n if (hasLetter.test(str) === false) {\n return false\n }\n\n let txt = str.replace(/[.!?\\u203D\\u2E18\\u203C\\u2047-\\u2049] *$/, '')\n let words = txt.split(' ')\n let lastWord = words[words.length - 1].toLowerCase()\n // check for 'Mr.'\n if (abbrevs.hasOwnProperty(lastWord)) {\n return false\n }\n // //check for jeopardy!\n // if (blacklist.hasOwnProperty(lastWord)) {\n // return false\n // }\n return true\n}\n\nconst splitSentences = function(text, world) {\n let abbrevs = world.cache.abbreviations\n\n text = text || ''\n text = String(text)\n let sentences = []\n // First do a greedy-split..\n let chunks = []\n // Ensure it 'smells like' a sentence\n if (!text || typeof text !== 'string' || hasSomething.test(text) === false) {\n return sentences\n }\n // Start somewhere:\n let splits = naiive_split(text)\n // Filter-out the crap ones\n for (let i = 0; i < splits.length; i++) {\n let s = splits[i]\n if (s === undefined || s === '') {\n continue\n }\n //this is meaningful whitespace\n if (hasSomething.test(s) === false) {\n //add it to the last one\n if (chunks[chunks.length - 1]) {\n chunks[chunks.length - 1] += s\n continue\n } else if (splits[i + 1]) {\n //add it to the next one\n splits[i + 1] = s + splits[i + 1]\n continue\n }\n }\n //else, only whitespace, no terms, no sentence\n chunks.push(s)\n }\n\n //detection of non-sentence chunks:\n //loop through these chunks, and join the non-sentence chunks back together..\n for (let i = 0; i < chunks.length; i++) {\n let c = chunks[i]\n //should this chunk be combined with the next one?\n if (chunks[i + 1] && isSentence(c, abbrevs) === false) {\n chunks[i + 1] = c + (chunks[i + 1] || '')\n } else if (c && c.length > 0) {\n //&& hasLetter.test(c)\n //this chunk is a proper sentence..\n sentences.push(c)\n chunks[i] = ''\n }\n }\n //if we never got a sentence, return the given text\n if (sentences.length === 0) {\n return [text]\n }\n\n //move whitespace to the ends of sentences, when possible\n //['hello',' world'] -> ['hello ','world']\n for (let i = 1; i < sentences.length; i += 1) {\n let ws = sentences[i].match(startWhitespace)\n if (ws !== null) {\n sentences[i - 1] += ws[0]\n sentences[i] = sentences[i].replace(startWhitespace, '')\n }\n }\n return sentences\n}\n\nmodule.exports = splitSentences\n// console.log(sentence_parser('john f. kennedy'));\n","const wordlike = /\\S/\nconst isBoundary = /^[!?.]+$/\nconst naiiveSplit = /(\\S+)/\nconst isSlash = /\\/\\W*$/\n\nconst notWord = {\n '.': true,\n '-': true, //dash\n '–': true, //en-dash\n '—': true, //em-dash\n '--': true,\n '...': true,\n // '/': true, // 'one / two'\n}\n\nconst hasHyphen = function(str) {\n //dont split 're-do'\n if (/^(re|un)-?[^aeiou]./.test(str) === true) {\n return false\n }\n //letter-number\n let reg = /^([a-z\\u00C0-\\u00FF`\"'/]+)(-|–|—)([a-z0-9\\u00C0-\\u00FF].*)/i\n if (reg.test(str) === true) {\n return true\n }\n //support weird number-emdash combo '2010–2011'\n // let reg2 = /^([0-9]+)(–|—)([0-9].*)/i\n // if (reg2.test(str)) {\n // return true\n // }\n return false\n}\n\n// 'he / she' should be one word\nconst combineSlashes = function(arr) {\n for (let i = 1; i < arr.length - 1; i++) {\n if (isSlash.test(arr[i])) {\n arr[i - 1] += arr[i] + arr[i + 1]\n arr[i] = null\n arr[i + 1] = null\n }\n }\n return arr\n}\n\nconst splitHyphens = function(word) {\n let arr = []\n //support multiple-hyphenated-terms\n const hyphens = word.split(/[-–—]/)\n for (let o = 0; o < hyphens.length; o++) {\n if (o === hyphens.length - 1) {\n arr.push(hyphens[o])\n } else {\n arr.push(hyphens[o] + '-')\n }\n }\n return arr\n}\n\n//turn a string into an array of terms (naiive for now, lumped later)\nconst splitWords = function(str) {\n let result = []\n let arr = []\n //start with a naiive split\n str = str || ''\n if (typeof str === 'number') {\n str = String(str)\n }\n\n const words = str.split(naiiveSplit)\n for (let i = 0; i < words.length; i++) {\n //split 'one-two'\n if (hasHyphen(words[i]) === true) {\n arr = arr.concat(splitHyphens(words[i]))\n continue\n }\n arr.push(words[i])\n }\n\n //greedy merge whitespace+arr to the right\n let carry = ''\n for (let i = 0; i < arr.length; i++) {\n let word = arr[i]\n //if it's more than a whitespace\n if (wordlike.test(word) === true && notWord.hasOwnProperty(word) === false && isBoundary.test(word) === false) {\n //put whitespace on end of previous term, if possible\n if (result.length > 0) {\n result[result.length - 1] += carry\n result.push(word)\n } else {\n //otherwise, but whitespace before\n result.push(carry + word)\n }\n carry = ''\n } else {\n carry += word\n }\n }\n //handle last one\n if (carry && result.length > 0) {\n result[result.length - 1] += carry //put it on the end\n }\n // combine 'one / two'\n result = combineSlashes(result)\n // remove empty results\n result = result.filter(s => s)\n return result\n}\nmodule.exports = splitWords\n","const Term = require('../Term/Term')\nconst Phrase = require('../Phrase/Phrase')\nconst Pool = require('./Pool')\n\nconst splitSentences = require('./01-sentences')\nconst splitTerms = require('./02-words')\n\n//add forward/backward 'linked-list' prev/next ids\nconst addLinks = terms => {\n terms.forEach((term, i) => {\n if (i > 0) {\n term.prev = terms[i - 1].id\n }\n if (terms[i + 1]) {\n term.next = terms[i + 1].id\n }\n })\n}\n\n/** turn a string into an array of Phrase objects */\nconst fromText = function(text = '', world, pool) {\n //a bit of validation, first\n if (typeof text !== 'string') {\n if (typeof text === 'number') {\n text = String(text)\n }\n }\n //tokenize into words\n let sentences = splitSentences(text, world)\n sentences = sentences.map(str => splitTerms(str))\n\n //turn them into proper objects\n pool = pool || new Pool()\n\n let phrases = sentences.map(terms => {\n terms = terms.map(str => {\n let term = new Term(str)\n pool.add(term)\n return term\n })\n //add next/previous ids\n addLinks(terms)\n\n //return phrase objects\n return new Phrase(terms[0].id, terms.length, pool)\n })\n //return them ready for a Document object\n return phrases\n}\n\n// parse the compressed format '3,2|2,4'\nconst parseTags = function(text, tagList) {\n return text.split('|').map(str => {\n let numList = str.split(',')\n numList = numList.map(n => parseInt(n, 10))\n // convert a list pf numbers into an array of tag names\n return numList.map(num => {\n if (!tagList[num]) {\n console.warn('Compromise import: missing tag at index ' + num)\n }\n return tagList[num]\n })\n })\n}\n\n/** create a word-pool and Phrase objects from .export() json*/\nconst fromJSON = function(json, world) {\n if (typeof json === 'string') {\n json = JSON.parse(json)\n }\n let pool = new Pool()\n //create Phrase objects\n let phrases = json.list.map(o => {\n // tokenize words from sentence text\n let terms = splitTerms(o[0])\n // unpack the tag data for each term\n let tagArr = parseTags(o[1], json.tags)\n //create Term objects\n terms = terms.map((str, i) => {\n let term = new Term(str)\n tagArr[i].forEach(tag => term.tag(tag, '', world))\n pool.add(term)\n return term\n })\n //add prev/next links\n addLinks(terms)\n // return a proper Phrase object\n return new Phrase(terms[0].id, terms.length, pool)\n })\n return phrases\n}\n\nmodule.exports = {\n fromText,\n fromJSON,\n}\n","module.exports = '12.0.0'","module.exports={\n \"Comparative\": \"true¦better\",\n \"Superlative\": \"true¦earlier\",\n \"PresentTense\": \"true¦is,sounds\",\n \"Value\": \"true¦a few\",\n \"Noun\": \"true¦a8b7c5e3f2here,ie,lit,m1no doubt,p0tce,vs;d,l;a,d;t,y;g,sp,tc,x0;!p;a,ca,o0;l,rp;a,c,l;d,l,rc\",\n \"Copula\": \"true¦a1is,w0;as,ere;m,re\",\n \"PastTense\": \"true¦be3came,d2had,meant,sa2taken,w0;as,e0;nt,re;id;en,gan\",\n \"Condition\": \"true¦if,unless\",\n \"Gerund\": \"true¦accord0be0develop0go0result0stain0;ing\",\n \"Negative\": \"true¦n0;ever,o0;!n,t\",\n \"QuestionWord\": \"true¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s\",\n \"Plural\": \"true¦records\",\n \"Conjunction\": \"true¦&,aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh\",\n \"Pronoun\": \"true¦'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s\",\n \"Singular\": \"true¦0:0X;1:10;a0Wb0Kc0Bd04e02fXgShOici1jel0kitty,lNmJnIoHpDquestion mark,rBs7t4u2womW;nc0Rs 2;doll0Dst0F; rex,a3h2ic,ragedy,v show;ere,i1;l0x return;ist0Pky,omeone,t2uper bowl,yst0W;ep3ri1u2;de0Pff;faMmoM;al0i1o2;om,se;a4i0Jr3u2;dLrpoD;erogaVobl0O;rt,te0I;bjSceGthers;othi1umb0E;a4ee04o2;del,m2nopo0th0C;!my;n,yf0;i0unch;ead start,o2;l0me3u2;se;! run;adf0entlem5irlZlaci04od,rand3u2;l0y; slam,fa2mo2;th01;an;a5ella,ly,ol0r3un2;di1;iTo2;ntiWsN;mi0thV;conomy,gg,ner5veWx2;ampQecu7;ad7e4innSo2ragonf0ude;cumentFg2i0l0or;gy;ath,t2;ec2;tive;!dy;a8eili1h6i4o2redit card;ttage,u2;riJsin;ty,vil w2;ar;andeliGocol2;ate;n2rD;ary;aAel0lesHo6r4u2;n2tterf0;ti1;eakfast,o2;!th8;dy,tt4y2;!fri2;end;le;nki1r2;ri2;er;d4l0noma0u2;nt;ly; homin4verti2;si1;ng;em\",\n \"Actor\": \"true¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt\",\n \"Honorific\": \"true¦a03b00cSdReQfiLgKhon,jr,king,lJmEoDp8queen,r4s0taoiseach,vice7;e1fc,gt,ir,r,u0;ltTpt,rg;c0nDrgeaL;ond liJretary;abbi,e0;ar1pAs,v0;!erend; admirY;astPhd,r0vt;esideEi1of0;!essN;me mini5nce0;!ss;fficOp,rd;a3essrs,i2lle,me,r1s0;!tr;!s;stK;gistrate,j,r6yF;i3lb,t;en,ov;eld mar3rst l0;ady,i0;eutena0;nt;shG;sq,xcellency;et,oct6r,utchess;apt6hance4mdr,o0pl;lonel,m2ngress0unci3;m0wom0;an;dr,mand5;ll0;or;!ain;ldg,rig0;!adi0;er;d0sst,tty,yatullah;j,m0v;!ir0;al\",\n \"SportsTeam\": \"true¦0:1A;1:1H;2:1G;a1Eb16c0Td0Kfc dallas,g0Ihouston 0Hindiana0Gjacksonville jagua0k0El0Bm01newToQpJqueens parkIreal salt lake,sAt5utah jazz,vancouver whitecaps,w3yW;ashington 3est ham0Rh10;natio1Oredski2wizar0W;ampa bay 6e5o3;ronto 3ttenham hotspur;blue ja0Mrapto0;nnessee tita2xasC;buccanee0ra0K;a7eattle 5heffield0Kporting kansas0Wt3;. louis 3oke0V;c1Frams;marine0s3;eah15ounG;cramento Rn 3;antonio spu0diego 3francisco gJjose earthquak1;char08paA; ran07;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat1steele0;il3oenix su2;adelphia 3li1;eagl1philNunE;dr1;akland 3klahoma city thunder,rlando magic;athle0Mrai3;de0; 3castle01;england 7orleans 6york 3;city fc,g4je0FknXme0Fred bul0Yy3;anke1;ian0D;pelica2sain0C;patrio0Brevolut3;ion;anchester Be9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Fvi3;kings;imberwolv1wi2;rewe0uc0K;dolphi2heat,marli2;mphis grizz3ts;li1;cXu08;a4eicesterVos angeles 3;clippe0dodDla9; galaxy,ke0;ansas city 3nE;chiefs,roya0E; pace0polis colU;astr06dynamo,rockeTtexa2;olden state warrio0reen bay pac3;ke0;.c.Aallas 7e3i05od5;nver 5troit 3;lio2pisto2ti3;ge0;broncZnuggeM;cowbo4maver3;ic00;ys; uQ;arCelKh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki1;brow2cavalie0india2;bengaWre3;ds;arlotte horAicago 3;b4cubs,fire,wh3;iteB;ea0ulR;diff3olina panthe0; c3;ity;altimore 9lackburn rove0oston 5rooklyn 3uffalo bilN;ne3;ts;cel4red3; sox;tics;rs;oriol1rave2;rizona Ast8tlanta 3;brav1falco2h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls\",\n \"Uncountable\": \"true¦a1Ib1Ac11d0Ye0Rf0Lg0Hh0Ci08j07knowled1Hl02mUnews,oTpQrLsAt5vi4w0;a2ea05i1oo0;d,l;ldlife,ne;rmth,t17;neg0Yol06tae;e3h2oothpaste,r0una;affPou0;ble,sers,t;ermod1Eund12;a,nnis;a8cene04eri0Oh7il6kittl0Onow,o5p3t1u0;g0Rnshi0H;ati1De0;am,el;ace16e0;ci0Jed;ap,cc0U;k,v0T;eep,ingl0G;d04fe10l0nd;m0St;a3e1ic0;e,ke0D;c0laxa09search;ogni08rea08;bi09in;aJe1hys10last5o0ressV;lit0Zrk,w0J;a0Vtrol;bstetr0Xil,xygen;a5e3ilk,o2u0;mps,s0;ic;nGo0A;a0chan0S;slZt;chine0il,themat0Q; learn05ry;aught08e2i1ogi0Nu0;ck,g0C;ce,ghtn02ngui0LteratH;a0isG;th04;ewel7usti0G;ce,mp0nformaOtself;a0ortan0E;ti0;en0C;a3isto2o0;ck0mework,n0spitali06;ey;ry;ir,libut,ppi7;en01o1r0um,ymna08;a6ound;l0ssip;d,f;i4lour,o1urnit0;ure;od,rgive0uriNwl;ne0;ss;c6sh;conomZduca5lectr4n2quip3thZvery0;body,o0thE;ne;joy0tertain0;ment;iciNonU;tiF;ar1iabet0raugh1;es;ts;a7elcius,h3ivPl2o0urrency;al,ld w0nfusiAttA;ar;assMoth2;aos,e0;e1w0;ing;se;r4sh;a4eef,i1lood,owls,read,utt0;er;lliar1s0;on;ds;g0ss;ga0;ge;c6dvi5ero3ir2mnes1rt,thl0;et7;ty;craft;b4d0naut4;ynam3;ce;id,ou0;st0;ics\",\n \"Infinitive\": \"true¦0:6H;1:6V;2:55;3:6S;4:6T;5:5W;6:64;7:6R;8:6N;9:6F;A:6P;B:6M;C:6A;D:6W;a67b5Wc4Yd46e3Qf3Dg37h30i2Nj2Lk2Jl2Am20n1Xo1Tp1Eques3Er0Ms01tTuPvMwFyE;awn,ield;aHe1Thist6iGoEre60;nd0rE;k,ry;pe,sh,th0;lk,nFrEsh,tCve;n,raD;d0t;aFiEo7;ew,sB;l68ry;nFpEr3se;gra4Jli3W;dEi7lo5O;er47o;aKeJhIoHrFuEwi8;ne,rn;aEe0Ki5Ku8y;de,in,nsf0p,v5C;r2VuC;ank,reat2L;nd,st;lk,rg1Ms7;aXcUeThRi48kip,lQmPnee3Ho4WpOtHuEwitC;bmBck,ff0gge8ppFrEspe5;ge,pri1rou4Tvi4;ly,o32;aJeIoHrFuE;dy,mb6;a4NeEi4;ngth2Bss,tC;p,re;m,p;in,ke,r0Oy;la50oil,rink6;e1Vi6o3F;am,ip;a2iv0oE;ck,ut;arCem,le5n1r4tt6;aFo2rE;atCew;le,re;il,ve;a03eGisk,oFuE;in,le,sh;am,ll;aZcXdu9fWgVje5lSmRnt,pOquNsItHvEwa5L;eEiew,o32;al,l,rE;se,t;a41i2u3Y;eHi8oGtE;!o2rE;i5uc1W;l4rt;mb6nt,r4;e8i2;air,eFlEo3XreseD;a9y;at;a3Remb0i3To4;aFeEi4y;a1nt;te,x;a53r0F;act1Uer,le5u1;a0Zei4k5FoEyc6;gni28nci6rd;ch,li27s5D;i1nE;ge,k;aRerQiPlMoKrGuE;b1Xll,mp,rEsh;cha1s4G;ai1eGiDoE;cEdu9greAhibBmi1te8vi2R;eAlaim;di5pa2ss,veD;iDp,rtr3WsEur;e,t;aFuE;g,n3;n,y;ck,le;fo2YmBsi8;ck,iDrt4Css,u1;bGccur,ff0pera7utweFverEwe;co3Xlap,ta1Yu1whelm;igh;ser4ta2Y;eFotE;e,i9;ed,gle5;aJeIiGoFuE;ltip3Ard0;nit10ve;nErr0Z;d,g6us;asu2lt,n0Mr3ssa3;inta2Ona3rFtE;ch,t0;ch,kEry;et;aKeJiGoEu1A;aEck,ok,ve;d,n;ft,ke,mBnFstEve;!en;e,k;a2Bc0Ct;b0Lck,uE;gh,nC;iEno2W;ck,ll,ss;am,o29uE;d3mp;gno2mOnEss39;cMdica7flu0KhLsItGvE;eEol4;nt,st;erErodu9;a5fe2;i8tE;aEru5;ll;abBibB;lu1Cr1A;agi20pE;lemeDo1Yro4;aIeGi2oFuE;nt,rry;n00pe,st;aElp;d,t;nd6ppErm,te;en;aIloAove1KrGuE;arEeAi11;ant30d;aEip,umb6;b,sp;in,th0ze;aOeaNiLlJoGracFuncE;ti3A;tu2;cus,lFrE;ce,eca8m,s2S;d,l1W;a1ToE;at,od,w;gu2lEni1Rx;e,l;r,tu2;il,vE;or;a11cho,le5mQnNstLvalua7xE;a08cJerIi8pEte15;a14eFla12oEreA;rt,se;ct,riE;en9;ci1t;el,han3;abEima7;li1D;ab6couVdFfor9ga3han9j01riCsu2t0vE;isi2Ny;!u2;body,er3pE;hasiEow0;ze;a04eSiJoIrFuE;mp;aFeAiE;ft;g,in;d3ubt;ff0p,re5sFvE;iWor9;aIcFliEmiApl13tingui0Y;ke;oEuA;uEv0;ra3;gr1QppE;ear,ro4;cLem,fJliv0ma0Bny,pIsFterE;mi0C;cribe,er4iFtrE;oy;gn,re;a07e06i5osB;eEi07y;at,ct;iGlFrE;ea1;a2i03;de;ma3n9re,te;a08e07h04i7l02oHrE;aFeEoAu0Dy;a7dB;ck,ve;llXmQnFok,py,uEv0;gh,nt;ceNdu5fKsItGvE;eEin9;rt,y;aNin0PrE;a8ibu7ol;iEtitu7;d0st;iFoEroD;rm;gu2rm;rn;biJfoImaHpE;a2laE;in;re;nd;rt;ne;ap1e5;aEip,o1;im,w;aFeE;at,ck,w;llen3n3r3se;a1nt0;ll,ncFrEt0u1;e,ry;el;aNeKloJoHruGuE;lEry;ly;sh;a8mb,o8rrEth0un9;ow;ck;ar,lFnefBtrE;ay;ie4ong;ng,se;band0Hc09d04ffo03gr02id,lZmu1nWppRrOsIttEvoid,waB;acGeFra5;ct;m0Dnd;h,k;k,sE;eGiFocia7uE;me;gn,st;mb6rt;le;chFgEri4;ue;!i4;eaHlGroE;aCve;ch;aud,y;l,r;noun9sw0tE;icipa7;ce;lFt0;er;e3ow;ee;rd;aPdGju8mBoP;it;st;!reA;ss;cHhie4knowled3tiva7;te;ge;ve;eGouDu1;se;nt;pt;on\",\n \"Unit\": \"true¦0:16;a11b0Zc0Ld0Ke0If0Dg09h06in0Ejoule0k00lYmNnMoLpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Kb,d0Qears old,o1;tt0E;att0b;able4b3e2on1sp;!ne0;a2r0A;!l,sp;spo01; ft,uare 1;c0Fd0Ef3i0Ckilo0Gm1ya0B;e0Jil1;e0li0E;eet0o0A;t,uart0;ascals,e2i1ou0Mt;c0Jnt0;rcent,tZ;hms,uVz;an0GewtQ;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;e1g,z;ct1rtz0;aXogQ;al2b,igAra1;in0m0;!l1;on0;a4emtPl2t1;²,³; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s\",\n \"Organization\": \"true¦0:46;a3Ab2Qc2Ad21e1Xf1Tg1Lh1Gi1Dj19k17l13m0Sn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0Xou1w0X;gov,tu2S;a3e1orld trade organizati41;lls fargo,st1;fie22inghou16;l1rner br3D;-m11gree31l street journ25m11;an halNeriz3Wisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Rps;es35i1;lev2Xted natio2Uv; mobi2Kaco bePd bMeAgi frida9h3im horto2Tmz,o1witt2W;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen33daily ma2Xguess w2holli0rolling st1Ms1w2;mashing pumpki2Ouprem0;ho;ea1lack eyed pe3Fyrds;ch bo1tl0;ys;l2s1;co,la m12;efoni07us;a6e4ieme2Gnp,o2pice gir5ta1ubaru;rbucks,to2N;ny,undgard1;en;a2Rx pisto1;ls;few25insbu26msu1X;.e.m.,adiohead,b6e3oyal 1yan2X;b1dutch she4;ank;/max,aders dige1Ed 1vl32;bu1c1Uhot chili peppe2Klobst28;ll;c,s;ant2Vizno2F;an5bs,e3fiz24hilip morrBi2r1;emier27octer & gamb1Rudenti14;nk floyd,zza hut;psi28tro1uge08;br2Qchina,n2Q; 2ason1Xda2G;ld navy,pec,range juli2xf1;am;us;a9b8e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0K;l,s;c,st1Etflix,w1; 1sweek;kids on the block,york08;a,c;nd1Us2t1;ional aca2Fo,we0Q;a,cYd0O;aAcdonald9e5i3lb,o1tv,yspace;b1Nnsanto,ody blu0t1;ley crue,or0O;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt13z1Y;'ore09a3e1g,ittle caesa1Ktd;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1K;art;iffy lu0Lo3pmorgan1sa;! cha1;se;hnson & johns1Sy d1R;bm,hop,n1tv;c,g,te1;l,rpol; & m,asbro,ewlett-packaTi3o1sbc,yundai;me dep1n1J;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Iu1;cci,ns n ros0;ldman sachs,o1;dye1g0B;ar;axo smith kliZencore;electr0Im1;oto0V;a3bi,da,edex,i1leetwood mac,oGrito-l0A;at,nancial1restoV; tim0;cebook,nnie mae;b06sa,u3xxon1; m1m1;ob0H;!rosceptics;aiml0Ae5isney,o3u1;nkin donuts,po0Wran dur1;an;j,w j1;on0;a,f leppa3ll,p2r spiegZstiny's chi1;ld;eche mode,t;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra05;al;!ca c5l4m1o0Ast05;ca2p1;aq;st;dplMgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Hy;dbury,pital o1rl's jr;ne;aGbc,eCfAl6mw,ni,o2p,r1;exiteeWos;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roX;ckbuster video,omingda1;le; g1g1;oodriN;cht3e ge0n & jer2rkshire hathaw1;ay;ryH;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bXcSdidRerosmith,ig,lLmFnheuser-busEol,ppleAr7s3t&t,v2y1;er;is,on;hland2s1;n,ociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c\",\n \"Demonym\": \"true¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an\",\n \"Possessive\": \"true¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne\",\n \"Currency\": \"true¦$,aud,bScQdLeurKfJgbp,hkd,iIjpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotySł;en,uanR;af,of;h0t5;e0il5;k0q0;elM;iel,oubleLp,upeeL;e2ound st0;er0;lingI;n0soH;ceGn0;ies,y;e0i8;i,mpi7;n,r0wanzaCyatC;!onaBw;ls,nr;ori7ranc9;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s\",\n \"City\": \"true¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,sario,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg\",\n \"Abbreviation\": \"true¦a08b05cZdXeUfSgRhQiPjNkanMlKmGnEoDpCque,rAs6t4u3v2w0;is0y00;!c;a,s,t;niv,safa,t;ce,e0;nn,x;ask,e1fc,gt,ir,r,t,u0;pt,rg;nDp0;!t;d,e0;pAs,v;a,d,ennGhd,l,rof,vt;ct,kla,nt,p,rd;eb0ov;!r;a2d,essrs,i1lle,me,r5s0t;!tr;nn,ster;!j,r;it,lb,t0;!d;!s;an,r,u0;l,n;a,da,e,nc;on,wy;a,en,ov;eb,l0t,y;!a;g,s1tc,x0;!p;p,q;ak,e0ist,r;c,pt,t;a3ca,l,m2o0pl,res,t;!l0m1nn,rp;!o;dr;!l0pt;!if;a,c,l1r0;ig,os;!dg,vd;d3l2pr,r1ss0tty,ug,ve;n,t;c,iz;!ta;!j,m,v\",\n \"Place\": \"true¦a07b05cZdYeXfVgRhQiOjfk,kMlKmHneEoDp9que,rd,s8t5u4v3w0yyz;is1y0;!o;!c;a,t;pYsafa,t;e1he 0;bronx,hamptons;nn,x;ask,fo,oho,t,under6yd;a2e1h0;l,x;k,nnK;!cifX;kla,nt;b1w eng0;land;!r;a1co,i0t,uc;dKnn;libu,nhattS;a0gw,hr;s,x;an0ul;!s;a0cn,da,ndianMst;!x;arlem,kg,nd,wy;a2re0;at 0enwich;britain,lak6;!y village;co,l0ra;!a;urope,verglad2;ak,en,fw,ist,own4xb;al4dg,gk,hina3l2o1r0t;es;lo,nn;!t;town;!if;cn,e0kk,lvd,rooklyn;l air,verly hills;frica,lta,m5ntarct2r1sia,tl0ve;!ant1;ct0iz;ic0; oce0;an;ericas,s\",\n \"Country\": \"true¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an\",\n \"Region\": \"true¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma\",\n \"FemaleName\": \"true¦0:FY;1:G2;2:FR;3:FD;4:FC;5:EP;6:ER;7:FS;8:GF;9:EZ;A:GB;B:E5;C:FO;D:FL;E:G8;F:EG;aE2bD4cB8dAIe9Gf91g8Hh83i7Sj6Uk60l4Om38n2To2Qp2Fqu2Er1Os0Qt04ursu6vUwOyLzG;aJeHoG;e,la,ra;lGna;da,ma;da,ra;as7EeHol1TvG;et5onB9;le0sen3;an9endBNhiB4iG;lInG;if3AniGo0;e,f39;a,helmi0lGma;a,ow;aMeJiG;cHviG;an9XenG1;kCZtor3;da,l8Vnus,rG;a,nGoniD2;a,iDC;leGnesEC;nDLrG;i1y;aSePhNiMoJrGu6y4;acG3iGu0E;c3na,sG;h9Mta;nHrG;a,i;i9Jya;a5IffaCGna,s7;al3eGomasi0;a,l8Go6Xres1;g7Uo6WrHssG;!a,ie;eFi,ri8;bNliMmKnIrHs7tGwa0;ia0um;a,yn;iGya;a,ka,s7;a4e4iGmCAra;!ka;a,t7;at7it7;a05carlet2Ye04hUiSkye,oQtMuHyG;bFJlvi1;e,sHzG;an2Tet5ie,y;anGi8;!a,e,nG;aDe;aIeG;fGl3DphG;an2;cF8r6;f3nGphi1;d4ia,ja,ya;er4lv3mon1nGobh75;dy;aKeGirlBLo0y6;ba,e0i6lIrG;iGrBPyl;!d70;ia,lBV;ki4nIrHu0w0yG;la,na;i,leAon,ron;a,da,ia,nGon;a,on;l5Yre0;bMdLi9lKmIndHrGs7vannaD;aDi0;ra,y;aGi4;nt7ra;lBNome;e,ie;in1ri0;a02eXhViToHuG;by,thBK;bQcPlOnNsHwe0xG;an94ie,y;aHeGie,lE;ann8ll1marBFtB;!lGnn1;iGyn;e,nG;a,d7W;da,i,na;an9;hel53io;bin,erByn;a,cGkki,na,ta;helBZki;ea,iannDXoG;da,n12;an0bIgi0i0nGta,y0;aGee;!e,ta;a,eG;cARkaD;chGe,i0mo0n5EquCDvCy0;aCCelGi9;!e,le;een2ia0;aMeLhJoIrG;iGudenAW;scil1Uyamva9;lly,rt3;ilome0oebe,ylG;is,lis;arl,ggy,nelope,r6t4;ige,m0Fn4Oo6rvaBBtHulG;a,et5in1;ricGsy,tA8;a,e,ia;ctav3deHfAWlGphAW;a,ga,iv3;l3t5;aQePiJoGy6;eHrG;aDeCma;ll1mi;aKcIkGla,na,s7ta;iGki;!ta;hoB2k8BolG;a,eBH;!mh;l7Tna,risF;dIi5PnHo23taG;li1s7;cy,et5;eAiCO;a01ckenz2eViLoIrignayani,uriBGyG;a,rG;a,na,tAS;i4ll9XnG;a,iG;ca,ka,qB4;a,chOkaNlJmi,nIrGtzi;aGiam;!n9;a,dy,erva,h,n2;a,dIi9JlG;iGy;cent,e;red;!e6;ae6el3G;ag4KgKi,lHrG;edi61isFyl;an2iGliF;nGsAM;a,da;!an,han;b08c9Ed06e,g04i03l01nZrKtJuHv6Sx87yGz2;a,bell,ra;de,rG;a,eC;h75il9t2;a,cSgOiJjor2l6In2s7tIyG;!aGbe5QjaAlou;m,n9S;a,ha,i0;!aIbALeHja,lEna,sGt53;!a,ol,sa;!l06;!h,m,nG;!a,e,n1;arIeHie,oGr3Kueri5;!t;!ry;et3IiB;elGi61y;a,l1;dGon,ue6;akranBy;iGlo36;a,ka,n9;a,re,s2;daGg2;!l2W;alEd2elGge,isBGon0;eiAin1yn;el,le;a0Ie08iWoQuKyG;d3la,nG;!a,dHe9SnGsAQ;!a,e9R;a,sAO;aB1cJelIiFlHna,pGz;e,iB;a,u;a,la;iGy;a2Ae,l25n9;is,l1GrHtt2uG;el6is1;aIeHi8na,rG;a6Zi8;lei,n1tB;!in1;aQbPd3lLnIsHv3zG;!a,be4Ket5z2;a,et5;a,dG;a,sGy;ay,ey,i,y;a,iaIlG;iGy;a8Ge;!n4F;b7Terty;!n5R;aNda,e0iLla,nKoIslARtGx2;iGt2;c3t3;la,nGra;a,ie,o4;a,or1;a,gh,laG;!ni;!h,nG;a,d4e,n4N;cNdon7Si6kes7na,rMtKurIvHxGy6;mi;ern1in3;a,eGie,yn;l,n;as7is7oG;nya,ya;a,isF;ey,ie,y;aZeUhadija,iMoLrIyG;lGra;a,ee,ie;istGy5B;a,en,iGy;!e,n48;ri,urtn9A;aMerLl99mIrGzzy;a,stG;en,in;!berlG;eGi,y;e,y;a,stC;!na,ra;el6PiJlInHrG;a,i,ri;d4na;ey,i,l9Qs2y;ra,s7;c8Wi5XlOma6nyakumari,rMss5LtJviByG;!e,lG;a,eG;e,i78;a5EeHhGi3PlEri0y;ar5Cer5Cie,leCr9Fy;!lyn73;a,en,iGl4Uyn;!ma,n31sF;ei72i,l2;a04eVilToMuG;anKdJliGst56;aHeGsF;!nAt0W;!n8X;i2Ry;a,iB;!anLcelEd5Vel71han6IlJni,sHva0yG;a,ce;eGie;fi0lEph4X;eGie;en,n1;!a,e,n36;!i10lG;!i0Z;anLle0nIrHsG;i5Qsi5Q;i,ri;!a,el6Pif1RnG;a,et5iGy;!e,f1P;a,e72iHnG;a,e71iG;e,n1;cLd1mi,nHqueliAsmin2Uvie4yAzG;min8;a8eHiG;ce,e,n1s;!lGsFt06;e,le;inHk2lEquelG;in1yn;da,ta;lPmNnMo0rLsHvaG;!na;aHiGob6U;do4;!belGdo4;!a,e,l2G;en1i0ma;a,di4es,gr5R;el9ogG;en1;a,eAia0o0se;aNeKilHoGyacin1N;ll2rten1H;aHdGlaH;a,egard;ry;ath0WiHlGnrietBrmiAst0W;en24ga;di;il75lKnJrGtt2yl75z6D;iGmo4Fri4G;etG;!te;aDnaD;ey,l2;aYeTiOlMold12rIwG;enGyne18;!dolE;acHetGisel9;a,chC;e,ieG;!la;adys,enGor3yn1Y;a,da,na;aJgi,lHna,ov71selG;a,e,le;da,liG;an;!n0;mYnIorgHrG;ald35i,m2Stru73;et5i5T;a,eGna;s1Nvieve;briel3Fil,le,rnet,yle;aReOio0loMrG;anHe9iG;da,e9;!cG;esHiGoi0G;n1s3V;!ca;!rG;a,en43;lHrnG;!an9;ec3ic3;rHtiGy8;ma;ah,rah;d0FileCkBl00mUn4ArRsMtLuKvG;aIelHiG;e,ta;in0Ayn;!ngel2H;geni1la,ni3R;h52ta;meral9peranJtG;eHhGrel6;er;l2Pr;za;iGma,nest29yn;cGka,n;a,ka;eJilImG;aGie,y;!liA;ee,i1y;lGrald;da,y;aTeRiMlLma,no4oJsIvG;a,iG;na,ra;a,ie;iGuiG;se;a,en,ie,y;a0c3da,nJsGzaH;aGe;!beG;th;!a,or;anor,nG;!a;in1na;en,iGna,wi0;e,th;aWeKiJoGul2U;lor51miniq3Yn30rGtt2;a,eCis,la,othGthy;ea,y;an09naDonAx2;anPbOde,eNiLja,lImetr3nGsir4U;a,iG;ce,se;a,iHla,orGphiA;es,is;a,l5J;dGrdG;re;!d4Mna;!b2CoraDra;a,d4nG;!a,e;hl3i0mMnKphn1rHvi1WyG;le,na;a,by,cHia,lG;a,en1;ey,ie;a,et5iG;!ca,el1Aka;arGia;is;a0Qe0Mh04i02lUoJrHynG;di,th3;istGy04;al,i0;lOnLrHurG;tn1D;aId28iGn28riA;!nG;a,e,n1;!l1S;n2sG;tanGuelo;ce,za;eGleC;en,t5;aIeoHotG;il4B;!pat4;ir8rIudG;et5iG;a,ne;a,e,iG;ce,sX;a4er4ndG;i,y;aPeMloe,rG;isHyG;stal;sy,tG;aHen,iGy;!an1e,n1;!l;lseHrG;!i8yl;a,y;nLrG;isJlHmG;aiA;a,eGot5;n1t5;!sa;d4el1PtG;al,el1O;cHlG;es5i3F;el3ilG;e,ia,y;iYlXmilWndVrNsLtGy6;aJeIhGri0;erGleCrEy;in1;ri0;li0ri0;a2GsG;a2Fie;a,iMlKmeIolHrG;ie,ol;!e,in1yn;lGn;!a,la;a,eGie,y;ne,y;na,sF;a0Di0D;a,e,l1;isBl2;tlG;in,yn;arb0CeYianXlVoTrG;andRePiIoHyG;an0nn;nwEok8;an2NdgKg0ItG;n27tG;!aHnG;ey,i,y;ny;etG;!t8;an0e,nG;da,na;i8y;bbi8nG;iBn2;ancGossom,ythe;a,he;ca;aRcky,lin9niBrNssMtIulaDvG;!erlG;ey,y;hHsy,tG;e,i0Zy8;!anG;ie,y;!ie;nGt7yl;adHiG;ce;et5iA;!triG;ce,z;a4ie,ra;aliy29b24d1Lg1Hi19l0Sm0Nn01rWsNthe0uJvIyG;anGes7;a,na;a,r25;drIgusHrG;el3;ti0;a,ey,i,y;hHtrG;id;aKlGt1P;eHi8yG;!n;e,iGy;gh;!nG;ti;iIleHpiB;ta;en,n1t5;an19elG;le;aYdWeUgQiOja,nHtoGya;inet5n3;!aJeHiGmI;e,ka;!mGt5;ar2;!belHliFmT;sa;!le;ka,sGta;a,sa;elGie;a,iG;a,ca,n1qG;ue;!t5;te;je6rea;la;!bHmGstas3;ar3;el;aIberHel3iGy;e,na;!ly;l3n9;da;aTba,eNiKlIma,yG;a,c3sG;a,on,sa;iGys0J;e,s0I;a,cHna,sGza;a,ha,on,sa;e,ia;c3is7jaIna,ssaIxG;aGia;!nd4;nd4;ra;ia;i0nHyG;ah,na;a,is,naD;c7da,leCmLnslKsG;haDlG;inGyW;g,n;!h;ey;ee;en;at7g2nG;es;ie;ha;aVdiSelLrG;eIiG;anLenG;a,e,ne;an0;na;aKeJiHyG;nn;a,n1;a,e;!ne;!iG;de;e,lEsG;on;yn;!lG;iAyn;ne;agaJbHiG;!gaI;ey,i8y;!e;il;ah\",\n \"WeekDay\": \"true¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s\",\n \"Month\": \"true¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il\",\n \"FirstName\": \"true¦aEblair,cCdevBj8k6lashawn,m3nelly,quinn,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0r9;ls7nyatta,rry;am0ess1ude;ie,m0;ie;an,on;as0heyenne;ey,sidy;lex1ndra,ubr0;ey;is\",\n \"LastName\": \"true¦0:34;1:39;2:3B;3:2Y;4:2E;5:30;a3Bb31c2Od2Ee2Bf25g1Zh1Pi1Kj1Ek17l0Zm0Nn0Jo0Gp05rYsMtHvFwCxBy8zh6;a6ou,u;ng,o;a6eun2Uoshi1Kun;ma6ng;da,guc1Zmo27sh21zaR;iao,u;a7eb0il6o3right,u;li3Bs1;gn0lk0ng,tanabe;a6ivaldi;ssilj37zqu2;a9h8i2Go7r6sui,urn0;an,ynisJ;lst0Prr1Uth;at1Uomps1;kah0Vnaka,ylor;aEchDeChimizu,iBmiAo9t7u6zabo;ar2lliv2AzuE;a6ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n7sa6to;ki;ch2dLtos,z;amBeag1Zi9o7u6;bio,iz,sD;b6dri1MgIj0Tme24osevelt,ssi,ux;erts,ins1;c6ve0F;ci,hards1;ir2os;aEeAh8ic6ow20;as6hl0;so;a6illips;m,n1T;ders5et8r7t6;e0Nr4;ez,ry;ers;h21rk0t6vl4;el,te0J;baBg0Blivei01r6;t6w1O;ega,iz;a6eils1guy5ix1owak,ym1E;gy,ka6var1K;ji6muW;ma;aEeCiBo8u6;ll0n6rr0Bssolini,ñ6;oz;lina,oKr6zart;al0Me6r0U;au,no;hhail4ll0;rci0ssi6y0;!er;eWmmad4r6tsu07;in6tin2;!o;aCe8i6op2uo;!n6u;coln,dholm;fe7n0Qr6w0J;oy;bv6v6;re;mmy,rs5u;aBennedy,imuAle0Lo8u7wo6;k,n;mar,znets4;bay6vacs;asY;ra;hn,rl9to,ur,zl4;aAen9ha3imen2o6u3;h6nYu3;an6ns1;ss1;ki0Es5;cks1nsse0D;glesi9ke8noue,shik7to,vano6;u,v;awa;da;as;aBe8itchcock,o7u6;!a3b0ghNynh;a3ffmann,rvat;mingw7nde6rN;rs1;ay;ns5rrQs7y6;asDes;an4hi6;moJ;a9il,o8r7u6;o,tierr2;ayli3ub0;m2nzal2;nd6o,rcia;hi;erAis9lor8o7uj6;ita;st0urni0;es;ch0;nand2;d7insteHsposi6vaL;to;is1wards;aCeBi9omin8u6;bo6rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw7vi6;es,s;in;aFhBlarkAo6;h5l6op0rbyn,x;em7li6;ns;an;!e;an8e7iu,o6ristens5u3we;i,ng,u3w,y;!n,on6u3;!g;mpb7rt0st6;ro;ell;aBe8ha3lanco,oyko,r6yrne;ooks,yant;ng;ck7ethov5nnett;en;er,ham;ch,h8iley,rn6;es,i0;er;k,ng;dDl9nd6;ers6rA;en,on,s1;on;eks7iy8var2;ez;ej6;ev;ams\",\n \"MaleName\": \"true¦0:CE;1:BL;2:C2;3:BT;4:B5;5:9V;6:BZ;7:AT;8:BD;9:AX;A:AO;aB4bA8c97d87e7Gf6Yg6Gh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt06u05v00wNxavi3yGzB;aBor0;cBh8Ine;hCkB;!aB1;ar51eB0;ass2i,oCuB;sDu25;nEsDusB;oBsC;uf;ef;at0g;aJeHiCoByaAP;lfgang,odrow;lBn1O;bDey,frBJlB;aA5iB;am,e,s;e89ur;i,nde5sB;!l7t1;de,lCrr6yB;l1ne;lBt3;a93y;aEern1iB;cCha0nceBrg9Bva0;!nt;ente,t5A;lentin49n8Yughn;lyss4Msm0;aTeOhKiIoErCyB;!l3ro8s1;av9QeBist0oy,um0;nt9Iv54y;bDd7XmBny;!as,mBoharu;aAYie,y;i83y;mBt9;!my,othy;adDeoCia7DomB;!as;!do7M;!de9;dErB;en8HrB;an8GeBy;ll,n8F;!dy;dgh,ic9Tnn3req,ts45;aRcotPeNhJiHoFpenc3tBur1Oylve8Hzym1;anDeBua7B;f0phAFvBwa7A;e57ie;!islaw,l7;lom1nA3uB;leyma8ta;dBl7Jm1;!n7;aDeB;lBrm0;d1t1;h6Sne,qu0Uun,wn,y8;aBbasti0k1Xl41rg40th,ymo9I;m9n;!tB;!ie,y;lCmBnti21q4Iul;!mAu4;ik,vato6V;aWeShe92iOoFuCyB;an,ou;b6LdCf9pe6QssB;!elAI;ol2Uy;an,bIcHdGel,geFh0landA9mEnDry,sCyB;!ce;coe,s;!a95nA;an,eo;l3Jr;e4Qg3n7olfo,ri68;co,ky;bAe9U;cBl7;ar5Oc5NhCkBo;!ey,ie,y;a85ie;gCid,ub6x,yBza;ansh,nS;g8WiB;na8Ss;ch5Yfa4lDmCndBpha4sh6Uul,ymo70;al9Yol2By;i9Ion;f,ph;ent2inB;cy,t1;aFeDhilCier62ol,reB;st1;!ip,lip;d9Brcy,tB;ar,e2V;b3Sdra6Ft44ul;ctav2Vliv3m96rFsCtBum8Uw6;is,to;aCc8SvB;al52;ma;i,l49vJ;athJeHiDoB;aBel,l0ma0r2X;h,m;cCg4i3IkB;h6Uola;hol5XkBol5X;!ol5W;al,d,il,ls1vB;il50;anBy;!a4i4;aWeTiKoFuCyB;l21r1;hamCr5ZstaB;fa,p4G;ed,mF;dibo,e,hamDis1XntCsBussa;es,he;e,y;ad,ed,mB;ad,ed;cGgu4kElDnCtchB;!e5;a78ik;house,o03t1;e,olB;aj;ah,hBk7;a4eB;al,l;hClv2rB;le,ri5v2;di,met;ck,hNlLmOnu4rHs1tDuricCxB;!imilian8Cwe5;e,io;eo,hCi52tB;!eo,hew,ia;eBis;us,w;cDio,k86lCqu6Gsha5tBv2;i2Hy;in,on;!el,oKus;achBcolm,ik;ai,y;amBdi,moud;adB;ou;aReNiMlo2RoIuCyB;le,nd1;cEiDkBth3;aBe;!s;gi,s;as,iaB;no;g0nn6RrenDuBwe5;!iB;e,s;!zo;am,on4;a7Bevi,la4SnDoBst3vi;!nB;!a60el;!ny;mCnBr67ur4Twr4T;ce,d1;ar,o4N;aIeDhaled,iBrist4Vu48y3B;er0p,rB;by,k,ollos;en0iEnBrmit,v2;!dCnBt5C;e0Yy;a5ri4N;r,th;na68rBthem;im,l;aYeQiOoDuB;an,liBst2;an,o,us;aqu2eJhnInGrEsB;eChBi7Bue;!ua;!ph;dBge;an,i,on;!aBny;h,s,th4X;!ath4Wie,nA;!l,sBy;ph;an,e,mB;!mA;d,ffGrDsB;sBus;!e;a5JemCmai8oBry;me,ni0O;i6Uy;!e58rB;ey,y;cHd6kGmFrDsCvi3yB;!d6s1;on,p3;ed,od,rBv4M;e4Zod;al,es,is1;e,ob,ub;k,ob,quB;es;aNbrahMchika,gKkeJlija,nuIrGsDtBv0;ai,sB;uki;aBha0i6Fma4sac;ac,iaB;h,s;a,vinBw2;!g;k,nngu52;!r;nacBor;io;im;in,n;aJeFina4VoDuByd56;be25gBmber4CsD;h,o;m3ra33sBwa3X;se2;aDctCitCn4ErB;be20m0;or;th;bKlJmza,nIo,rDsCyB;a43d6;an,s0;lEo4FrDuBv7;hi40ki,tB;a,o;is1y;an,ey;k,s;!im;ib;aQeMiLlenKoIrEuB;illerCsB;!tavo;mo;aDegBov3;!g,orB;io,y;dy,h57nt;nzaBrd1;lo;!n;lbe4Qno,ovan4R;ne,oDrB;aBry;ld,rd4U;ffr7rge;bri4l6rBv2;la1Zr3Eth,y;aReNiLlJorr0IrB;anDedBitz;!dAeBri24;ri23;cDkB;!ie,lB;in,yn;esJisB;!co,zek;etch3oB;yd;d4lBonn;ip;deriDliCng,rnB;an01;pe,x;co;bi0di;arZdUfrTit0lNmGnFo2rCsteb0th0uge8vBym6zra;an,ere2V;gi,iCnBrol,v2w2;est45ie;c07k;och,rique,zo;aGerFiCmB;aFe2P;lCrB;!h0;!io;s1y;nu4;be09d1iEliDmCt1viBwood;n,s;er,o;ot1Ts;!as,j43sB;ha;a2en;!dAg32mEuCwB;a25in;arB;do;o0Su0S;l,nB;est;aYeOiLoErDuCwByl0;ay8ight;a8dl7nc0st2;ag0ew;minFnDri0ugCyB;le;!l03;!a29nBov0;e5ie,y;go,icB;!k;armuCeBll1on,rk;go;id;anIj0lbeHmetri9nFon,rEsDvCwBxt3;ay8ey;en,in;hawn,mo08;ek,ri0F;is,nBv3;is,y;rt;!dB;re;lKmInHrDvB;e,iB;!d;en,iDne5rByl;eBin,yl;l2Vn;n,o,us;!e,i4ny;iBon;an,en,on;e,lB;as;a06e04hWiar0lLoGrEuCyrB;il,us;rtB;!is;aBistobal;ig;dy,lEnCrB;ey,neli9y;or,rB;ad;by,e,in,l2t1;aGeDiByI;fBnt;fo0Ct1;meCt9velaB;nd;nt;rDuCyB;!t1;de;enB;ce;aFeErisCuB;ck;!tB;i0oph3;st3;d,rlBs;eBie;s,y;cBdric,s11;il;lEmer1rB;ey,lCro5y;ll;!os,t1;eb,v2;ar02eUilTlaSoPrCuByr1;ddy,rtI;aJeEiDuCyB;an,ce,on;ce,no;an,ce;nCtB;!t;dCtB;!on;an,on;dCndB;en,on;!foBl7y;rd;bCrByd;is;!by;i8ke;al,lA;nFrBshoi;at,nCtB;!r10;aBie;rd0S;!edict,iCjam2nA;ie,y;to;n7rBt;eBy;tt;ey;ar0Xb0Nd0Jgust2hm0Gid6ja0ElZmXnPputsiOrFsaEuCveBya0ziz;ry;gust9st2;us;hi;aIchHi4jun,maFnDon,tBy0;hBu06;ur;av,oB;ld;an,nd0A;el;ie;ta;aq;dGgel05tB;hoEoB;i8nB;!i02y;ne;ny;reBy;!as,s,w;ir,mBos;ar;an,beOd6eIfFi,lEonDphonHt1vB;aMin;on;so,zo;an,en;onCrB;edP;so;c,jaEksandDssaExB;!and3;er;ar,er;ndB;ro;rtH;ni;en;ad,eB;d,t;in;aColfBri0vik;!o;mBn;!a;dFeEraCuB;!bakr,lfazl;hBm;am;!l;allEel,oulaye,ulB;!lCrahm0;an;ah,o;ah;av,on\",\n \"Person\": \"true¦ashton kutchSbRcMdKeIgastNhGinez,jEkDleCmBnettJoAp8r4s3t2v0;a0irgin maG;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussain,carlett johanssJlobodan milosevic,uB;ay romano,eese witherspoIo1ush limbau0;gh;d stewart,nald0;inho,o;a0ipJ;lmIris hiltD;prah winfrFra;essiaen,itt romnEubarek;bron james,e;anye west,iefer sutherland,obe bryant;aime,effers8k rowli0;ng;alle ber0itlBulk hogan;ry;ff0meril lagasse,zekiel;ie;a0enzel washingt2ick wolf;lt1nte;ar1lint0ruz;on;dinal wols1son0;! palm2;ey;arack obama,rock;er\",\n \"Verb\": \"true¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en\",\n \"PhrasalVerb\": \"true¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2fast,oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut\",\n \"Modal\": \"true¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld\",\n \"Adjective\": \"true¦0:75;1:7K;2:7Q;3:7J;4:7C;5:5C;6:48;7:49;8:4S;9:61;A:7H;B:70;C:6Z;D:73;E:5X;a6Jb65c5Rd57e4Tf49g41h3Qi35j33k32l2Rm2Gn27o1Rp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6C;d6Ezy;despr75s5G;!sa7;eGlFste26;co1Il o4L;!k5;aGiFola4B;b7Tce versa,ol55;ca2gabo63nilla;ltWnJpGrb5Asu4tterF;!moC; f34b1OpGsFti1H;ca7et,ide dMtairs;er,i3N;aPbeco6Rconvin27deMeLfair,ivers4knKprecedYrIsGwF;iel20ritt5Z;i1VuF;pervis0specti3;eFu5;cognLgul6Hl6H;own;ndi3v5Txpect0;cid0rF;!grou5OsF;iz0tood;b7ppeaLssu6GuthorF;iz0;i24ra;aJeHhough4PoGrF;i1oubl0;geth8p,rpB;en5QlFm50rr2Ust0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3EoPpOqueami3EtJuFymb64;bHi gener55pFrprisi3;erFre0L;! dup8b,i29;du0seq4U;anda6UeIi0PrFy38;aightFip0; fFfF;or5B;adfaCreotyp0;aEec2Gir1JlendBot on; call0le,mb8phist1XrFu0Xvi42;dBry;gnifica2nF;ceEg7;am2Pe8ocki3ut;cFda1em5lfi2Yni1Wpa69re6;o1Gr3W;at58ient28reec58;cr0me,ns serif;aMeIiGoF;buCtt4UuSy4;ghtFv4;!-29f9;ar,bel,condi1du63fres52lHpublic3WsFtard0;is48oF;lu1na2;e1Euc46;bBciF;al,st;aQeOicayu6lacBopuliCrGuF;bl5Amp0;eJiGoF;!b0AfuDmi32p8;mGor,sFva1;ti6;a4We;ciDmF;a0IiF;er,um;ac20rFti1;feAma2Uplexi3v34;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Msi46;en,posi1; boa5Gg2Kli6;!ay; gua5EbFli6;eat;eHsF;cFer0Hole1;e6uE;d2Tse;ak0eMiLoFua4P;nJrGtF;ab7;thF;!eF;rn;chala2descri50stop;ght5;arby,cessa3Xighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuE;di4FnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abEho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3D;!-0C;nguBst,tt8;ap1Tind5no0A;agg0uF;niOstifi0veni7;de4gno4Clleg4mSnHpso 1WrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenDoxF;ic37;a6i2S;a1er,oce2;iGoF;or;reA;deq3Kppr2Z;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0R;d2RnD;aKelJiHoFumdr3C;neCok0rrFs07ur5;if2T;ghfalut1PspF;an2R;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Kiga23lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Eob4;aUeOinNlMoHrF;a1UeFoz1L;e2Eq13tf9;oHrF; keeps,eFm8tuna1;g05ign;liF;sh;ag30ue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lDr Gux,voF;ri1uri1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiE;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erD;creHeas0gruntl0honeCordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarElJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraBg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainCgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerD;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt\",\n \"Comparable\": \"true¦0:40;1:4H;2:44;3:4A;4:2X;5:3W;a4Nb43c3Nd3Ce34f2Qg2Eh23i1Uj1Tk1Ql1Hm1Bn15o13p0Tqu0Rr0IsRtKuIvFw7y6za11;ell26ou3;aBe9hi1Xi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Lt;k,ry;n1Sr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Lse5;like0ti1;aAen9hi8i7ough,r6;anqu2Pen1ue;dy,g3Tme0ny,r09;ck,n,rs2Q;d41se;ll,me,rt,s6wd46;te5;aVcarUeThRiQkin0FlMmKoHpGqua1GtAu7w6;eet,ift;b7dd14per0Gr6;e,re2I;sta2Gt4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Gn0V;a1ep,rn;le,rk;e23i3Gright0;ci29ft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g36m6;!y;ek,nd3E;ck,l0mp4;a6iTort,rill,y;dy,ll0Yrp;cu0Sve0Sxy;ce,ed,y;d,fe,int0l1Wv15;aBe9i8o6ude;mantic,o1Jsy,u6;gh,nd;ch,pe,tzy;a6d,mo0I;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aEhoDi1RlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fouZud;ey,k0;li05or,te1C;ain,easa2;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd\",\n \"TextValue\": \"true¦bMeIfChundredNmMnin9one,qu8s6t0zeroN;enMh3rLw0;e0o;l0ntC;fGve;ir0ousandIree;d,t5;e0ix7;cond,ptEven6xtE;adrDintD;e0th;!t0;e9ie8y;i3o0;rt1ur0;!t2;ie4y;ft0rst,ve;e3h,ie2y;ight0lev2;!e1h,ie0y;th;en1;illion0;!th\",\n \"Ordinal\": \"true¦bGeDf9hundredHmGnin7qu6s4t0zeroH;enGh1rFwe0;lfFn9;ir0ousandE;d,t4;e0ixt9;cond,ptAvent8xtA;adr9int9;et0th;e6ie8;i2o0;r0urt3;tie5;ft1rst;ight0lev1;e0h,ie2;en1;illion0;th\",\n \"Cardinal\": \"true¦bGeDf7hundred,mGnine9one,qu6s4t0zero;en,h2rFw0;e0o;lve,n7;irt8ousand,ree;e0ix4;ptAven3xtA;adr9int9;i3o0;r1ur0;!t2;ty;ft0ve;e2y;ight0lev1;!e0y;en;illion\",\n \"Expression\": \"true¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la\",\n \"Adverb\": \"true¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori\",\n \"Preposition\": \"true¦'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut\",\n \"Determiner\": \"true¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er\"\n}","const entity = ['Person', 'Place', 'Organization']\n\nmodule.exports = {\n Noun: {\n notA: ['Verb', 'Adjective', 'Adverb'],\n },\n // - singular\n Singular: {\n isA: 'Noun',\n notA: 'Plural',\n },\n //a specific thing that's capitalized\n ProperNoun: {\n isA: 'Noun',\n },\n\n // -- people\n Person: {\n isA: ['ProperNoun', 'Singular'],\n notA: ['Place', 'Organization'],\n },\n FirstName: {\n isA: 'Person',\n },\n MaleName: {\n isA: 'FirstName',\n notA: ['FemaleName', 'LastName'],\n },\n FemaleName: {\n isA: 'FirstName',\n notA: ['MaleName', 'LastName'],\n },\n LastName: {\n isA: 'Person',\n notA: ['FirstName'],\n },\n Honorific: {\n isA: 'Noun',\n notA: ['FirstName', 'LastName'],\n },\n\n // -- places\n Place: {\n isA: 'Singular',\n notA: ['Person', 'Organization'],\n },\n Country: {\n isA: ['Place', 'ProperNoun'],\n notA: ['City'],\n },\n City: {\n isA: ['Place', 'ProperNoun'],\n notA: ['Country'],\n },\n Region: {\n isA: ['Place', 'ProperNoun'],\n },\n Address: {\n isA: 'Place',\n },\n\n //---Orgs---\n Organization: {\n isA: ['Singular', 'ProperNoun'],\n notA: ['Person', 'Place'],\n },\n SportsTeam: {\n isA: 'Organization',\n },\n School: {\n isA: 'Organization',\n },\n Company: {\n isA: 'Organization',\n },\n\n // - plural\n Plural: {\n isA: 'Noun',\n notA: ['Singular'],\n },\n //(not plural or singular)\n Uncountable: {\n isA: 'Noun',\n },\n Pronoun: {\n isA: 'Noun',\n notA: entity,\n },\n //a word for someone doing something -'plumber'\n Actor: {\n isA: 'Noun',\n notA: entity,\n },\n //a gerund-as-noun - 'swimming'\n Activity: {\n isA: 'Noun',\n notA: ['Person', 'Place'],\n },\n //'kilograms'\n Unit: {\n isA: 'Noun',\n notA: entity,\n },\n //'Canadians'\n Demonym: {\n isA: ['Noun', 'ProperNoun'],\n notA: entity,\n },\n //`john's`\n Possessive: {\n isA: 'Noun',\n // notA: 'Pronoun',\n },\n}\n","module.exports = {\n Verb: {\n notA: ['Noun', 'Adjective', 'Adverb', 'Value'],\n },\n // walks\n PresentTense: {\n isA: 'Verb',\n notA: ['PastTense', 'Copula', 'FutureTense'],\n },\n // neutral form - 'walk'\n Infinitive: {\n isA: 'PresentTense',\n notA: ['PastTense', 'Gerund'],\n },\n // walking\n Gerund: {\n isA: 'PresentTense',\n notA: ['PastTense', 'Copula', 'FutureTense'],\n },\n // walked\n PastTense: {\n isA: 'Verb',\n notA: ['FutureTense'],\n },\n // will walk\n FutureTense: {\n isA: 'Verb',\n },\n\n // is\n Copula: {\n isA: 'Verb',\n },\n // would have\n Modal: {\n isA: 'Verb',\n notA: ['Infinitive'],\n },\n // had walked\n PerfectTense: {\n isA: 'Verb',\n notA: 'Gerund',\n },\n Pluperfect: {\n isA: 'Verb',\n },\n // shown\n Participle: {\n isA: 'Verb',\n },\n // show up\n PhrasalVerb: {\n isA: 'Verb',\n },\n //'up' part\n Particle: {\n isA: 'PhrasalVerb',\n },\n}\n","module.exports = {\n Value: {\n notA: ['Verb', 'Adjective', 'Adverb'],\n },\n Ordinal: {\n isA: 'Value',\n notA: ['Cardinal'],\n },\n Cardinal: {\n isA: 'Value',\n notA: ['Ordinal'],\n },\n RomanNumeral: {\n isA: 'Cardinal', //can be a person, too\n notA: ['Ordinal', 'TextValue'],\n },\n TextValue: {\n isA: 'Value',\n notA: ['NumericValue'],\n },\n NumericValue: {\n isA: 'Value',\n notA: ['TextValue'],\n },\n Money: {\n isA: 'Cardinal',\n },\n Percent: {\n isA: 'Value',\n },\n}\n","const anything = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Value']\n\nmodule.exports = {\n //--Adjectives--\n Adjective: {\n notA: ['Noun', 'Verb', 'Adverb', 'Value'],\n },\n // adjectives that can conjugate\n Comparable: {\n isA: ['Adjective'],\n },\n // better\n Comparative: {\n isA: ['Adjective'],\n },\n // best\n Superlative: {\n isA: ['Adjective'],\n notA: ['Comparative'],\n },\n\n NumberRange: {\n isA: ['Contraction'],\n },\n Adverb: {\n notA: ['Noun', 'Verb', 'Adjective', 'Value'],\n },\n\n // Dates:\n //not a noun, but usually is\n Date: {\n notA: ['Verb', 'Conjunction', 'Adverb', 'Preposition', 'Adjective'],\n },\n Month: {\n isA: ['Date', 'Singular'],\n notA: ['Year', 'WeekDay', 'Time'],\n },\n WeekDay: {\n isA: ['Date', 'Noun'],\n },\n\n //glue\n Determiner: {\n notA: anything,\n },\n Conjunction: {\n notA: anything,\n },\n Preposition: {\n notA: anything,\n },\n\n // what, who, why\n QuestionWord: {\n notA: ['Determiner'],\n },\n\n // peso, euro\n Currency: {},\n // ughh\n Expression: {\n notA: ['Noun', 'Adjective', 'Verb', 'Adverb'],\n },\n // dr.\n Abbreviation: {},\n\n // internet tags\n Url: {\n notA: ['HashTag', 'PhoneNumber', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'],\n },\n PhoneNumber: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'],\n },\n HashTag: {},\n AtMention: {\n isA: ['Noun'],\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'Email'],\n },\n Emoji: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'],\n },\n Emoticon: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'],\n },\n Email: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'],\n },\n\n //non-exclusive\n Auxiliary: {\n notA: ['Noun', 'Adjective', 'Value'],\n },\n Acronym: {\n notA: ['Plural', 'RomanNumeral'],\n },\n Negative: {\n notA: ['Noun', 'Adjective', 'Value'],\n },\n // if, unless, were\n Condition: {\n notA: ['Verb', 'Adjective', 'Noun', 'Value'],\n },\n}\n","// i just made these up\nconst colorMap = {\n Noun: 'blue',\n\n Verb: 'green',\n Negative: 'green',\n\n Date: 'red',\n Value: 'red',\n\n Adjective: 'magenta',\n\n Preposition: 'cyan',\n Conjunction: 'cyan',\n Determiner: 'cyan',\n Adverb: 'cyan',\n}\n\n/** add a debug color to some tags */\nconst addColors = function(tags) {\n Object.keys(tags).forEach(k => {\n if (colorMap[k]) {\n tags[k].color = colorMap[k]\n return\n }\n tags[k].isA.some(t => {\n if (colorMap[t]) {\n tags[k].color = colorMap[t]\n return true\n }\n return false\n })\n })\n return tags\n}\n\nmodule.exports = addColors\n","const unique = function(arr) {\n return arr.filter((v, i, a) => a.indexOf(v) === i)\n}\n\n//add 'downward' tags (that immediately depend on this one)\nconst inferIsA = function(tags) {\n Object.keys(tags).forEach(k => {\n let tag = tags[k]\n let len = tag.isA.length\n for (let i = 0; i < len; i++) {\n let down = tag.isA[i]\n if (tags[down]) {\n tag.isA = tag.isA.concat(tags[down].isA)\n }\n }\n // clean it up\n tag.isA = unique(tag.isA)\n })\n return tags\n}\nmodule.exports = inferIsA\n","const unique = function(arr) {\n return arr.filter((v, i, a) => a.indexOf(v) === i)\n}\n\n// crawl the tag-graph and infer any conflicts\n// faster than doing this at tag-time\nconst inferNotA = function(tags) {\n let keys = Object.keys(tags)\n keys.forEach(k => {\n let tag = tags[k]\n tag.notA = tag.notA || []\n tag.isA.forEach(down => {\n if (tags[down] && tags[down].notA) {\n // borrow its conflicts\n let notA = typeof tags[down].notA === 'string' ? [tags[down].isA] : tags[down].notA || []\n tag.notA = tag.notA.concat(notA)\n }\n })\n // any tag that lists us as a conflict, we conflict it back.\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]\n if (tags[key].notA.indexOf(k) !== -1) {\n tag.notA.push(key)\n }\n }\n // clean it up\n tag.notA = unique(tag.notA)\n })\n return tags\n}\nmodule.exports = inferNotA\n","// a lineage is all 'incoming' tags that have this as 'isA'\nconst inferLineage = function(tags) {\n let keys = Object.keys(tags)\n keys.forEach(k => {\n let tag = tags[k]\n tag.lineage = []\n // find all tags with it in their 'isA' set\n for (let i = 0; i < keys.length; i++) {\n if (tags[keys[i]].isA.indexOf(k) !== -1) {\n tag.lineage.push(keys[i])\n }\n }\n })\n return tags\n}\nmodule.exports = inferLineage\n","const inferColor = require('./_color')\nconst inferIsA = require('./_isA')\nconst inferNotA = require('./_notA')\nconst lineage = require('./_lineage')\n\nconst validate = function(tags) {\n // cleanup format\n Object.keys(tags).forEach(k => {\n let tag = tags[k]\n // ensure isA is an array\n tag.isA = tag.isA || []\n if (typeof tag.isA === 'string') {\n tag.isA = [tag.isA]\n }\n // ensure notA is an array\n tag.notA = tag.notA || []\n if (typeof tag.notA === 'string') {\n tag.notA = [tag.notA]\n }\n })\n return tags\n}\n\n// build-out the tag-graph structure\nconst inferTags = function(tags) {\n // validate data\n tags = validate(tags)\n // build its 'down tags'\n tags = inferIsA(tags)\n // infer the conflicts\n tags = inferNotA(tags)\n // debug tag color\n tags = inferColor(tags)\n // find incoming links\n tags = lineage(tags)\n return tags\n}\nmodule.exports = inferTags\n","const nouns = require('./tags/nouns')\nconst verbs = require('./tags/verbs')\nconst values = require('./tags/values')\nconst misc = require('./tags/misc')\nconst inferTags = require('./inference/index')\n\n//extend tagset with new tags\nconst addIn = function(obj, tags) {\n Object.keys(obj).forEach(k => {\n tags[k] = obj[k]\n })\n}\n\nconst build = () => {\n let tags = {}\n addIn(nouns, tags)\n addIn(verbs, tags)\n addIn(values, tags)\n addIn(misc, tags)\n // do the graph-stuff\n tags = inferTags(tags)\n return tags\n}\nmodule.exports = build()\n","\"use strict\";const BASE=36,seq=\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\",cache=seq.split(\"\").reduce(function(n,o,e){return n[o]=e,n},{}),toAlphaCode=function(n){if(void 0!==seq[n])return seq[n];let o=1,e=36,t=\"\";for(;n>=e;n-=e,o++,e*=36);for(;o--;){const o=n%36;t=String.fromCharCode((o<10?48:55)+o)+t,n=(n-o)/36}return t},fromAlphaCode=function(n){if(void 0!==cache[n])return cache[n];let o=0,e=1,t=36,r=1;for(;e=0;e--,r*=36){let t=n.charCodeAt(e)-48;t>10&&(t-=7),o+=t*r}return o};var encoding={toAlphaCode:toAlphaCode,fromAlphaCode:fromAlphaCode},symbols=function(n){const o=new RegExp(\"([0-9A-Z]+):([0-9A-Z]+)\");for(let e=0;e{let s=n.nodes[t];\"!\"===s[0]&&(o.push(r),s=s.slice(1));const c=s.split(/([A-Z0-9,]+)/g);for(let s=0;s{const e=o.split(\"¦\");return n[e[0]]=e[1],n},{}),e={};return Object.keys(o).forEach(function(n){const t=unpack_1(o[n]);\"true\"===n&&(n=!0);for(let o=0;o 1) {\n //cache the beginning word\n world.hasCompound[words[0]] = true\n }\n // inflect our nouns\n if (tag === 'Singular') {\n let plural = transform.toPlural(word, world)\n lexicon[plural] = lexicon[plural] || 'Plural' // only if it's safe\n }\n //conjugate our verbs\n if (tag === 'Infinitive') {\n let conj = transform.conjugate(word, world)\n let tags = Object.keys(conj)\n for (let i = 0; i < tags.length; i++) {\n let w = conj[tags[i]]\n lexicon[w] = lexicon[w] || tags[i] // only if it's safe\n }\n }\n //derive more adjective forms\n if (tag === 'Comparable') {\n let conj = transform.adjectives(word)\n let tags = Object.keys(conj)\n for (let i = 0; i < tags.length; i++) {\n let w = conj[tags[i]]\n lexicon[w] = lexicon[w] || tags[i] // only if it's safe\n }\n }\n //conjugate phrasal-verbs\n if (tag === 'PhrasalVerb') {\n //add original form\n addWord(word, 'Infinitive', lexicon)\n //conjugate first word\n let conj = transform.conjugate(words[0], world)\n let tags = Object.keys(conj)\n for (let i = 0; i < tags.length; i++) {\n //add it to our cache\n world.hasCompound[conj[tags[i]]] = true\n //first + last words\n let w = conj[tags[i]] + ' ' + words[1]\n\n addWord(w, tags[i], lexicon)\n addWord(w, 'PhrasalVerb', lexicon)\n }\n }\n // inflect our demonyms - 'germans'\n if (tag === 'Demonym') {\n let plural = transform.toPlural(word, world)\n lexicon[plural] = lexicon[plural] || ['Demonym', 'Plural'] // only if it's safe\n }\n}\n\n// throw a bunch of words in our lexicon\n// const doWord = function(words, tag, world) {\n// let lexicon = world.words\n// for (let i = 0; i < words.length; i++) {\n// addWord(words[i], tag, lexicon)\n// // do some fancier stuff\n// addMore(words[i], tag, world)\n// }\n// }\nmodule.exports = {\n addWord: addWord,\n addMore: addMore,\n}\n","// add words from plurals and conjugations data\nconst addIrregulars = function(world) {\n //add irregular plural nouns\n let nouns = world.irregulars.nouns\n let words = Object.keys(nouns)\n for (let i = 0; i < words.length; i++) {\n const w = words[i]\n world.words[w] = 'Singular'\n world.words[nouns[w]] = 'Plural'\n }\n\n // add irregular verb conjugations\n let verbs = world.irregulars.verbs\n let keys = Object.keys(verbs)\n for (let i = 0; i < keys.length; i++) {\n const inf = keys[i]\n //add only if it it's safe...\n world.words[inf] = world.words[inf] || 'Infinitive'\n let forms = world.transforms.conjugate(inf, world)\n forms = Object.assign(forms, verbs[inf])\n //add the others\n Object.keys(forms).forEach(tag => {\n world.words[forms[tag]] = world.words[forms[tag]] || tag\n })\n }\n}\nmodule.exports = addIrregulars\n","//words that can't be compressed, for whatever reason\nmodule.exports = {\n // numbers\n '20th century fox': 'Organization',\n // '3m': 'Organization',\n '7 eleven': 'Organization',\n '7-eleven': 'Organization',\n g8: 'Organization',\n 'motel 6': 'Organization',\n vh1: 'Organization',\n q1: 'Date',\n q2: 'Date',\n q3: 'Date',\n q4: 'Date',\n}\n","//nouns with irregular plural/singular forms\n//used in noun.inflect, and also in the lexicon.\n\nmodule.exports = {\n addendum: 'addenda',\n alga: 'algae',\n alumna: 'alumnae',\n alumnus: 'alumni',\n analysis: 'analyses',\n antenna: 'antennae',\n appendix: 'appendices',\n avocado: 'avocados',\n axis: 'axes',\n bacillus: 'bacilli',\n barracks: 'barracks',\n beau: 'beaux',\n bus: 'buses',\n cactus: 'cacti',\n chateau: 'chateaux',\n child: 'children',\n circus: 'circuses',\n clothes: 'clothes',\n corpus: 'corpora',\n criterion: 'criteria',\n curriculum: 'curricula',\n database: 'databases',\n deer: 'deer',\n diagnosis: 'diagnoses',\n echo: 'echoes',\n embargo: 'embargoes',\n epoch: 'epochs',\n foot: 'feet',\n formula: 'formulae',\n fungus: 'fungi',\n genus: 'genera',\n goose: 'geese',\n halo: 'halos',\n hippopotamus: 'hippopotami',\n index: 'indices',\n larva: 'larvae',\n leaf: 'leaves',\n libretto: 'libretti',\n loaf: 'loaves',\n man: 'men',\n matrix: 'matrices',\n memorandum: 'memoranda',\n modulus: 'moduli',\n mosquito: 'mosquitoes',\n mouse: 'mice',\n move: 'moves',\n nebula: 'nebulae',\n nucleus: 'nuclei',\n octopus: 'octopi',\n opus: 'opera',\n ovum: 'ova',\n ox: 'oxen',\n parenthesis: 'parentheses',\n person: 'people',\n phenomenon: 'phenomena',\n prognosis: 'prognoses',\n quiz: 'quizzes',\n radius: 'radii',\n referendum: 'referenda',\n rodeo: 'rodeos',\n sex: 'sexes',\n shoe: 'shoes',\n sombrero: 'sombreros',\n stimulus: 'stimuli',\n stomach: 'stomachs',\n syllabus: 'syllabi',\n synopsis: 'synopses',\n tableau: 'tableaux',\n thesis: 'theses',\n thief: 'thieves',\n tooth: 'teeth',\n tornado: 'tornados',\n tuxedo: 'tuxedos',\n vertebra: 'vertebrae',\n // virus: 'viri',\n // zero: 'zeros',\n}\n","// a list of irregular verb conjugations\n// used in verbs().conjugate()\n// but also added to our lexicon\n\n//use shorter key-names\nconst mapping = {\n g: 'Gerund',\n prt: 'Participle',\n perf: 'PerfectTense',\n pst: 'PastTense',\n fut: 'FuturePerfect',\n pres: 'PresentTense',\n pluperf: 'Pluperfect',\n a: 'Actor',\n}\n\n// '_' in conjugations is the infinitive form\nlet conjugations = {\n act: {\n a: '_or',\n },\n age: {\n g: 'ageing',\n pst: 'aged',\n pres: 'ages',\n },\n aim: {\n a: '_er',\n g: '_ing',\n pst: '_ed',\n },\n arise: {\n prt: '_n',\n pst: 'arose',\n },\n babysit: {\n a: '_ter',\n pst: 'babysat',\n },\n ban: {\n a: '',\n g: '_ning',\n pst: '_ned',\n },\n be: {\n a: '',\n g: 'am',\n prt: 'been',\n pst: 'was',\n pres: 'is',\n },\n beat: {\n a: '_er',\n g: '_ing',\n prt: '_en',\n },\n become: {\n prt: '_',\n },\n begin: {\n g: '_ning',\n prt: 'begun',\n pst: 'began',\n },\n being: {\n g: 'are',\n pst: 'were',\n pres: 'are',\n },\n bend: {\n prt: 'bent',\n },\n bet: {\n a: '_ter',\n prt: '_',\n },\n bind: {\n pst: 'bound',\n },\n bite: {\n g: 'biting',\n prt: 'bitten',\n pst: 'bit',\n },\n bleed: {\n prt: 'bled',\n pst: 'bled',\n },\n blow: {\n prt: '_n',\n pst: 'blew',\n },\n boil: {\n a: '_er',\n },\n brake: {\n prt: 'broken',\n },\n break: {\n pst: 'broke',\n },\n breed: {\n pst: 'bred',\n },\n bring: {\n prt: 'brought',\n pst: 'brought',\n },\n broadcast: {\n pst: '_',\n },\n budget: {\n pst: '_ed',\n },\n build: {\n prt: 'built',\n pst: 'built',\n },\n burn: {\n prt: '_ed',\n },\n burst: {\n prt: '_',\n },\n buy: {\n prt: 'bought',\n pst: 'bought',\n },\n can: {\n a: '',\n fut: '_',\n g: '',\n pst: 'could',\n perf: 'could',\n pluperf: 'could',\n pres: '_',\n },\n catch: {\n pst: 'caught',\n },\n choose: {\n g: 'choosing',\n prt: 'chosen',\n pst: 'chose',\n },\n cling: {\n prt: 'clung',\n },\n come: {\n prt: '_',\n pst: 'came',\n },\n compete: {\n a: 'competitor',\n g: 'competing',\n pst: '_d',\n },\n cost: {\n pst: '_',\n },\n creep: {\n prt: 'crept',\n },\n cut: {\n prt: '_',\n },\n deal: {\n prt: '_t',\n pst: '_t',\n },\n develop: {\n a: '_er',\n g: '_ing',\n pst: '_ed',\n },\n die: {\n g: 'dying',\n pst: '_d',\n },\n dig: {\n g: '_ging',\n prt: 'dug',\n pst: 'dug',\n },\n dive: {\n prt: '_d',\n },\n do: {\n pst: 'did',\n pres: '_es',\n },\n draw: {\n prt: '_n',\n pst: 'drew',\n },\n dream: {\n prt: '_t',\n },\n drink: {\n prt: 'drunk',\n pst: 'drank',\n },\n drive: {\n g: 'driving',\n prt: '_n',\n pst: 'drove',\n },\n drop: {\n g: '_ping',\n pst: '_ped',\n },\n eat: {\n a: '_er',\n g: '_ing',\n prt: '_en',\n pst: 'ate',\n },\n edit: {\n g: '_ing',\n },\n egg: {\n pst: '_ed',\n },\n fall: {\n prt: '_en',\n pst: 'fell',\n },\n feed: {\n prt: 'fed',\n pst: 'fed',\n },\n feel: {\n a: '_er',\n pst: 'felt',\n },\n fight: {\n prt: 'fought',\n pst: 'fought',\n },\n find: {\n pst: 'found',\n },\n flee: {\n g: '_ing',\n prt: 'fled',\n },\n fling: {\n prt: 'flung',\n },\n fly: {\n prt: 'flown',\n pst: 'flew',\n },\n forbid: {\n pst: 'forbade',\n },\n forget: {\n g: '_ing',\n prt: 'forgotten',\n pst: 'forgot',\n },\n forgive: {\n g: 'forgiving',\n prt: '_n',\n pst: 'forgave',\n },\n free: {\n a: '',\n g: '_ing',\n },\n freeze: {\n g: 'freezing',\n prt: 'frozen',\n pst: 'froze',\n },\n get: {\n pst: 'got',\n prt: 'gotten',\n },\n give: {\n g: 'giving',\n prt: '_n',\n pst: 'gave',\n },\n go: {\n prt: '_ne',\n pst: 'went',\n pres: 'goes',\n },\n grow: {\n prt: '_n',\n },\n hang: {\n prt: 'hung',\n pst: 'hung',\n },\n have: {\n g: 'having',\n prt: 'had',\n pst: 'had',\n pres: 'has',\n },\n hear: {\n prt: '_d',\n pst: '_d',\n },\n hide: {\n prt: 'hidden',\n pst: 'hid',\n },\n hit: {\n prt: '_',\n },\n hold: {\n prt: 'held',\n pst: 'held',\n },\n hurt: {\n prt: '_',\n pst: '_',\n },\n ice: {\n g: 'icing',\n pst: '_d',\n },\n imply: {\n pst: 'implied',\n pres: 'implies',\n },\n is: {\n a: '',\n g: 'being',\n pst: 'was',\n pres: '_',\n },\n keep: {\n prt: 'kept',\n },\n kneel: {\n prt: 'knelt',\n },\n know: {\n prt: '_n',\n },\n lay: {\n prt: 'laid',\n pst: 'laid',\n },\n lead: {\n prt: 'led',\n pst: 'led',\n },\n leap: {\n prt: '_t',\n },\n leave: {\n prt: 'left',\n pst: 'left',\n },\n lend: {\n prt: 'lent',\n },\n lie: {\n g: 'lying',\n pst: 'lay',\n },\n light: {\n prt: 'lit',\n pst: 'lit',\n },\n log: {\n g: '_ging',\n pst: '_ged',\n },\n loose: {\n prt: 'lost',\n },\n lose: {\n g: 'losing',\n pst: 'lost',\n },\n make: {\n prt: 'made',\n pst: 'made',\n },\n mean: {\n prt: '_t',\n pst: '_t',\n },\n meet: {\n a: '_er',\n g: '_ing',\n prt: 'met',\n pst: 'met',\n },\n miss: {\n pres: '_',\n },\n pay: {\n prt: 'paid',\n pst: 'paid',\n },\n prove: {\n prt: '_n',\n },\n puke: {\n g: 'puking',\n },\n put: {\n prt: '_',\n },\n quit: {\n prt: '_',\n },\n read: {\n prt: '_',\n pst: '_',\n },\n ride: {\n prt: 'ridden',\n },\n ring: {\n prt: 'rung',\n pst: 'rang',\n },\n rise: {\n fut: 'will have _n',\n g: 'rising',\n prt: '_n',\n pst: 'rose',\n pluperf: 'had _n',\n },\n rub: {\n g: '_bing',\n pst: '_bed',\n },\n run: {\n g: '_ning',\n prt: '_',\n pst: 'ran',\n },\n say: {\n prt: 'said',\n pst: 'said',\n pres: '_s',\n },\n seat: {\n prt: 'sat',\n },\n see: {\n g: '_ing',\n prt: '_n',\n pst: 'saw',\n },\n seek: {\n prt: 'sought',\n },\n sell: {\n prt: 'sold',\n pst: 'sold',\n },\n send: {\n prt: 'sent',\n },\n set: {\n prt: '_',\n },\n sew: {\n prt: '_n',\n },\n shake: {\n prt: '_n',\n },\n shave: {\n prt: '_d',\n },\n shed: {\n g: '_ding',\n pst: '_',\n pres: '_s',\n },\n shine: {\n prt: 'shone',\n pst: 'shone',\n },\n shoot: {\n prt: 'shot',\n pst: 'shot',\n },\n show: {\n pst: '_ed',\n },\n shut: {\n prt: '_',\n },\n sing: {\n prt: 'sung',\n pst: 'sang',\n },\n sink: {\n pst: 'sank',\n pluperf: 'had sunk',\n },\n sit: {\n pst: 'sat',\n },\n ski: {\n pst: '_ied',\n },\n slay: {\n prt: 'slain',\n },\n sleep: {\n prt: 'slept',\n },\n slide: {\n prt: 'slid',\n pst: 'slid',\n },\n smash: {\n pres: '_es',\n },\n sneak: {\n prt: 'snuck',\n },\n speak: {\n fut: 'will have spoken',\n prt: 'spoken',\n pst: 'spoke',\n perf: 'have spoken',\n pluperf: 'had spoken',\n },\n speed: {\n prt: 'sped',\n },\n spend: {\n prt: 'spent',\n },\n spill: {\n prt: '_ed',\n pst: 'spilt',\n },\n spin: {\n g: '_ning',\n prt: 'spun',\n pst: 'spun',\n },\n spit: {\n prt: 'spat',\n },\n split: {\n prt: '_',\n },\n spread: {\n pst: '_',\n },\n spring: {\n prt: 'sprung',\n },\n stand: {\n pst: 'stood',\n },\n steal: {\n a: '_er',\n pst: 'stole',\n },\n stick: {\n pst: 'stuck',\n },\n sting: {\n pst: 'stung',\n },\n stink: {\n prt: 'stunk',\n pst: 'stunk',\n },\n stream: {\n a: '_er',\n },\n strew: {\n prt: '_n',\n },\n strike: {\n g: 'striking',\n pst: 'struck',\n },\n suit: {\n a: '_er',\n g: '_ing',\n pst: '_ed',\n },\n sware: {\n prt: 'sworn',\n },\n swear: {\n pst: 'swore',\n },\n sweep: {\n prt: 'swept',\n },\n swim: {\n g: '_ming',\n pst: 'swam',\n },\n swing: {\n pst: 'swung',\n },\n take: {\n fut: 'will have _n',\n pst: 'took',\n perf: 'have _n',\n pluperf: 'had _n',\n },\n teach: {\n pst: 'taught',\n pres: '_es',\n },\n tear: {\n pst: 'tore',\n },\n tell: {\n pst: 'told',\n },\n think: {\n pst: 'thought',\n },\n thrive: {\n prt: '_d',\n },\n tie: {\n g: 'tying',\n pst: '_d',\n },\n undergo: {\n prt: '_ne',\n },\n understand: {\n pst: 'understood',\n },\n upset: {\n prt: '_',\n },\n wait: {\n a: '_er',\n g: '_ing',\n pst: '_ed',\n },\n wake: {\n pst: 'woke',\n },\n wear: {\n pst: 'wore',\n },\n weave: {\n prt: 'woven',\n },\n weep: {\n prt: 'wept',\n },\n win: {\n g: '_ning',\n pst: 'won',\n },\n wind: {\n prt: 'wound',\n },\n withdraw: {\n pst: 'withdrew',\n },\n wring: {\n prt: 'wrung',\n },\n write: {\n g: 'writing',\n prt: 'written',\n pst: 'wrote',\n },\n}\n\n//uncompress our ad-hoc compression scheme\nlet keys = Object.keys(conjugations)\nfor (let i = 0; i < keys.length; i++) {\n const inf = keys[i]\n let final = {}\n Object.keys(conjugations[inf]).forEach(key => {\n let str = conjugations[inf][key]\n //swap-in infinitives for '_'\n str = str.replace('_', inf)\n\n let full = mapping[key]\n final[full] = str\n })\n //over-write original\n conjugations[inf] = final\n}\n\nmodule.exports = conjugations\n","const endsWith = {\n b: [\n {\n reg: /([^aeiou][aeiou])b$/i,\n repl: {\n pr: '$1bs',\n pa: '$1bbed',\n gr: '$1bbing',\n },\n },\n ],\n d: [\n {\n reg: /(end)$/i,\n repl: {\n pr: '$1s',\n pa: 'ent',\n gr: '$1ing',\n ar: '$1er',\n },\n },\n {\n reg: /(eed)$/i,\n repl: {\n pr: '$1s',\n pa: '$1ed',\n gr: '$1ing',\n ar: '$1er',\n },\n },\n {\n reg: /(ed)$/i,\n repl: {\n pr: '$1s',\n pa: '$1ded',\n ar: '$1der',\n gr: '$1ding',\n },\n },\n {\n reg: /([^aeiou][ou])d$/i,\n repl: {\n pr: '$1ds',\n pa: '$1dded',\n gr: '$1dding',\n },\n },\n ],\n e: [\n {\n reg: /(eave)$/i,\n repl: {\n pr: '$1s',\n pa: '$1d',\n gr: 'eaving',\n ar: '$1r',\n },\n },\n {\n reg: /(ide)$/i,\n repl: {\n pr: '$1s',\n pa: 'ode',\n gr: 'iding',\n ar: 'ider',\n },\n },\n {\n reg: /(ake)$/i,\n repl: {\n pr: '$1s',\n pa: 'ook',\n gr: 'aking',\n ar: '$1r',\n },\n },\n {\n reg: /(a[tg]|i[zn]|ur|nc|gl|is)e$/i,\n repl: {\n pr: '$1es',\n pa: '$1ed',\n gr: '$1ing',\n prt: '$1en',\n },\n },\n {\n reg: /([bd]l)e$/i,\n repl: {\n pr: '$1es',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n {\n reg: /(om)e$/i,\n repl: {\n pr: '$1es',\n pa: 'ame',\n gr: '$1ing',\n },\n },\n ],\n\n g: [\n {\n reg: /([^aeiou][ou])g$/i,\n repl: {\n pr: '$1gs',\n pa: '$1gged',\n gr: '$1gging',\n },\n },\n ],\n h: [\n {\n reg: /(..)([cs]h)$/i,\n repl: {\n pr: '$1$2es',\n pa: '$1$2ed',\n gr: '$1$2ing',\n },\n },\n ],\n k: [\n {\n reg: /(ink)$/i,\n repl: {\n pr: '$1s',\n pa: 'unk',\n gr: '$1ing',\n ar: '$1er',\n },\n },\n ],\n\n m: [\n {\n reg: /([^aeiou][aeiou])m$/i,\n repl: {\n pr: '$1ms',\n pa: '$1mmed',\n gr: '$1mming',\n },\n },\n ],\n\n n: [\n {\n reg: /(en)$/i,\n repl: {\n pr: '$1s',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n ],\n p: [\n {\n reg: /(e)(ep)$/i,\n repl: {\n pr: '$1$2s',\n pa: '$1pt',\n gr: '$1$2ing',\n ar: '$1$2er',\n },\n },\n {\n reg: /([^aeiou][aeiou])p$/i,\n repl: {\n pr: '$1ps',\n pa: '$1pped',\n gr: '$1pping',\n },\n },\n {\n reg: /([aeiu])p$/i,\n repl: {\n pr: '$1ps',\n pa: '$1p',\n gr: '$1pping',\n },\n },\n ],\n\n r: [\n {\n reg: /([td]er)$/i,\n repl: {\n pr: '$1s',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n {\n reg: /(er)$/i,\n repl: {\n pr: '$1s',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n ],\n s: [\n {\n reg: /(ish|tch|ess)$/i,\n repl: {\n pr: '$1es',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n ],\n\n t: [\n {\n reg: /(ion|end|e[nc]t)$/i,\n repl: {\n pr: '$1s',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n {\n reg: /(.eat)$/i,\n repl: {\n pr: '$1s',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n {\n reg: /([aeiu])t$/i,\n repl: {\n pr: '$1ts',\n pa: '$1t',\n gr: '$1tting',\n },\n },\n {\n reg: /([^aeiou][aeiou])t$/i,\n repl: {\n pr: '$1ts',\n pa: '$1tted',\n gr: '$1tting',\n },\n },\n ],\n\n w: [\n {\n reg: /(..)(ow)$/i,\n repl: {\n pr: '$1$2s',\n pa: '$1ew',\n gr: '$1$2ing',\n prt: '$1$2n',\n },\n },\n ],\n y: [\n {\n reg: /([i|f|rr])y$/i,\n repl: {\n pr: '$1ies',\n pa: '$1ied',\n gr: '$1ying',\n },\n },\n ],\n\n z: [\n {\n reg: /([aeiou]zz)$/i,\n repl: {\n pr: '$1es',\n pa: '$1ed',\n gr: '$1ing',\n },\n },\n ],\n}\n\nmodule.exports = endsWith\n","const suffixes = require('./suffixes')\nconst posMap = {\n pr: 'PresentTense',\n pa: 'PastTense',\n gr: 'Gerund',\n prt: 'Participle',\n ar: 'Actor',\n}\n\nconst doTransform = function(str, obj) {\n let found = {}\n let keys = Object.keys(obj.repl)\n for (let i = 0; i < keys.length; i += 1) {\n let pos = keys[i]\n found[posMap[pos]] = str.replace(obj.reg, obj.repl[pos])\n }\n return found\n}\n\n//look at the end of the word for clues\nconst checkSuffix = function(str = '') {\n let c = str[str.length - 1]\n if (suffixes.hasOwnProperty(c) === true) {\n for (let r = 0; r < suffixes[c].length; r += 1) {\n const reg = suffixes[c][r].reg\n if (reg.test(str) === true) {\n return doTransform(str, suffixes[c][r])\n }\n }\n }\n return {}\n}\nmodule.exports = checkSuffix\n","//non-specifc, 'hail-mary' transforms from infinitive, into other forms\nconst hasY = /[bcdfghjklmnpqrstvwxz]y$/\n\nconst generic = {\n Gerund: inf => {\n if (inf.charAt(inf.length - 1) === 'e') {\n return inf.replace(/e$/, 'ing')\n }\n return inf + 'ing'\n },\n\n PresentTense: inf => {\n if (inf.charAt(inf.length - 1) === 's') {\n return inf + 'es'\n }\n if (hasY.test(inf) === true) {\n return inf.slice(0, -1) + 'ies'\n }\n return inf + 's'\n },\n\n PastTense: inf => {\n if (inf.charAt(inf.length - 1) === 'e') {\n return inf + 'd'\n }\n if (inf.substr(-2) === 'ed') {\n return inf\n }\n if (hasY.test(inf) === true) {\n return inf.slice(0, -1) + 'ied'\n }\n return inf + 'ed'\n },\n}\n\nmodule.exports = generic\n","const checkSuffix = require('./01-suffixes')\nconst genericFill = require('./02-generic')\n\n//we run this on every verb in the lexicon, so please keep it fast\n//we assume the input word is a proper infinitive\nconst conjugate = function(str = '', world) {\n let found = {}\n // 1. look at irregulars\n //the lexicon doesn't pass this in\n if (world && world.irregulars) {\n if (world.irregulars.verbs.hasOwnProperty(str) === true) {\n found = Object.assign({}, world.irregulars.verbs[str])\n }\n }\n //2. rule-based regex\n found = Object.assign({}, checkSuffix(str), found)\n\n //3. generic transformations\n //'buzzing'\n if (found.Gerund === undefined) {\n found.Gerund = genericFill.Gerund(str)\n }\n //'buzzed'\n if (found.PastTense === undefined) {\n found.PastTense = genericFill.PastTense(str)\n }\n //'buzzes'\n if (found.PresentTense === undefined) {\n found.PresentTense = genericFill.PresentTense(str)\n }\n return found\n}\nmodule.exports = conjugate\n","//turn 'quick' into 'quickest'\nconst do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /oud$/, /...p$/]\nconst dont_rules = [/ary$/]\n\nconst irregulars = {\n nice: 'nicest',\n late: 'latest',\n hard: 'hardest',\n inner: 'innermost',\n outer: 'outermost',\n far: 'furthest',\n worse: 'worst',\n bad: 'worst',\n good: 'best',\n big: 'biggest',\n large: 'largest',\n}\n\nconst transforms = [\n {\n reg: /y$/i,\n repl: 'iest',\n },\n {\n reg: /([aeiou])t$/i,\n repl: '$1ttest',\n },\n {\n reg: /([aeou])de$/i,\n repl: '$1dest',\n },\n {\n reg: /nge$/i,\n repl: 'ngest',\n },\n {\n reg: /([aeiou])te$/i,\n repl: '$1test',\n },\n]\n\nconst to_superlative = function(str) {\n //irregulars\n if (irregulars.hasOwnProperty(str)) {\n return irregulars[str]\n }\n //known transforms\n for (let i = 0; i < transforms.length; i++) {\n if (transforms[i].reg.test(str)) {\n return str.replace(transforms[i].reg, transforms[i].repl)\n }\n }\n //dont-rules\n for (let i = 0; i < dont_rules.length; i++) {\n if (dont_rules[i].test(str) === true) {\n return null\n }\n }\n //do-rules\n for (let i = 0; i < do_rules.length; i++) {\n if (do_rules[i].test(str) === true) {\n if (str.charAt(str.length - 1) === 'e') {\n return str + 'st'\n }\n return str + 'est'\n }\n }\n return str + 'est'\n}\n\nmodule.exports = to_superlative\n","//turn 'quick' into 'quickly'\nconst do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /old$/, /oud$/, /e[ae]p$/]\nconst dont_rules = [/ary$/, /ous$/]\n\nconst irregulars = {\n grey: 'greyer',\n gray: 'grayer',\n green: 'greener',\n yellow: 'yellower',\n red: 'redder',\n good: 'better',\n well: 'better',\n bad: 'worse',\n sad: 'sadder',\n big: 'bigger',\n}\n\nconst transforms = [\n {\n reg: /y$/i,\n repl: 'ier',\n },\n {\n reg: /([aeiou])t$/i,\n repl: '$1tter',\n },\n {\n reg: /([aeou])de$/i,\n repl: '$1der',\n },\n {\n reg: /nge$/i,\n repl: 'nger',\n },\n]\n\nconst to_comparative = function(str) {\n //known-irregulars\n if (irregulars.hasOwnProperty(str)) {\n return irregulars[str]\n }\n //known-transforms\n for (let i = 0; i < transforms.length; i++) {\n if (transforms[i].reg.test(str) === true) {\n return str.replace(transforms[i].reg, transforms[i].repl)\n }\n }\n //dont-patterns\n for (let i = 0; i < dont_rules.length; i++) {\n if (dont_rules[i].test(str) === true) {\n return null\n }\n }\n //do-patterns\n for (let i = 0; i < do_rules.length; i++) {\n if (do_rules[i].test(str) === true) {\n return str + 'er'\n }\n }\n //easy-one\n if (/e$/.test(str) === true) {\n return str + 'r'\n }\n return str + 'er'\n}\n\nmodule.exports = to_comparative\n","const fns = {\n toSuperlative: require('./toSuperlative'),\n toComparative: require('./toComparative'),\n}\n\n/** conjugate an adjective into other forms */\nconst conjugate = function(w) {\n let res = {}\n // 'greatest'\n let sup = fns.toSuperlative(w)\n if (sup) {\n res.Superlative = sup\n }\n // 'greater'\n let comp = fns.toComparative(w)\n if (comp) {\n res.Comparative = comp\n }\n return res\n}\nmodule.exports = conjugate\n","/** patterns for turning 'bus' to 'buses'*/\nconst suffixes = {\n a: [[/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae'], [/([ti])a$/i, '$1a']],\n\n e: [\n [/(kn|l|w)ife$/i, '$1ives'],\n [/(hive)$/i, '$1s'],\n [/([m|l])ouse$/i, '$1ice'],\n [/([m|l])ice$/i, '$1ice'],\n ],\n\n f: [\n [/^(dwar|handkerchie|hoo|scar|whar)f$/i, '$1ves'],\n [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)f$/i, '$1ves'],\n ],\n\n i: [[/(octop|vir)i$/i, '$1i']],\n\n m: [[/([ti])um$/i, '$1a']],\n\n n: [[/^(oxen)$/i, '$1']],\n\n o: [[/(al|ad|at|er|et|ed|ad)o$/i, '$1oes']],\n\n s: [\n [/(ax|test)is$/i, '$1es'],\n [/(alias|status)$/i, '$1es'],\n [/sis$/i, 'ses'],\n [/(bu)s$/i, '$1ses'],\n [/(sis)$/i, 'ses'],\n [/^(?!talis|.*hu)(.*)man$/i, '$1men'],\n [/(octop|vir|radi|nucle|fung|cact|stimul)us$/i, '$1i'],\n ],\n\n x: [[/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices'], [/^(ox)$/i, '$1en']],\n\n y: [[/([^aeiouy]|qu)y$/i, '$1ies']],\n\n z: [[/(quiz)$/i, '$1zes']],\n}\n\nmodule.exports = suffixes\n","const rules = require('./_rules')\nconst addE = /(x|ch|sh|s|z)$/\n\nconst trySuffix = function(str) {\n let c = str[str.length - 1]\n if (rules.hasOwnProperty(c) === true) {\n for (let i = 0; i < rules[c].length; i += 1) {\n let reg = rules[c][i][0]\n if (reg.test(str) === true) {\n return str.replace(reg, rules[c][i][1])\n }\n }\n }\n return null\n}\n\n/** Turn a singular noun into a plural\n * assume the given string is singular\n */\nconst pluralize = function(str = '', world) {\n let irregulars = world.irregulars.nouns\n\n // check irregulars list\n if (irregulars.hasOwnProperty(str)) {\n return irregulars[str]\n }\n\n //we have some rules to try-out\n let plural = trySuffix(str)\n if (plural !== null) {\n return plural\n }\n //like 'church'\n if (addE.test(str)) {\n return str + 'es'\n }\n // ¯\\_(ツ)_/¯\n return str + 's'\n}\nmodule.exports = pluralize\n","//patterns for turning 'dwarves' to 'dwarf'\nmodule.exports = [\n [/([^v])ies$/i, '$1y'],\n [/ises$/i, 'isis'],\n [/(kn|[^o]l|w)ives$/i, '$1ife'],\n [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i, '$1f'],\n [/^(dwar|handkerchie|hoo|scar|whar)ves$/i, '$1f'],\n [/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a'],\n [/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i, '$1us'],\n [/(buffal|tomat|tornad)(oes)$/i, '$1o'],\n // [/(analy|diagno|parenthe|progno|synop|the)ses$/i, '$1sis'],\n [/(..[aeiou]s)es$/i, '$1'],\n [/(vert|ind|cort)(ices)$/i, '$1ex'],\n [/(matr|append)(ices)$/i, '$1ix'],\n [/(x|ch|ss|sh|z|o)es$/i, '$1'],\n [/men$/i, 'man'],\n [/(n)ews$/i, '$1ews'],\n [/([ti])a$/i, '$1um'],\n [/([^aeiouy]|qu)ies$/i, '$1y'],\n [/(s)eries$/i, '$1eries'],\n [/(m)ovies$/i, '$1ovie'],\n [/([m|l])ice$/i, '$1ouse'],\n [/(cris|ax|test)es$/i, '$1is'],\n [/(alias|status)es$/i, '$1'],\n [/(ss)$/i, '$1'],\n [/(ics)$/i, '$1'],\n [/s$/i, ''],\n]\n","const rules = require('./_rules')\n\nconst invertObj = function(obj) {\n return Object.keys(obj).reduce((h, k) => {\n h[obj[k]] = k\n return h\n }, {})\n}\n\nconst toSingular = function(str, world) {\n let irregulars = world.irregulars.nouns\n let invert = invertObj(irregulars)\n\n // check irregulars list\n if (invert.hasOwnProperty(str)) {\n return invert[str]\n }\n\n // go through our regexes\n for (let i = 0; i < rules.length; i++) {\n if (rules[i][0].test(str) === true) {\n str = str.replace(rules[i][0], rules[i][1])\n return str\n }\n }\n return str\n}\nmodule.exports = toSingular\n","//rules for turning a verb into infinitive form\nlet rules = {\n Participle: [\n {\n reg: /own$/i,\n to: 'ow',\n },\n {\n reg: /(.)un([g|k])$/i,\n to: '$1in$2',\n },\n ],\n\n Actor: [\n {\n reg: /(er)er$/i,\n to: '$1',\n },\n ],\n\n PresentTense: [\n {\n reg: /(..)(ies)$/i,\n to: '$1y',\n },\n {\n reg: /(tch|sh)es$/i,\n to: '$1',\n },\n {\n reg: /(ss|zz)es$/i,\n to: '$1',\n },\n {\n reg: /([tzlshicgrvdnkmu])es$/i,\n to: '$1e',\n },\n {\n reg: /(n[dtk]|c[kt]|[eo]n|i[nl]|er|a[ytrl])s$/i,\n to: '$1',\n },\n {\n reg: /(ow)s$/i,\n to: '$1',\n },\n {\n reg: /(op)s$/i,\n to: '$1',\n },\n {\n reg: /([eirs])ts$/i,\n to: '$1t',\n },\n {\n reg: /(ll)s$/i,\n to: '$1',\n },\n {\n reg: /(el)s$/i,\n to: '$1',\n },\n {\n reg: /(ip)es$/i,\n to: '$1e',\n },\n {\n reg: /ss$/i,\n to: 'ss',\n },\n {\n reg: /s$/i,\n to: '',\n },\n ],\n\n Gerund: [\n {\n reg: /pping$/i,\n to: 'p',\n },\n {\n reg: /lling$/i,\n to: 'll',\n },\n {\n reg: /tting$/i,\n to: 't',\n },\n {\n reg: /dding$/i,\n to: 'd',\n },\n {\n reg: /ssing$/i,\n to: 'ss',\n },\n {\n reg: /(..)gging$/i,\n to: '$1g',\n },\n {\n reg: /([^aeiou])ying$/i,\n to: '$1y',\n },\n {\n reg: /([^ae]i.)ing$/i,\n to: '$1e',\n },\n {\n reg: /(ea.)ing$/i,\n to: '$1',\n },\n {\n reg: /(u[rtcb]|[bdtpkg]l|n[cg]|a[gdkvtc]|[ua]s|[dr]g|yz|o[rlsp]|cre)ing$/i,\n to: '$1e',\n },\n {\n reg: /(ch|sh)ing$/i,\n to: '$1',\n },\n {\n reg: /(..)ing$/i,\n to: '$1',\n },\n ],\n\n PastTense: [\n {\n reg: /(ued)$/i,\n to: 'ue',\n },\n {\n reg: /a([^aeiouy])ed$/i,\n to: 'a$1e',\n },\n {\n reg: /([aeiou]zz)ed$/i,\n to: '$1',\n },\n {\n reg: /(e|i)lled$/i,\n to: '$1ll',\n },\n {\n reg: /(.)(sh|ch)ed$/i,\n to: '$1$2',\n },\n {\n reg: /(tl|gl)ed$/i,\n to: '$1e',\n },\n {\n reg: /(um?pt?)ed$/i,\n to: '$1',\n },\n {\n reg: /(ss)ed$/i,\n to: '$1',\n },\n {\n reg: /pped$/i,\n to: 'p',\n },\n {\n reg: /tted$/i,\n to: 't',\n },\n {\n reg: /(..)gged$/i,\n to: '$1g',\n },\n {\n reg: /(..)lked$/i,\n to: '$1lk',\n },\n {\n reg: /([^aeiouy][aeiou])ked$/i,\n to: '$1ke',\n },\n {\n reg: /(.[aeiou])led$/i,\n to: '$1l',\n },\n {\n reg: /(..)(h|ion|n[dt]|ai.|[cs]t|pp|all|ss|tt|int|ail|ld|en|oo.|er|k|pp|w|ou.|rt|ght|rm)ed$/i,\n to: '$1$2',\n },\n {\n reg: /(.ut)ed$/i,\n to: '$1e',\n },\n {\n reg: /(.pt)ed$/i,\n to: '$1',\n },\n {\n reg: /(us)ed$/i,\n to: '$1e',\n },\n {\n reg: /(..[^aeiouy])ed$/i,\n to: '$1e',\n },\n {\n reg: /(..)ied$/i,\n to: '$1y',\n },\n {\n reg: /(.o)ed$/i,\n to: '$1o',\n },\n {\n reg: /(..i)ed$/i,\n to: '$1',\n },\n {\n reg: /(.a[^aeiou])ed$/i,\n to: '$1',\n },\n {\n reg: /([rl])ew$/i,\n to: '$1ow',\n },\n {\n reg: /([pl])t$/i,\n to: '$1t',\n },\n ],\n}\nmodule.exports = rules\n","let guessVerb = {\n Gerund: ['ing'],\n Actor: ['erer'],\n Infinitive: [\n 'ate',\n 'ize',\n 'tion',\n 'rify',\n 'then',\n 'ress',\n 'ify',\n 'age',\n 'nce',\n 'ect',\n 'ise',\n 'ine',\n 'ish',\n 'ace',\n 'ash',\n 'ure',\n 'tch',\n 'end',\n 'ack',\n 'and',\n 'ute',\n 'ade',\n 'ock',\n 'ite',\n 'ase',\n 'ose',\n 'use',\n 'ive',\n 'int',\n 'nge',\n 'lay',\n 'est',\n 'ain',\n 'ant',\n 'ent',\n 'eed',\n 'er',\n 'le',\n 'own',\n 'unk',\n 'ung',\n 'en',\n ],\n PastTense: ['ed', 'lt', 'nt', 'pt', 'ew', 'ld'],\n PresentTense: [\n 'rks',\n 'cks',\n 'nks',\n 'ngs',\n 'mps',\n 'tes',\n 'zes',\n 'ers',\n 'les',\n 'acks',\n 'ends',\n 'ands',\n 'ocks',\n 'lays',\n 'eads',\n 'lls',\n 'els',\n 'ils',\n 'ows',\n 'nds',\n 'ays',\n 'ams',\n 'ars',\n 'ops',\n 'ffs',\n 'als',\n 'urs',\n 'lds',\n 'ews',\n 'ips',\n 'es',\n 'ts',\n 'ns',\n ],\n}\n//flip it into a lookup object\nguessVerb = Object.keys(guessVerb).reduce((h, k) => {\n guessVerb[k].forEach(a => (h[a] = k))\n return h\n}, {})\nmodule.exports = guessVerb\n","const rules = require('./_transform')\nconst guess = require('./_guess')\n\n/** it helps to know what we're conjugating from */\nconst guessTense = function(str) {\n let three = str.substr(str.length - 3)\n if (guess.hasOwnProperty(three) === true) {\n return guess[three]\n }\n let two = str.substr(str.length - 2)\n if (guess.hasOwnProperty(two) === true) {\n return guess[two]\n }\n let one = str.substr(str.length - 1)\n if (one === 's') {\n return 'PresentTense'\n }\n return null\n}\n\nconst toInfinitive = function(str, world, tense) {\n if (!str) {\n return ''\n }\n //1. look at known irregulars\n if (world.words.hasOwnProperty(str) === true) {\n let irregs = world.irregulars.verbs\n let keys = Object.keys(irregs)\n for (let i = 0; i < keys.length; i++) {\n let forms = Object.keys(irregs[keys[i]])\n for (let o = 0; o < forms.length; o++) {\n if (str === irregs[keys[i]][forms[o]]) {\n return keys[i]\n }\n }\n }\n }\n\n // give'r!\n tense = tense || guessTense(str)\n if (tense && rules[tense]) {\n for (let i = 0; i < rules[tense].length; i++) {\n const rule = rules[tense][i]\n if (rule.reg.test(str) === true) {\n return str.replace(rule.reg, rule.to)\n }\n }\n }\n return str\n}\nmodule.exports = toInfinitive\n","const lexData = require('./_data')\nconst defaultTags = require('./tags')\nconst unpack = require('efrt-unpack')\nconst addLex = require('./addWords')\nconst addIrregulars = require('./addIrregulars')\nconst inferTagSet = require('./tags/inference')\n\nlet misc = require('./data/misc')\n\n//these let users change inflection / verb conjugation\nconst irregulars = {\n nouns: require('./data/plurals'),\n verbs: require('./data/conjugations'),\n}\n\n//these behaviours are configurable & shared across some plugins\nconst transforms = {\n conjugate: require('../transforms/conjugate'),\n adjectives: require('../transforms/adjectives'),\n toPlural: require('../transforms/toPlural'),\n toSingular: require('../transforms/toSingular'),\n toInfinitive: require('../transforms/toInfinitive'),\n}\n\nlet isVerbose = false\n\n/** all configurable linguistic data */\nclass World {\n constructor() {\n // quiet these properties from a console.log\n Object.defineProperty(this, 'words', {\n enumerable: false,\n value: misc,\n writable: true,\n })\n Object.defineProperty(this, 'hasCompound', {\n enumerable: false,\n value: {},\n writable: true,\n })\n Object.defineProperty(this, 'irregulars', {\n enumerable: false,\n value: irregulars,\n writable: true,\n })\n Object.defineProperty(this, 'tags', {\n enumerable: false,\n value: Object.assign({}, defaultTags),\n writable: true,\n })\n Object.defineProperty(this, 'transforms', {\n enumerable: false,\n value: transforms,\n writable: true,\n })\n\n Object.defineProperty(this, 'taggers', {\n enumerable: false,\n value: [],\n writable: true,\n })\n // add our compressed data to lexicon\n this.unpackWords(lexData)\n // add our irregulars to lexicon\n this.addIrregulars()\n\n // cache our abbreviations for our sentence-parser\n Object.defineProperty(this, 'cache', {\n enumerable: false,\n value: {\n abbreviations: this.getByTag('Abbreviation'),\n },\n })\n }\n\n /** more logs for debugging */\n verbose(bool) {\n isVerbose = bool\n return this\n }\n isVerbose() {\n return isVerbose\n }\n\n /** get all terms in our lexicon with this tag */\n getByTag(tag) {\n let lex = this.words\n let res = {}\n let words = Object.keys(lex)\n for (let i = 0; i < words.length; i++) {\n if (typeof lex[words[i]] === 'string') {\n if (lex[words[i]] === tag) {\n res[words[i]] = true\n }\n } else if (lex[words[i]].some(t => t === tag)) {\n res[words[i]] = true\n }\n }\n return res\n }\n\n /** augment our lingustic data with new data */\n unpackWords(lex) {\n let tags = Object.keys(lex)\n for (let i = 0; i < tags.length; i++) {\n let words = Object.keys(unpack(lex[tags[i]]))\n for (let w = 0; w < words.length; w++) {\n addLex.addWord(words[w], tags[i], this.words)\n // do some fancier stuff\n addLex.addMore(words[w], tags[i], this)\n }\n }\n }\n /** put new words into our lexicon, properly */\n addWords(obj) {\n let keys = Object.keys(obj)\n for (let i = 0; i < keys.length; i++) {\n let word = keys[i].toLowerCase()\n addLex.addWord(word, obj[keys[i]], this.words)\n // do some fancier stuff\n addLex.addMore(word, obj[keys[i]], this)\n }\n }\n\n addIrregulars() {\n addIrregulars(this)\n return this\n }\n\n /** extend the compromise tagset */\n addTags(tags) {\n tags = Object.assign({}, tags)\n this.tags = Object.assign(this.tags, tags)\n // calculate graph implications for the new tags\n this.tags = inferTagSet(this.tags)\n return this\n }\n /** call methods after tagger runs */\n postProcess(fn) {\n this.taggers.push(fn)\n return this\n }\n\n /** helper method for logging + debugging */\n stats() {\n return {\n words: Object.keys(this.words).length,\n plurals: Object.keys(this.irregular.plurals).length,\n conjugations: Object.keys(this.irregular.conjugations).length,\n compounds: Object.keys(this.hasCompound).length,\n postProcessors: this.taggers.length,\n }\n }\n}\n\n// ¯\\_(:/)_/¯\nconst clone = function(obj) {\n return JSON.parse(JSON.stringify(obj))\n}\n\n/** produce a deep-copy of all lingustic data */\nWorld.prototype.clone = function() {\n let w2 = new World()\n // these are simple to copy:\n w2.words = Object.assign({}, this.words)\n w2.hasCompound = Object.assign({}, this.hasCompound)\n //these ones are nested:\n w2.irregulars = clone(this.irregulars)\n w2.tags = clone(this.tags)\n // these are functions\n w2.transforms = this.transforms\n w2.taggers = this.taggers\n return w2\n}\nmodule.exports = World\n","// const cache = require('./_setCache')\n\n/** return the root, first document */\nexports.all = function() {\n return this.parents()[0] || this\n}\n\n/** return the previous result */\nexports.parent = function() {\n if (this.from) {\n return this.from\n }\n return this\n}\n\n/** return a list of all previous results */\nexports.parents = function(n) {\n let arr = []\n const addParent = function(doc) {\n if (doc.from) {\n arr.push(doc.from)\n addParent(doc.from)\n }\n }\n addParent(this)\n arr = arr.reverse()\n if (typeof n === 'number') {\n return arr[n]\n }\n return arr\n}\n\n/** deep-copy the document, so that no references remain */\nexports.clone = function(doShallow) {\n let list = this.list.map(ts => ts.clone(doShallow))\n let tmp = this.buildFrom(list)\n return tmp\n}\n\n/** how many seperate terms does the document have? */\nexports.wordCount = function() {\n return this.list.reduce((count, p) => {\n count += p.wordCount()\n return count\n }, 0)\n}\nexports.wordcount = exports.wordCount\n\n/** turn on logging for decision-debugging */\n// exports.verbose = function(bool) {\n// if (bool === undefined) {\n// bool = true\n// }\n// this.world.verbose = bool\n// }\n\n/** freeze the current state of the document, for speed-purposes*/\nexports.cache = function(options) {\n options = options || {}\n this.list.forEach(p => {\n let words = {}\n p.cache = p.cache || {}\n p.cache.terms = p.cache.terms || p.terms()\n // cache all the terms\n p.cache.terms.forEach(t => {\n words[t.clean] = true\n words[t.reduced] = true\n words[t.text.toLowerCase()] = true\n if (t.implicit) {\n words[t.implicit] = true\n }\n if (t.root) {\n words[t.root] = true\n }\n if (t.alias !== undefined) {\n words = Object.assign(words, t.alias)\n }\n if (options.root) {\n t.setRoot(this.world)\n words[t.root] = true\n }\n })\n delete words['']\n p.cache.words = words\n })\n return this\n}\n\n/** un-freezes the current state of the document, so it may be transformed */\nexports.uncache = function() {\n this.list.forEach(p => {\n p.cache = {}\n })\n // do parents too?\n this.parents().forEach(doc => {\n doc.list.forEach(p => {\n p.cache = {}\n })\n })\n return this\n}\n","/** use only the first result(s) */\nexports.first = function(n) {\n if (n === undefined) {\n return this.get(0)\n }\n return this.slice(0, n)\n}\n\n/** use only the last result(s) */\nexports.last = function(n) {\n if (n === undefined) {\n return this.get(this.list.length - 1)\n }\n let end = this.list.length\n return this.slice(end - n, end)\n}\n\n/** grab a given subset of the results*/\nexports.slice = function(start, end) {\n let list = this.list.slice(start, end)\n return this.buildFrom(list)\n}\n\n/* grab nth result */\nexports.eq = function(n) {\n let p = this.list[n]\n if (p === undefined) {\n return this.buildFrom([])\n }\n return this.buildFrom([p])\n}\nexports.get = exports.eq\n\n/** grab term[0] for every match */\nexports.firstTerm = function() {\n return this.match('^.')\n}\n/** grab the last term for every match */\nexports.lastTerm = function() {\n return this.match('.$')\n}\n\n/** return a flat array of term objects */\nexports.termList = function(num) {\n let arr = []\n //'reduce' but faster\n for (let i = 0; i < this.list.length; i++) {\n let terms = this.list[i].terms()\n for (let o = 0; o < terms.length; o++) {\n arr.push(terms[o])\n //support .termList(4)\n if (num !== undefined && arr[num] !== undefined) {\n return arr[num]\n }\n }\n }\n return arr\n}\n","const parseSyntax = require('../match/syntax')\n\n/** return a new Doc, with this one as a parent */\nexports.match = function(reg) {\n //parse-up the input expression\n let regs = parseSyntax(reg)\n if (regs.length === 0) {\n return this.buildFrom([])\n }\n //try expression on each phrase\n let matches = this.list.reduce((arr, p) => {\n return arr.concat(p.match(regs))\n }, [])\n return this.buildFrom(matches)\n}\n\n/** return all results except for this */\nexports.not = function(reg) {\n //parse-up the input expression\n let regs = parseSyntax(reg)\n //if it's empty, return them all!\n if (regs.length === 0) {\n return this\n }\n //try expression on each phrase\n let matches = this.list.reduce((arr, p) => {\n return arr.concat(p.not(regs))\n }, [])\n return this.buildFrom(matches)\n}\n\n/** return only the first match */\nexports.matchOne = function(reg) {\n let regs = parseSyntax(reg)\n for (let i = 0; i < this.list.length; i++) {\n let match = this.list[i].match(regs)\n return this.buildFrom(match)\n }\n return this.buildFrom([])\n}\n\n/** return each current phrase, only if it contains this match */\nexports.if = function(reg) {\n let regs = parseSyntax(reg)\n let found = this.list.filter(p => p.match(regs).length > 0)\n return this.buildFrom(found)\n}\n\n/** Filter-out any current phrases that have this match*/\nexports.ifNo = function(reg) {\n let regs = parseSyntax(reg)\n let found = this.list.filter(p => p.match(regs).length === 0)\n return this.buildFrom(found)\n}\n\n/**Return a boolean if this match exists */\nexports.has = function(reg) {\n let regs = parseSyntax(reg)\n return this.list.some(p => p.has(regs) === true)\n}\n\n/** match any terms after our matches, within the sentence */\nexports.lookAhead = function(reg) {\n // find everything afterwards, by default\n if (!reg) {\n reg = '.*'\n }\n let regs = parseSyntax(reg)\n let matches = []\n this.list.forEach(p => {\n matches = matches.concat(p.lookAhead(regs))\n })\n matches = matches.filter(p => p)\n return this.buildFrom(matches)\n}\nexports.lookAfter = exports.lookAhead\n\n/** match any terms before our matches, within the sentence */\nexports.lookBehind = function(reg) {\n // find everything afterwards, by default\n if (!reg) {\n reg = '.*'\n }\n let regs = parseSyntax(reg)\n let matches = []\n this.list.forEach(p => {\n matches = matches.concat(p.lookBehind(regs))\n })\n matches = matches.filter(p => p)\n return this.buildFrom(matches)\n}\nexports.lookBefore = exports.lookBehind\n\n/** return all terms before a match, in each phrase */\nexports.before = function(reg) {\n let regs = parseSyntax(reg)\n //only the phrases we care about\n let phrases = this.if(regs).list\n let befores = phrases.map(p => {\n let ids = p.terms().map(t => t.id)\n //run the search again\n let m = p.match(regs)[0]\n let index = ids.indexOf(m.start)\n //nothing is before a first-term match\n if (index === 0 || index === -1) {\n return null\n }\n return p.buildFrom(p.start, index)\n })\n befores = befores.filter(p => p !== null)\n return this.buildFrom(befores)\n}\n\n/** return all terms after a match, in each phrase */\nexports.after = function(reg) {\n let regs = parseSyntax(reg)\n //only the phrases we care about\n let phrases = this.if(regs).list\n let befores = phrases.map(p => {\n let terms = p.terms()\n let ids = terms.map(t => t.id)\n //run the search again\n let m = p.match(regs)[0]\n let index = ids.indexOf(m.start)\n //skip if nothing is after it\n if (index === -1 || !terms[index + m.length]) {\n return null\n }\n //create the new phrase, after our match.\n let id = terms[index + m.length].id\n let len = p.length - index - m.length\n return p.buildFrom(id, len)\n })\n befores = befores.filter(p => p !== null)\n return this.buildFrom(befores)\n}\n","/** apply a tag, or tags to all terms */\nconst tagTerms = function(tag, doc, safe, reason) {\n let tagList = []\n if (typeof tag === 'string') {\n tagList = tag.split(' ')\n }\n\n // console.log(doc.parents().length)\n //do indepenent tags for each term:\n doc.list.forEach(p => {\n let terms = p.terms()\n // tagSafe - apply only to fitting terms\n if (safe === true) {\n terms = terms.filter(t => t.canBe(tag, doc.world))\n }\n terms.forEach((t, i) => {\n //fancy version:\n if (tagList.length > 1) {\n if (tagList[i] && tagList[i] !== '.') {\n t.tag(tagList[i], reason, doc.world)\n }\n } else {\n //non-fancy version (same tag for all terms)\n t.tag(tag, reason, doc.world)\n }\n })\n })\n return\n}\nmodule.exports = tagTerms\n","const setTag = require('./_setTag')\n\n/** Give all terms the given tag */\nexports.tag = function(tags, why) {\n if (!tags) {\n return this\n }\n setTag(tags, this, false, why)\n return this\n}\n\n/** Only apply tag to terms if it is consistent with current tags */\nexports.tagSafe = function(tags, why) {\n if (!tags) {\n return this\n }\n setTag(tags, this, true, why)\n return this\n}\n\n/** Remove this term from the given terms */\nexports.unTag = function(tags, why) {\n this.list.forEach(p => {\n p.terms().forEach(t => t.unTag(tags, why, this.world))\n })\n return this\n}\n\n/** return only the terms that can be this tag*/\nexports.canBe = function(tag) {\n if (!tag) {\n return this\n }\n let world = this.world\n let matches = this.list.reduce((arr, p) => {\n return arr.concat(p.canBe(tag, world))\n }, [])\n return this.buildFrom(matches)\n}\n","/* run each phrase through a function, and create a new document */\nexports.map = function(fn) {\n if (!fn) {\n return this\n }\n let list = this.list.map((p, i) => {\n let doc = this.buildFrom([p])\n doc.from = null //it's not a child/parent\n let res = fn(doc, i)\n if (res.list && res.list[0]) {\n return res.list[0]\n }\n return res\n })\n if (list.length === 0) {\n return this.buildFrom(list)\n }\n // if it is not a list of Phrase objects, then don't try to make a Doc object\n if (typeof list[0] !== 'object' || list[0].isA !== 'Phrase') {\n return list\n }\n return this.buildFrom(list)\n}\n\n/** run a function on each phrase */\nexports.forEach = function(fn, detachParent) {\n if (!fn) {\n return this\n }\n this.list.forEach((p, i) => {\n let sub = this.buildFrom([p])\n // if we're doing fancy insertions, we may want to skip updating the parent each time.\n if (detachParent === true) {\n sub.from = null //\n }\n // let len\n // console.log(sub.from.list[0].text())\n fn(sub, i)\n // console.log(sub.from.list[0].text())\n })\n return this\n}\n\n/** return only the phrases that return true */\nexports.filter = function(fn) {\n if (!fn) {\n return this\n }\n let list = this.list.filter((p, i) => {\n let doc = this.buildFrom([p])\n doc.from = null //it's not a child/parent\n return fn(doc, i)\n })\n return this.buildFrom(list)\n}\n\n/** return a document with only the first phrase that matches */\nexports.find = function(fn) {\n if (!fn) {\n return this\n }\n let phrase = this.list.find((p, i) => {\n let doc = this.buildFrom([p])\n doc.from = null //it's not a child/parent\n return fn(doc, i)\n })\n if (phrase) {\n return this.buildFrom([phrase])\n }\n return undefined\n}\n\n/** return true or false if there is one matching phrase */\nexports.some = function(fn) {\n if (!fn) {\n return this\n }\n return this.list.some((p, i) => {\n let doc = this.buildFrom([p])\n doc.from = null //it's not a child/parent\n return fn(doc, i)\n })\n}\n\n/** sample a subset of the results */\nexports.random = function(n) {\n if (!this.found) {\n return this\n }\n let r = Math.floor(Math.random() * this.list.length)\n if (n === undefined) {\n let list = [this.list[r]]\n return this.buildFrom(list)\n }\n //prevent it from going over the end\n if (r + n > this.length) {\n r = this.length - n\n r = r < 0 ? 0 : r\n }\n return this.slice(r, r + n)\n}\n\n/** combine each phrase into a new data-structure */\n// exports.reduce = function(fn, h) {\n// let list = this.list.reduce((_h, ts) => {\n// let doc = this.buildFrom([ts])\n// doc.from = null //it's not a child/parent\n// return fn(_h, doc)\n// }, h)\n// return this.buildFrom(list)\n// }\n","const tokenize = require('../../01-tokenizer/02-words')\n\n// compare one term and one match\nconst doesMatch = function(term, str) {\n if (str === '') {\n return false\n }\n return term.reduced === str || term.implicit === str || term.root === str || term.text.toLowerCase() === str\n}\n\n// is this lookup found in these terms?\nconst findStart = function(arr, terms) {\n //find the start\n for (let i = 0; i < terms.length; i++) {\n if (doesMatch(terms[i], arr[0])) {\n if (arr.every((a, n) => doesMatch(terms[i + n], a) === true)) {\n return terms[i].id\n }\n }\n }\n return false\n}\n\n/** lookup an array of words or phrases */\nexports.lookup = function(arr) {\n if (typeof arr === 'string') {\n arr = [arr]\n }\n let lookups = arr.map(str => {\n str = str.toLowerCase()\n let words = tokenize(str)\n words = words.map(s => s.trim())\n return words\n })\n this.cache()\n let found = []\n // try each lookup\n lookups.forEach(a => {\n //try each phrase\n this.list.forEach(p => {\n // cache-miss, skip.\n if (p.cache.words[a[0]] !== true) {\n return\n }\n //we found a potential match\n let terms = p.terms()\n let id = findStart(a, terms)\n if (id !== false) {\n // create the actual phrase\n let phrase = p.buildFrom(id, a.length)\n found.push(phrase)\n return\n }\n })\n })\n return this.buildFrom(found)\n}\n","const tokenize = require('../../../01-tokenizer')\n\nconst titleCase = str => {\n return str.charAt(0).toUpperCase() + str.substr(1)\n}\n\n/** substitute-in new content */\nexports.replaceWith = function(replace, keepTags, keepCase) {\n if (!replace) {\n return this.delete()\n }\n // clear the cache\n this.uncache()\n // return this\n this.list.forEach(p => {\n let input = replace\n // accept a function for replace\n if (typeof replace === 'function') {\n input = replace(p)\n }\n let newPhrases\n // accept a Doc object to replace\n if (input && typeof input === 'object' && input.isA === 'Doc') {\n newPhrases = input.list\n this.pool().merge(input.pool())\n } else if (typeof input === 'string') {\n //input is a string\n if (keepCase === true && p.terms(0).isTitleCase()) {\n input = titleCase(input)\n }\n newPhrases = tokenize.fromText(input, this.world, this.pool())\n //tag the new phrases\n let tmpDoc = this.buildFrom(newPhrases)\n tmpDoc.tagger()\n } else {\n return //don't even bother\n }\n\n // try to keep its old tags, if appropriate\n if (keepTags === true) {\n let oldTags = p.json({ terms: { tags: true } }).terms\n newPhrases[0].terms().forEach((t, i) => {\n if (oldTags[i]) {\n t.tagSafe(oldTags[i].tags, 'keptTag', this.world)\n }\n })\n }\n p.replace(newPhrases[0], this) //Oneday: support multi-sentence replacements\n })\n return this\n}\n\n/** search and replace match with new content */\nexports.replace = function(match, replace, keepTags, keepCase) {\n // if there's no 2nd param, use replaceWith\n if (replace === undefined) {\n return this.replaceWith(match)\n }\n this.match(match).replaceWith(replace, keepTags, keepCase)\n return this\n}\n","const tokenize = require('../../../01-tokenizer')\n\n/** add these new terms to the end*/\nexports.append = function(str) {\n if (!str) {\n return this\n }\n // clear the cache\n this.uncache()\n //add it to end of every phrase\n this.list.forEach(p => {\n //build it\n let phrase = tokenize.fromText(str, this.world, this.pool())[0] //assume it's one sentence, for now\n //tag it\n let tmpDoc = this.buildFrom([phrase])\n tmpDoc.tagger()\n // push it onto the end\n p.append(phrase, this)\n })\n return this\n}\nexports.insertAfter = exports.append\nexports.insertAt = exports.append\n\n/** add these new terms to the front*/\nexports.prepend = function(str) {\n if (!str) {\n return this\n }\n // clear the cache\n this.uncache()\n //add it to start of every phrase\n this.list.forEach(p => {\n //build it\n let phrase = tokenize.fromText(str, this.world, this.pool())[0] //assume it's one sentence, for now\n //tag it\n let tmpDoc = this.buildFrom([phrase])\n tmpDoc.tagger()\n // add it to the start\n p.prepend(phrase, this)\n })\n return this\n}\nexports.insertBefore = exports.prepend\n\n/** add these new things to the end*/\nexports.concat = function() {\n // clear the cache\n this.uncache()\n let list = this.list.slice(0)\n //repeat for any number of params\n for (let i = 0; i < arguments.length; i++) {\n let arg = arguments[i]\n //support a fresh string\n if (typeof arg === 'string') {\n let arr = tokenize.fromText(arg, this.world)\n //TODO: phrase.tagger()?\n list = list.concat(arr)\n } else if (arg.isA === 'Doc') {\n list = list.concat(arg.list)\n } else if (arg.isA === 'Phrase') {\n list.push(arg)\n }\n }\n return this.buildFrom(list)\n}\n\n/** fully remove these terms from the document */\nexports.delete = function(match) {\n // clear the cache\n this.uncache()\n let toRemove = this\n if (match) {\n toRemove = this.match(match)\n }\n toRemove.list.forEach(phrase => phrase.delete(this))\n return this\n}\n// aliases\nexports.remove = exports.delete\n","/** return the document as text */\nexports.text = function(options) {\n options = options || {}\n //are we showing every phrase?\n let showFull = false\n if (this.parents().length === 0) {\n showFull = true\n }\n // cache roots, if necessary\n if (options === 'root' || (typeof options === 'object' && options.root)) {\n this.list.forEach(p => {\n p.terms().forEach(t => {\n if (t.root === null) {\n t.setRoot(this.world)\n }\n })\n })\n }\n\n return this.list.reduce((str, p, i) => {\n const trimPre = !showFull && i === 0\n const trimPost = !showFull && i === this.list.length - 1\n return str + p.text(options, trimPre, trimPost)\n }, '')\n}\n","const jsonDefaults = { text: true, terms: true, trim: true }\n\n// get all character startings in doc\nconst termOffsets = function(doc) {\n let elapsed = 0\n let index = 0\n let offsets = {}\n doc.termList().forEach(term => {\n offsets[term.id] = {\n index: index,\n start: elapsed + term.pre.length,\n length: term.text.length,\n }\n elapsed += term.pre.length + term.text.length + term.post.length\n index += 1\n })\n return offsets\n}\n\n/** pull out desired metadata from the document */\nexports.json = function(options = {}) {\n //support json(3) format\n if (typeof options === 'number' && this.list[options]) {\n return this.list[options].json(jsonDefaults)\n }\n options = Object.assign({}, jsonDefaults, options)\n\n // cache roots, if necessary\n if (options === 'root' || (typeof options === 'object' && options.root)) {\n this.list.forEach(p => {\n p.terms().forEach(t => {\n if (t.root === null) {\n t.setRoot(this.world)\n }\n })\n })\n }\n\n if (options.unique) {\n options.reduced = true\n }\n if (options.offset) {\n options.terms = options.terms === true ? {} : options.terms\n options.terms.offset = true\n }\n if (options.index || options.terms.index) {\n options.terms = options.terms === true ? {} : options.terms\n options.terms.id = true\n }\n let result = this.list.map(p => {\n return p.json(options, this.world)\n })\n // add offset and index data for each term\n if (options.terms.offset || options.offset || options.terms.index || options.index) {\n // calculate them, (from beginning of doc)\n let offsets = termOffsets(this.all())\n // add index values\n if (options.terms.index || options.index) {\n result.forEach(o => {\n o.terms.forEach(t => {\n t.index = offsets[t.id].index\n })\n o.index = o.terms[0].index\n })\n }\n // add offset values\n if (options.terms.offset || options.offset) {\n result.forEach(o => {\n o.terms.forEach(t => {\n t.offset = offsets[t.id] || {}\n })\n let len = o.terms.reduce((n, t) => {\n n += t.offset.length || 0\n return n\n }, 0)\n o.offset = o.terms[0].offset\n o.offset.length = len\n })\n }\n }\n // add frequency #s\n if (options.frequency || options.freq || options.count) {\n let obj = {}\n this.list.forEach(p => {\n let str = p.text('reduced')\n obj[str] = obj[str] || 0\n obj[str] += 1\n })\n this.list.forEach((p, i) => {\n result[i].count = obj[p.text('reduced')]\n })\n }\n // remove duplicates\n if (options.unique) {\n let already = {}\n result = result.filter(o => {\n if (already[o.reduced] === true) {\n return false\n }\n already[o.reduced] = true\n return true\n })\n }\n return result\n}\n\n//aliases\nexports.data = exports.json\n","const entity = ['Person', 'Place', 'Organization']\n\nmodule.exports = {\n Noun: {\n notA: ['Verb', 'Adjective', 'Adverb'],\n },\n // - singular\n Singular: {\n isA: 'Noun',\n notA: 'Plural',\n },\n //a specific thing that's capitalized\n ProperNoun: {\n isA: 'Noun',\n },\n\n // -- people\n Person: {\n isA: ['ProperNoun', 'Singular'],\n notA: ['Place', 'Organization'],\n },\n FirstName: {\n isA: 'Person',\n },\n MaleName: {\n isA: 'FirstName',\n notA: ['FemaleName', 'LastName'],\n },\n FemaleName: {\n isA: 'FirstName',\n notA: ['MaleName', 'LastName'],\n },\n LastName: {\n isA: 'Person',\n notA: ['FirstName'],\n },\n Honorific: {\n isA: 'Noun',\n notA: ['FirstName', 'LastName'],\n },\n\n // -- places\n Place: {\n isA: 'Singular',\n notA: ['Person', 'Organization'],\n },\n Country: {\n isA: ['Place', 'ProperNoun'],\n notA: ['City'],\n },\n City: {\n isA: ['Place', 'ProperNoun'],\n notA: ['Country'],\n },\n Region: {\n isA: ['Place', 'ProperNoun'],\n },\n Address: {\n isA: 'Place',\n },\n\n //---Orgs---\n Organization: {\n isA: ['Singular', 'ProperNoun'],\n notA: ['Person', 'Place'],\n },\n SportsTeam: {\n isA: 'Organization',\n },\n School: {\n isA: 'Organization',\n },\n Company: {\n isA: 'Organization',\n },\n\n // - plural\n Plural: {\n isA: 'Noun',\n notA: ['Singular'],\n },\n //(not plural or singular)\n Uncountable: {\n isA: 'Noun',\n },\n Pronoun: {\n isA: 'Noun',\n notA: entity,\n },\n //a word for someone doing something -'plumber'\n Actor: {\n isA: 'Noun',\n notA: entity,\n },\n //a gerund-as-noun - 'swimming'\n Activity: {\n isA: 'Noun',\n notA: ['Person', 'Place'],\n },\n //'kilograms'\n Unit: {\n isA: 'Noun',\n notA: entity,\n },\n //'Canadians'\n Demonym: {\n isA: ['Noun', 'ProperNoun'],\n notA: entity,\n },\n //`john's`\n Possessive: {\n isA: 'Noun',\n // notA: 'Pronoun',\n },\n}\n","module.exports = {\n Verb: {\n notA: ['Noun', 'Adjective', 'Adverb', 'Value'],\n },\n // walks\n PresentTense: {\n isA: 'Verb',\n notA: ['PastTense', 'Copula', 'FutureTense'],\n },\n // neutral form - 'walk'\n Infinitive: {\n isA: 'PresentTense',\n notA: ['PastTense', 'Gerund'],\n },\n // walking\n Gerund: {\n isA: 'PresentTense',\n notA: ['PastTense', 'Copula', 'FutureTense'],\n },\n // walked\n PastTense: {\n isA: 'Verb',\n notA: ['FutureTense'],\n },\n // will walk\n FutureTense: {\n isA: 'Verb',\n },\n\n // is\n Copula: {\n isA: 'Verb',\n },\n // would have\n Modal: {\n isA: 'Verb',\n notA: ['Infinitive'],\n },\n // had walked\n PerfectTense: {\n isA: 'Verb',\n notA: 'Gerund',\n },\n Pluperfect: {\n isA: 'Verb',\n },\n // shown\n Participle: {\n isA: 'Verb',\n },\n // show up\n PhrasalVerb: {\n isA: 'Verb',\n },\n //'up' part\n Particle: {\n isA: 'PhrasalVerb',\n },\n}\n","module.exports = {\n Value: {\n notA: ['Verb', 'Adjective', 'Adverb'],\n },\n Ordinal: {\n isA: 'Value',\n notA: ['Cardinal'],\n },\n Cardinal: {\n isA: 'Value',\n notA: ['Ordinal'],\n },\n RomanNumeral: {\n isA: 'Cardinal', //can be a person, too\n notA: ['Ordinal', 'TextValue'],\n },\n TextValue: {\n isA: 'Value',\n notA: ['NumericValue'],\n },\n NumericValue: {\n isA: 'Value',\n notA: ['TextValue'],\n },\n Money: {\n isA: 'Cardinal',\n },\n Percent: {\n isA: 'Value',\n },\n}\n","const anything = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Value']\n\nmodule.exports = {\n //--Adjectives--\n Adjective: {\n notA: ['Noun', 'Verb', 'Adverb', 'Value'],\n },\n // adjectives that can conjugate\n Comparable: {\n isA: ['Adjective'],\n },\n // better\n Comparative: {\n isA: ['Adjective'],\n },\n // best\n Superlative: {\n isA: ['Adjective'],\n notA: ['Comparative'],\n },\n\n NumberRange: {\n isA: ['Contraction'],\n },\n Adverb: {\n notA: ['Noun', 'Verb', 'Adjective', 'Value'],\n },\n\n // Dates:\n //not a noun, but usually is\n Date: {\n notA: ['Verb', 'Conjunction', 'Adverb', 'Preposition', 'Adjective'],\n },\n Month: {\n isA: ['Date', 'Singular'],\n notA: ['Year', 'WeekDay', 'Time'],\n },\n WeekDay: {\n isA: ['Date', 'Noun'],\n },\n\n //glue\n Determiner: {\n notA: anything,\n },\n Conjunction: {\n notA: anything,\n },\n Preposition: {\n notA: anything,\n },\n\n // what, who, why\n QuestionWord: {\n notA: ['Determiner'],\n },\n\n // peso, euro\n Currency: {},\n // ughh\n Expression: {\n notA: ['Noun', 'Adjective', 'Verb', 'Adverb'],\n },\n // dr.\n Abbreviation: {},\n\n // internet tags\n Url: {\n notA: ['HashTag', 'PhoneNumber', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'],\n },\n PhoneNumber: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'],\n },\n HashTag: {},\n AtMention: {\n isA: ['Noun'],\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'Email'],\n },\n Emoji: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'],\n },\n Emoticon: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'],\n },\n Email: {\n notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'],\n },\n\n //non-exclusive\n Auxiliary: {\n notA: ['Noun', 'Adjective', 'Value'],\n },\n Acronym: {\n notA: ['Plural', 'RomanNumeral'],\n },\n Negative: {\n notA: ['Noun', 'Adjective', 'Value'],\n },\n // if, unless, were\n Condition: {\n notA: ['Verb', 'Adjective', 'Noun', 'Value'],\n },\n}\n","// i just made these up\nconst colorMap = {\n Noun: 'blue',\n\n Verb: 'green',\n Negative: 'green',\n\n Date: 'red',\n Value: 'red',\n\n Adjective: 'magenta',\n\n Preposition: 'cyan',\n Conjunction: 'cyan',\n Determiner: 'cyan',\n Adverb: 'cyan',\n}\n\n/** add a debug color to some tags */\nconst addColors = function(tags) {\n Object.keys(tags).forEach(k => {\n if (colorMap[k]) {\n tags[k].color = colorMap[k]\n return\n }\n tags[k].isA.some(t => {\n if (colorMap[t]) {\n tags[k].color = colorMap[t]\n return true\n }\n return false\n })\n })\n return tags\n}\n\nmodule.exports = addColors\n","const unique = function(arr) {\n return arr.filter((v, i, a) => a.indexOf(v) === i)\n}\n\n//add 'downward' tags (that immediately depend on this one)\nconst inferIsA = function(tags) {\n Object.keys(tags).forEach(k => {\n let tag = tags[k]\n let len = tag.isA.length\n for (let i = 0; i < len; i++) {\n let down = tag.isA[i]\n if (tags[down]) {\n tag.isA = tag.isA.concat(tags[down].isA)\n }\n }\n // clean it up\n tag.isA = unique(tag.isA)\n })\n return tags\n}\nmodule.exports = inferIsA\n","const unique = function(arr) {\n return arr.filter((v, i, a) => a.indexOf(v) === i)\n}\n\n// crawl the tag-graph and infer any conflicts\n// faster than doing this at tag-time\nconst inferNotA = function(tags) {\n let keys = Object.keys(tags)\n keys.forEach(k => {\n let tag = tags[k]\n tag.notA = tag.notA || []\n tag.isA.forEach(down => {\n if (tags[down] && tags[down].notA) {\n // borrow its conflicts\n let notA = typeof tags[down].notA === 'string' ? [tags[down].isA] : tags[down].notA || []\n tag.notA = tag.notA.concat(notA)\n }\n })\n // any tag that lists us as a conflict, we conflict it back.\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]\n if (tags[key].notA.indexOf(k) !== -1) {\n tag.notA.push(key)\n }\n }\n // clean it up\n tag.notA = unique(tag.notA)\n })\n return tags\n}\nmodule.exports = inferNotA\n","// a lineage is all 'incoming' tags that have this as 'isA'\nconst inferLineage = function(tags) {\n let keys = Object.keys(tags)\n keys.forEach(k => {\n let tag = tags[k]\n tag.lineage = []\n // find all tags with it in their 'isA' set\n for (let i = 0; i < keys.length; i++) {\n if (tags[keys[i]].isA.indexOf(k) !== -1) {\n tag.lineage.push(keys[i])\n }\n }\n })\n return tags\n}\nmodule.exports = inferLineage\n","const inferColor = require('./_color')\nconst inferIsA = require('./_isA')\nconst inferNotA = require('./_notA')\nconst lineage = require('./_lineage')\n\nconst validate = function(tags) {\n // cleanup format\n Object.keys(tags).forEach(k => {\n let tag = tags[k]\n // ensure isA is an array\n tag.isA = tag.isA || []\n if (typeof tag.isA === 'string') {\n tag.isA = [tag.isA]\n }\n // ensure notA is an array\n tag.notA = tag.notA || []\n if (typeof tag.notA === 'string') {\n tag.notA = [tag.notA]\n }\n })\n return tags\n}\n\n// build-out the tag-graph structure\nconst inferTags = function(tags) {\n // validate data\n tags = validate(tags)\n // build its 'down tags'\n tags = inferIsA(tags)\n // infer the conflicts\n tags = inferNotA(tags)\n // debug tag color\n tags = inferColor(tags)\n // find incoming links\n tags = lineage(tags)\n return tags\n}\nmodule.exports = inferTags\n","const nouns = require('./tags/nouns')\nconst verbs = require('./tags/verbs')\nconst values = require('./tags/values')\nconst misc = require('./tags/misc')\nconst inferTags = require('./inference/index')\n\n//extend tagset with new tags\nconst addIn = function(obj, tags) {\n Object.keys(obj).forEach(k => {\n tags[k] = obj[k]\n })\n}\n\nconst build = () => {\n let tags = {}\n addIn(nouns, tags)\n addIn(verbs, tags)\n addIn(values, tags)\n addIn(misc, tags)\n // do the graph-stuff\n tags = inferTags(tags)\n return tags\n}\nmodule.exports = build()\n","const tagset = require('../../world/tags')\n\n// https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color\nconst reset = '\\x1b[0m'\n\nconst padEnd = function(str, width) {\n str = str.toString()\n while (str.length < width) {\n str += ' '\n }\n return str\n}\n\n//cheaper than requiring chalk\nconst cli = {\n green: function(str) {\n return '\\x1b[32m' + str + reset\n },\n red: function(str) {\n return '\\x1b[31m' + str + reset\n },\n blue: function(str) {\n return '\\x1b[34m' + str + reset\n },\n magenta: function(str) {\n return '\\x1b[35m' + str + reset\n },\n cyan: function(str) {\n return '\\x1b[36m' + str + reset\n },\n yellow: function(str) {\n return '\\x1b[33m' + str + reset\n },\n black: function(str) {\n return '\\x1b[30m' + str + reset\n },\n}\n\nconst tagString = function(tags) {\n tags = tags.map(tag => {\n if (!tagset.hasOwnProperty(tag)) {\n return tag\n }\n const c = tagset[tag].color || 'blue'\n return cli[c](tag)\n })\n return tags.join(', ')\n}\n\n//output some helpful stuff to the console\nconst debug = function(doc) {\n console.log(cli.blue('====='))\n doc.list.forEach(p => {\n console.log(cli.blue(' -----'))\n p.terms().forEach(t => {\n let tags = Object.keys(t.tags)\n let text = t.text || '-'\n if (t.implicit) {\n text = '[' + t.implicit + ']'\n }\n if (typeof module !== undefined) {\n text = cli.yellow(text)\n }\n let word = \"'\" + text + \"'\"\n word = padEnd(word, 18)\n let str = cli.blue(' | ') + word + ' - ' + tagString(tags)\n console.log(str)\n })\n })\n console.log('')\n return doc\n}\nmodule.exports = debug\n","const topk = function(doc) {\n let list = doc.json({ text: false, terms: false, reduced: true })\n // combine them\n let obj = {}\n list.forEach(o => {\n if (!obj[o.reduced]) {\n o.count = 0\n obj[o.reduced] = o\n }\n obj[o.reduced].count += 1\n })\n let arr = Object.keys(obj).map(k => obj[k])\n // sort them\n arr.sort((a, b) => {\n if (a.count > b.count) {\n return -1\n } else if (a.count < b.count) {\n return 1\n }\n return 0\n })\n return arr\n}\nmodule.exports = topk\n","const debug = require('../_debug')\nconst topk = require('./_topk')\n\n/** pretty-print the current document and its tags */\nexports.debug = function() {\n debug(this)\n return this\n}\n\n/** some named output formats */\nexports.out = function(method) {\n if (method === 'text') {\n return this.text()\n }\n if (method === 'normal') {\n return this.text('normal')\n }\n if (method === 'json') {\n return this.json()\n }\n if (method === 'offset' || method === 'offsets') {\n return this.json({ offset: true })\n }\n if (method === 'array') {\n return this.json({ terms: false }).map(obj => obj.text)\n }\n if (method === 'freq' || method === 'frequency') {\n return topk(this)\n }\n if (method === 'terms') {\n let list = []\n this.json({ text: false, terms: { text: true } }).forEach(obj => {\n let terms = obj.terms.map(t => t.text)\n terms = terms.filter(t => t)\n list = list.concat(terms)\n })\n return list\n }\n if (method === 'tags') {\n return this.list.map(p => {\n return p.terms().reduce((h, t) => {\n h[t.clean || t.implicit] = Object.keys(t.tags)\n return h\n }, {})\n })\n }\n if (method === 'debug') {\n debug(this)\n return this\n }\n return this.text()\n}\n","// compress a list of things by frequency\nconst topk = function(list) {\n let counts = {}\n list.forEach(a => {\n counts[a] = counts[a] || 0\n counts[a] += 1\n })\n let arr = Object.keys(counts)\n arr = arr.sort((a, b) => {\n if (counts[a] > counts[b]) {\n return -1\n } else {\n return 1\n }\n })\n // arr = arr.filter(a => counts[a] > 1)\n return arr.map(a => [a, counts[a]])\n}\n\n// remove implied tags, like 'Noun' when we have 'Plural'\nconst reduceTags = function(tags, world) {\n let tagset = world.tags\n let implied = []\n tags.forEach(tag => {\n if (tagset[tag] && tagset[tag].isA) {\n implied = implied.concat(tagset[tag].isA)\n }\n })\n implied = implied.reduce((h, tag) => {\n h[tag] = true\n return h\n }, {})\n tags = tags.filter(tag => !implied[tag])\n // tags\n return tags\n}\n\n/** store a parsed document for later use */\nexports.export = function() {\n let phraseList = this.json({ text: true, trim: false, terms: { tags: true, whitespace: true } })\n // let phraseList = json.map(p => p.terms)\n let allTags = []\n phraseList.forEach(p => {\n p.terms.forEach(t => {\n // reduce redundant tags\n let tags = reduceTags(t.tags, this.world)\n allTags = allTags.concat(tags)\n })\n })\n // compress the top tags\n allTags = topk(allTags)\n let tagMap = {}\n allTags.forEach((a, i) => {\n tagMap[a[0]] = i\n })\n\n //use index numbers instead of redundant tag-names\n phraseList = phraseList.map(p => {\n let terms = p.terms.map(term => {\n let tags = term.tags\n tags = reduceTags(tags, this.world)\n tags = tags.map(tag => tagMap[tag])\n tags = tags.join(',')\n return tags\n })\n terms = terms.join('|')\n return [p.text, terms]\n })\n\n return {\n tags: Object.keys(tagMap),\n // words: {},\n list: phraseList,\n }\n}\n","const methods = {\n /** alphabetical order */\n alpha: (a, b) => {\n let left = a.text('clean')\n let right = b.text('clean')\n if (left < right) {\n return -1\n }\n if (left > right) {\n return 1\n }\n return 0\n },\n\n /** count the # of characters of each match */\n length: (a, b) => {\n let left = a.text().trim().length\n let right = b.text().trim().length\n if (left < right) {\n return 1\n }\n if (left > right) {\n return -1\n }\n return 0\n },\n\n /** count the # of terms in each match */\n wordCount: (a, b) => {\n let left = a.wordCount()\n let right = b.wordCount()\n if (left < right) {\n return 1\n }\n if (left > right) {\n return -1\n }\n return 0\n },\n}\n\n/** sort by # of duplicates in the document*/\nconst byFreq = function(doc) {\n let counts = {}\n const options = {\n case: true,\n punctuation: false,\n whitespace: true,\n unicode: true,\n }\n doc.list.forEach(p => {\n let str = p.text(options)\n counts[str] = counts[str] || 0\n counts[str] += 1\n })\n // sort by freq\n doc.list.sort((a, b) => {\n let left = counts[a.text(options)]\n let right = counts[b.text(options)]\n if (left < right) {\n return 1\n }\n if (left > right) {\n return -1\n }\n return 0\n })\n return doc\n}\n\n// order results 'chronologically', or document-order\nconst sortSequential = function(doc) {\n let order = {}\n doc.json({ terms: { offset: true } }).forEach(o => {\n order[o.terms[0].id] = o.terms[0].offset.start\n })\n doc.list = doc.list.sort((a, b) => {\n if (order[a.start] > order[b.start]) {\n return 1\n } else if (order[a.start] < order[b.start]) {\n return -1\n }\n return 0\n })\n return doc\n}\n\n//aliases\nmethods.alphabetical = methods.alpha\nmethods.wordcount = methods.wordCount\n\n// aliases for sequential ordering\nconst seqNames = {\n index: true,\n sequence: true,\n seq: true,\n sequential: true,\n chron: true,\n chronological: true,\n}\n\n/** re-arrange the order of the matches (in place) */\nexports.sort = function(input) {\n input = input || 'alpha'\n //do this one up-front\n if (input === 'freq' || input === 'frequency' || input === 'topk') {\n return byFreq(this)\n }\n if (seqNames.hasOwnProperty(input)) {\n return sortSequential(this)\n }\n\n input = methods[input] || input\n // apply sort method on each phrase\n if (typeof input === 'function') {\n this.list = this.list.sort(input)\n return this\n }\n return this\n}\n\n/** reverse the order of the matches, but not the words */\nexports.reverse = function() {\n let list = [].concat(this.list)\n list = list.reverse()\n return this.buildFrom(list)\n}\n\n/** remove any duplicate matches */\nexports.unique = function() {\n let list = [].concat(this.list)\n let obj = {}\n list = list.filter(p => {\n let str = p.text('reduced').trim()\n if (obj.hasOwnProperty(str) === true) {\n return false\n }\n obj[str] = true\n return true\n })\n return this.buildFrom(list)\n}\n","const killUnicode = require('../../../Term/normalize/unicode')\nconst isPunct = /[\\[\\]{}⟨⟩:,،、‒–—―…‹›«»‐\\-;\\/⁄·*\\•^†‡°¡¿※№÷׺ª%‰=‱¶§~|‖¦©℗®℠™¤₳฿]/g\nconst quotes = /['‘’“”\"′″‴]+/g\n\nconst methods = {\n // cleanup newlines and extra spaces\n whitespace: function(doc) {\n let termArr = doc.list.map(ts => ts.terms())\n termArr.forEach((terms, o) => {\n terms.forEach((t, i) => {\n // keep dashes between words\n if (t.hasDash() === true) {\n t.post = ' - '\n return\n }\n // remove existing spaces\n t.pre = t.pre.replace(/\\s/g, '')\n t.post = t.post.replace(/\\s/g, '')\n //last word? ensure there's a next sentence.\n if (terms.length - 1 === i && !termArr[o + 1]) {\n return\n }\n // no extra spaces for contractions\n if (t.implicit && Boolean(t.text) === true) {\n return\n }\n // no extra spaces for hyphenated words\n if (t.hasHyphen() === true) {\n return\n }\n\n t.post += ' '\n })\n })\n },\n\n punctuation: function(termList) {\n termList.forEach(t => {\n // space between hyphenated words\n if (t.hasHyphen() === true) {\n t.post = ' '\n }\n t.pre = t.pre.replace(isPunct, '')\n t.post = t.post.replace(isPunct, '')\n // elipses\n t.post = t.post.replace(/\\.\\.\\./, '')\n // only allow one exclamation\n if (/!/.test(t.post) === true) {\n t.post = t.post.replace(/!/g, '')\n t.post = '!' + t.post\n }\n // only allow one question mark\n if (/\\?/.test(t.post) === true) {\n t.post = t.post.replace(/[\\?!]*/, '')\n t.post = '?' + t.post\n }\n })\n },\n\n unicode: function(termList) {\n termList.forEach(t => {\n if (t.isImplicit() === true) {\n return\n }\n t.text = killUnicode(t.text)\n })\n },\n\n quotations: function(termList) {\n termList.forEach(t => {\n t.post = t.post.replace(quotes, '')\n t.pre = t.pre.replace(quotes, '')\n })\n },\n\n adverbs: function(doc) {\n doc\n .match('#Adverb')\n .not('(not|nary|seldom|never|barely|almost|basically|so)')\n .remove()\n },\n\n // remove the '.' from 'Mrs.' (safely)\n abbreviations: function(doc) {\n doc.list.forEach(ts => {\n let terms = ts.terms()\n terms.forEach((t, i) => {\n if (t.tags.Abbreviation === true && terms[i + 1]) {\n t.post = t.post.replace(/^\\./, '')\n }\n })\n })\n },\n}\nmodule.exports = methods\n","const methods = require('./_methods')\n\nconst defaults = {\n // light\n whitespace: true,\n unicode: true,\n punctuation: true,\n emoji: true,\n acronyms: true,\n abbreviations: true,\n\n // medium\n case: false,\n contractions: false,\n parentheses: false,\n quotations: false,\n adverbs: false,\n\n // heavy (loose legibility)\n possessives: false,\n verbs: false,\n nouns: false,\n honorifics: false,\n\n // pronouns: true,\n}\nconst mapping = {\n light: {},\n medium: { case: true, contractions: true, parentheses: true, quotations: true, adverbs: true },\n}\nmapping.heavy = Object.assign({}, mapping.medium, { possessives: true, verbs: true, nouns: true, honorifics: true })\n\n/** common ways to clean-up the document, and reduce noise */\nexports.normalize = function(options) {\n options = options || {}\n // support named forms\n if (typeof options === 'string') {\n options = mapping[options] || {}\n }\n // set defaults\n options = Object.assign({}, defaults, options)\n // clear the cache\n this.uncache()\n\n let termList = this.termList()\n\n // lowercase things\n if (options.case) {\n this.toLowerCase()\n }\n\n //whitespace\n if (options.whitespace) {\n methods.whitespace(this)\n }\n\n // unicode: é -> e\n if (options.unicode) {\n methods.unicode(termList)\n }\n\n //punctuation - keep sentence punctation, quotes, parenths\n if (options.punctuation) {\n methods.punctuation(termList)\n }\n\n // remove ':)'\n if (options.emoji) {\n this.remove('(#Emoji|#Emoticon)')\n }\n\n // 'f.b.i.' -> 'FBI'\n if (options.acronyms) {\n this.acronyms().strip()\n // .toUpperCase()\n }\n // remove period from abbreviations\n if (options.abbreviations) {\n methods.abbreviations(this)\n }\n\n // --Medium methods--\n\n // `isn't` -> 'is not'\n if (options.contraction || options.contractions) {\n this.contractions().expand()\n }\n\n // '(word)' -> 'word'\n if (options.parentheses) {\n this.parentheses().unwrap()\n }\n // remove \"\" punctuation\n if (options.quotations || options.quotes) {\n methods.quotations(termList)\n }\n\n // remove any un-necessary adverbs\n if (options.adverbs) {\n methods.adverbs(this)\n }\n\n // --Heavy methods--\n\n // `cory hart's -> cory hart'\n if (options.possessive || options.possessives) {\n this.possessives().strip()\n }\n // 'he walked' -> 'he walk'\n if (options.verbs) {\n this.verbs().toInfinitive()\n }\n // 'three dogs' -> 'three dog'\n if (options.nouns || options.plurals) {\n this.nouns().toSingular()\n }\n // remove 'Mr.' from 'Mr John Smith'\n if (options.honorifics) {\n this.remove('#Honorific')\n }\n\n return this\n}\n","const parseSyntax = require('../../match/syntax')\n\n/** return a Document with three parts for every match\n * seperate everything before the word, as a new phrase\n */\nexports.splitOn = function(reg) {\n // if there's no match, split parent, instead\n if (!reg) {\n let parent = this.parent()\n return parent.splitOn(this)\n }\n //start looking for a match..\n let regs = parseSyntax(reg)\n let matches = []\n this.list.forEach(p => {\n let foundEm = p.match(regs)\n //no match here, add full sentence\n if (foundEm.length === 0) {\n matches.push(p)\n return\n }\n // we found something here.\n let carry = p\n foundEm.forEach(found => {\n let parts = carry.splitOn(found)\n // add em in\n if (parts.before) {\n matches.push(parts.before)\n }\n if (parts.match) {\n matches.push(parts.match)\n }\n // start matching now on the end\n carry = parts.after\n })\n // add that last part\n if (carry) {\n matches.push(carry)\n }\n })\n return this.buildFrom(matches)\n}\n\n/** return a Document with two parts for every match\n * seperate everything after the word, as a new phrase\n */\nexports.splitAfter = function(reg) {\n // if there's no match, split parent, instead\n if (!reg) {\n let parent = this.parent()\n return parent.splitAfter(this)\n }\n // start looking for our matches\n let regs = parseSyntax(reg)\n let matches = []\n this.list.forEach(p => {\n let foundEm = p.match(regs)\n //no match here, add full sentence\n if (foundEm.length === 0) {\n matches.push(p)\n return\n }\n // we found something here.\n let carry = p\n foundEm.forEach(found => {\n let parts = carry.splitOn(found)\n // add em in\n if (parts.before && parts.match) {\n // merge these two together\n parts.before.length += parts.match.length\n matches.push(parts.before)\n } else if (parts.match) {\n matches.push(parts.match)\n }\n // start matching now on the end\n carry = parts.after\n })\n // add that last part\n if (carry) {\n matches.push(carry)\n }\n })\n return this.buildFrom(matches)\n}\nexports.split = exports.splitAfter //i guess?\n\n/** return a Document with two parts for every match */\nexports.splitBefore = function(reg) {\n // if there's no match, split parent, instead\n if (!reg) {\n let parent = this.parent()\n return parent.splitBefore(this)\n }\n //start looking for a match..\n let regs = parseSyntax(reg)\n let matches = []\n this.list.forEach(p => {\n let foundEm = p.match(regs)\n //no match here, add full sentence\n if (foundEm.length === 0) {\n matches.push(p)\n return\n }\n // we found something here.\n let carry = p\n foundEm.forEach(found => {\n let parts = carry.splitOn(found)\n // add before part in\n if (parts.before) {\n matches.push(parts.before)\n }\n // merge match+after\n if (parts.match && parts.after) {\n parts.match.length += parts.after.length\n }\n // start matching now on the end\n carry = parts.match\n })\n // add that last part\n if (carry) {\n matches.push(carry)\n }\n })\n return this.buildFrom(matches)\n}\n\n/** split a document into labeled sections */\nexports.segment = function(regs, options) {\n regs = regs || {}\n options = options || { text: true }\n let doc = this\n let keys = Object.keys(regs)\n // split em\n keys.forEach(k => {\n doc = doc.splitOn(k)\n })\n //add labels for each section\n doc.list.forEach(p => {\n for (let i = 0; i < keys.length; i += 1) {\n if (p.has(keys[i])) {\n p.segment = regs[keys[i]]\n return\n }\n }\n })\n return doc.list.map(p => {\n let res = p.json(options)\n res.segment = p.segment || null\n return res\n })\n}\n","const eachTerm = function(doc, fn) {\n let world = doc.world\n doc.list.forEach(p => {\n p.terms().forEach(t => t[fn](world))\n })\n return doc\n}\n\n/** turn every letter of every term to lower-cse */\nexports.toLowerCase = function() {\n return eachTerm(this, 'toLowerCase')\n}\n\n/** turn every letter of every term to upper case */\nexports.toUpperCase = function() {\n return eachTerm(this, 'toUpperCase')\n}\n\n/** upper-case the first letter of each term */\nexports.toTitleCase = function() {\n this.tag('TitleCase')\n return eachTerm(this, 'toTitleCase')\n}\n/** remove whitespace and title-case each term */\nexports.toCamelCase = function() {\n this.list.forEach(p => {\n //remove whitespace\n let terms = p.terms()\n terms.forEach((t, i) => {\n if (i !== 0) {\n t.toTitleCase()\n }\n if (i !== terms.length - 1) {\n t.post = ''\n }\n })\n })\n // this.tag('#CamelCase', 'toCamelCase')\n return this\n}\n","/** add this punctuation or whitespace before each match: */\nexports.pre = function(str) {\n if (str === undefined) {\n return this.list[0].terms(0).pre\n }\n this.list.forEach(p => {\n let term = p.terms(0)\n term.pre = str\n })\n return this\n}\n\n/** add this punctuation or whitespace after each match: */\nexports.post = function(str) {\n // return array of post strings\n if (str === undefined) {\n return this.list.map(p => {\n let terms = p.terms()\n let term = terms[terms.length - 1]\n return term.post\n })\n }\n // set post string on all ends\n this.list.forEach(p => {\n let terms = p.terms()\n let term = terms[terms.length - 1]\n term.post = str\n })\n return this\n}\n\n/** remove start and end whitespace */\nexports.trim = function() {\n this.list = this.list.map(p => p.trim())\n return this\n}\n\n/** connect words with hyphen, and remove whitespace */\nexports.hyphenate = function() {\n this.list.forEach(p => {\n let terms = p.terms()\n //remove whitespace\n terms.forEach((t, i) => {\n if (i !== 0) {\n t.pre = ''\n }\n if (terms[i + 1]) {\n t.post = '-'\n }\n })\n })\n return this\n}\n\n/** remove hyphens between words, and set whitespace */\nexports.dehyphenate = function() {\n const hasHyphen = /(-|–|—)/\n this.list.forEach(p => {\n let terms = p.terms()\n //remove whitespace\n terms.forEach(t => {\n if (hasHyphen.test(t.post)) {\n t.post = ' '\n }\n })\n })\n return this\n}\nexports.deHyphenate = exports.dehyphenate\n\n/** add quotations around these matches */\nexports.toQuotations = function(start, end) {\n start = start || `\"`\n end = end || `\"`\n this.list.forEach(p => {\n let terms = p.terms()\n terms[0].pre = start + terms[0].pre\n let last = terms[terms.length - 1]\n last.post = end + last.post\n })\n return this\n}\nexports.toQuotation = exports.toQuotations\n\n/** add brackets around these matches */\nexports.toParentheses = function(start, end) {\n start = start || `(`\n end = end || `)`\n this.list.forEach(p => {\n let terms = p.terms()\n terms[0].pre = start + terms[0].pre\n let last = terms[terms.length - 1]\n last.post = end + last.post\n })\n return this\n}\n","/** make all phrases into one phrase */\nexports.join = function(str) {\n // clear the cache\n this.uncache()\n // make one large phrase - 'main'\n let main = this.list[0]\n let before = main.length\n let removed = {}\n for (let i = 1; i < this.list.length; i++) {\n const p = this.list[i]\n removed[p.start] = true\n let term = main.lastTerm()\n // add whitespace between them\n if (str) {\n term.post += str\n }\n // main -> p\n term.next = p.start\n // main <- p\n p.terms(0).prev = term.id\n main.length += p.length\n }\n\n // parents are bigger than than their children.\n // when we increase a child, we increase their parent too.\n let increase = main.length - before\n this.parents().forEach(doc => {\n // increase length on each effected phrase\n doc.list.forEach(p => {\n let terms = p.terms()\n for (let i = 0; i < terms.length; i++) {\n if (terms[i].id === main.start) {\n p.length += increase\n break\n }\n }\n })\n // remove redundant phrases now\n doc.list = doc.list.filter(p => removed[p.start] !== true)\n })\n // return one major phrase\n return this.buildFrom([main])\n}\n","const postPunct = /[,\\)\"';:\\-–—\\.…]/\n// const irregulars = {\n// 'will not': `won't`,\n// 'i am': `i'm`,\n// }\n\nconst setContraction = function(m, suffix) {\n if (!m.found) {\n return\n }\n let terms = m.termList()\n //avoid any problematic punctuation\n for (let i = 0; i < terms.length - 1; i++) {\n const t = terms[i]\n if (postPunct.test(t.post)) {\n return\n }\n }\n\n // set them as implict\n terms.forEach(t => {\n t.implicit = t.clean\n })\n // perform the contraction\n terms[0].text += suffix\n // clean-up the others\n terms.slice(1).forEach(t => {\n t.text = ''\n })\n for (let i = 0; i < terms.length - 1; i++) {\n const t = terms[i]\n t.post = t.post.replace(/ /, '')\n }\n}\n\n/** turn 'i am' into i'm */\nexports.contract = function() {\n let doc = this.not('@hasContraction')\n // we are -> we're\n let m = doc.match('(we|they|you) are')\n setContraction(m, `'re`)\n // they will -> they'll\n m = doc.match('(he|she|they|it|we|you) will')\n setContraction(m, `'ll`)\n // she is -> she's\n m = doc.match('(he|she|they|it|we) is')\n setContraction(m, `'s`)\n // spencer is -> spencer's\n m = doc.match('#Person is')\n setContraction(m, `'s`)\n // spencer would -> spencer'd\n m = doc.match('#Person would')\n setContraction(m, `'d`)\n // would not -> wouldn't\n m = doc.match('(is|was|had|would|should|could|do|does|have|has|can) not')\n setContraction(m, `n't`)\n // i have -> i've\n m = doc.match('(i|we|they) have')\n setContraction(m, `'ve`)\n // would have -> would've\n m = doc.match('(would|should|could) have')\n setContraction(m, `'ve`)\n // i am -> i'm\n m = doc.match('i am')\n setContraction(m, `'m`)\n // going to -> gonna\n m = doc.match('going to')\n return this\n}\n","module.exports = Object.assign(\n {},\n require('./01-utils'),\n require('./02-accessors'),\n require('./03-match'),\n require('./04-tag'),\n require('./05-loops'),\n require('./06-lookup'),\n\n require('./insert/01-replace'),\n require('./insert/02-insert'),\n\n require('./output/01-text'),\n require('./output/02-json'),\n require('./output/03-out'),\n require('./output/04-export'),\n\n require('./transform/01-sort'),\n require('./transform/02-normalize'),\n require('./transform/03-split'),\n require('./transform/04-case'),\n require('./transform/05-whitespace'),\n require('./transform/06-join'),\n require('./transform/07-contract')\n)\n","let methods = {}\n\n// allow helper methods like .adjectives() and .adverbs()\nconst arr = [\n ['terms', '.'],\n ['hyphenated', '@hasHyphen .'],\n ['adjectives', '#Adjective'],\n ['hashTags', '#HashTag'],\n ['emails', '#Email'],\n ['emoji', '#Emoji'],\n ['emoticons', '#Emoticon'],\n ['atMentions', '#AtMention'],\n ['urls', '#Url'],\n ['adverbs', '#Adverb'],\n ['pronouns', '#Pronoun'],\n ['conjunctions', '#Conjunction'],\n ['prepositions', '#Preposition'],\n]\narr.forEach(a => {\n methods[a[0]] = function(n) {\n let m = this.match(a[1])\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n }\n})\n// aliases\nmethods.emojis = methods.emoji\nmethods.atmentions = methods.atMentions\nmethods.words = methods.terms\n\n/** return anything tagged as a phone number */\nmethods.phoneNumbers = function(n) {\n let m = this.splitAfter('@hasComma')\n m = m.match('#PhoneNumber+')\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n}\n\n/** money + currency pair */\nmethods.money = function(n) {\n let m = this.match('#Money #Currency?')\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n}\n\n/** return all cities, countries, addresses, and regions */\nmethods.places = function(n) {\n // don't split 'paris, france'\n let keep = this.match('(#City && @hasComma) (#Region|#Country)')\n // but split the other commas\n let m = this.not(keep).splitAfter('@hasComma')\n // combine them back together\n m = m.concat(keep)\n m.sort('index')\n m = m.match('#Place+')\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n}\n\n/** return all schools, businesses and institutions */\nmethods.organizations = function(n) {\n let m = this.clauses()\n m = m.match('#Organization+')\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n}\n\n//combine them with .topics() method\nmethods.entities = function(n) {\n let r = this.clauses()\n // Find people, places, and organizations\n let yup = r.people()\n yup = yup.concat(r.places())\n yup = yup.concat(r.organizations())\n let ignore = ['someone', 'man', 'woman', 'mother', 'brother', 'sister', 'father']\n yup = yup.not(ignore)\n //return them to normal ordering\n yup.sort('sequence')\n // yup.unique() //? not sure\n if (typeof n === 'number') {\n yup = yup.get(n)\n }\n return yup\n}\n//aliases\nmethods.things = methods.entities\nmethods.topics = methods.entities\n\n/** alias for .all() until it gets overloaded by plugin */\nmethods.sentences = function() {\n return this.all()\n}\n\nmodule.exports = methods\n","/** match a word-sequence, like 'super bowl' in the lexicon */\nconst tryMultiple = function(terms, t, world) {\n let lex = world.words\n //try a two-word version\n let txt = terms[t].reduced + ' ' + terms[t + 1].reduced\n if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) {\n terms[t].tag(lex[txt], 'lexicon-two', world)\n terms[t + 1].tag(lex[txt], 'lexicon-two', world)\n return 1\n }\n //try a three-word version?\n if (t + 2 < terms.length) {\n txt += ' ' + terms[t + 2].reduced\n if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) {\n terms[t].tag(lex[txt], 'lexicon-three', world)\n terms[t + 1].tag(lex[txt], 'lexicon-three', world)\n terms[t + 2].tag(lex[txt], 'lexicon-three', world)\n return 2\n }\n }\n //try a four-word version?\n if (t + 3 < terms.length) {\n txt += ' ' + terms[t + 3].reduced\n if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) {\n terms[t].tag(lex[txt], 'lexicon-four', world)\n terms[t + 1].tag(lex[txt], 'lexicon-four', world)\n terms[t + 2].tag(lex[txt], 'lexicon-four', world)\n terms[t + 3].tag(lex[txt], 'lexicon-four', world)\n return 3\n }\n }\n return 0\n}\n\n/** look at each word in our list of known-words */\nconst checkLexicon = function(terms, world) {\n let lex = world.words\n let hasCompound = world.hasCompound // use reduced?\n //go through each term, and check the lexicon\n for (let t = 0; t < terms.length; t += 1) {\n let str = terms[t].clean\n //is it the start of a compound word, like 'super bowl'?\n if (hasCompound[str] === true && t + 1 < terms.length) {\n let foundWords = tryMultiple(terms, t, world)\n if (foundWords > 0) {\n t += foundWords //skip any already-found words\n continue\n }\n }\n //try one-word lexicon\n if (lex[str] !== undefined && lex.hasOwnProperty(str) === true) {\n terms[t].tag(lex[str], 'lexicon', world)\n }\n // look at reduced version of term, too\n if (str !== terms[t].reduced && lex.hasOwnProperty(terms[t].reduced) === true) {\n terms[t].tag(lex[terms[t].reduced], 'lexicon', world)\n }\n }\n return terms\n}\nmodule.exports = checkLexicon\n","const apostrophes = /[\\'‘’‛‵′`´]$/\nconst oneLetterAcronym = /^[A-Z]('s|,)?$/\n\nconst oneLetterWord = {\n I: true,\n A: true,\n}\n\nconst isAcronym = function(term, world) {\n let str = term.reduced\n // a known acronym like fbi\n if (term.tags.Acronym) {\n return true\n }\n // if (term.tags.Adverb || term.tags.Verb || term.tags.Value || term.tags.Plural) {\n // return false\n // }\n // 'PIZZA' is not an acronym.\n if (str.length > 4 && world.words[str]) {\n return false\n }\n return term.isAcronym()\n}\n\n//\nconst checkPunctuation = function(terms, i, world) {\n let term = terms[i]\n\n //check hyphenation\n // if (term.post.indexOf('-') !== -1 && terms[i + 1] && terms[i + 1].pre === '') {\n // term.tag('Hyphenated', 'has-hyphen', world)\n // }\n\n //an end-tick (trailing apostrophe) - flanders', or Carlos'\n if (apostrophes.test(term.text)) {\n if (!apostrophes.test(term.pre) && !apostrophes.test(term.post) && term.clean.length > 2) {\n let endChar = term.clean[term.clean.length - 2]\n //flanders'\n if (endChar === 's') {\n term.tag(['Possessive', 'Noun'], 'end-tick', world)\n return\n }\n //chillin'\n if (endChar === 'n') {\n term.tag(['Gerund'], 'chillin', world)\n }\n }\n }\n // 'NASA' is, but not 'i REALLY love it.'\n if (isAcronym(term, world)) {\n term.tag('Acronym', 'acronym-step', world)\n term.tag('Noun', 'acronym-infer', world)\n } else if (!oneLetterWord.hasOwnProperty(term.text) && oneLetterAcronym.test(term.text)) {\n term.tag('Acronym', 'one-letter-acronym', world)\n term.tag('Noun', 'one-letter-infer', world)\n }\n}\nmodule.exports = checkPunctuation\n","//these are regexes applied to t.text, instead of t.clean\n// order matters.\nmodule.exports = [\n //phone numbers\n [/^[0-9]{3}-[0-9]{4}$/, 'PhoneNumber'], //589-3809\n [/^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$/, 'PhoneNumber'], //632-589-3809\n\n //money\n [/^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?([a-z]{1,4})?$/, ['Money', 'Value']], //like $5.30\n [/^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$/, ['Money', 'Value']], //like $5,231.30\n [/^[-+]?[0-9]([0-9,.]+)?(usd|eur|jpy|gbp|cad|aud|chf|cny|hkd|nzd|kr|rub)$/i, ['Money', 'Value']], //like 400usd\n\n //web tags\n [/^\\w+@\\w+\\.[a-z]{2,3}$/, 'Email'], //not fancy\n [/^#[a-z0-9_\\u00C0-\\u00FF]{2,}$/, 'HashTag'],\n [/^@\\w{2,}$/, 'AtMention'],\n [/^(https?:\\/\\/|www\\.)\\w+\\.[a-z]{2,3}/, 'Url'], //with http/www\n [/^[\\w\\.\\/]+\\.(com|net|gov|org|ly|edu|info|biz|ru|jp|de|in|uk|br)/, 'Url'], //http://mostpopularwebsites.net/top-level-domain\n\n //dates/times\n [/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$/, 'Time'], //4:32:32\n [/^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$/, 'Time'], //4pm\n [/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$/, 'Time'], //4:00pm\n [/^[PMCE]ST$/, 'Time'], //PST, time zone abbrevs\n [/^utc ?[+-]?[0-9]+?$/, 'Time'], //UTC 8+\n [/^[a-z0-9]*? o\\'?clock$/, 'Time'], //3 oclock\n [/^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$/, 'Date'], // 03-02-89\n [/^[0-9]{1,4}\\/[0-9]{1,2}\\/[0-9]{1,4}$/, 'Date'], // 03/02/89\n\n //names\n [/^ma?c\\'.*/, 'LastName'], //mc'adams\n [/^o\\'[drlkn].*/, 'LastName'], //o'douggan\n [/^ma?cd[aeiou]/, 'LastName'], //macdonell - Last patterns https://en.wikipedia.org/wiki/List_of_family_name_affixes\n\n //slang things\n [/^(lol)+[sz]$/, 'Expression'], //lol\n [/^(un|de|re)\\\\-[a-z\\u00C0-\\u00FF]{2}/, 'Verb'],\n [/^[\\-\\+]?[0-9]+(\\.[0-9])*$/, ['Cardinal', 'NumericValue']],\n [/^(over|under)[a-z]{2,}/, 'Adjective'],\n [/^[0-9]{1,4}\\.[0-9]{1,2}\\.[0-9]{1,4}$/, 'Date'], // 03-02-89\n\n //numbers\n [/^[\\-\\+]?[0-9][0-9,]*(\\.[0-9])*$/, ['Cardinal', 'NumericValue']], //like 5\n [/^[-+]?[0-9]+(.[0-9]+)?$/, ['Cardinal', 'NumericValue']], //like +5.0\n [/^[0-9\\.]{1,4}(st|nd|rd|th)?[-–][0-9\\.]{1,4}(st|nd|rd|th)?$/, 'NumberRange'], //5-7\n [/^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$/, 'NumericValue'], //like 5,999.0\n [/^.?[0-9]+([0-9,.]+)?%$/, ['Percent', 'Cardinal', 'NumericValue']], //7% ..\n [/^[0-9]{1,4}\\/[0-9]{1,4}$/, 'Fraction'], //3/2ths\n [/^[0-9\\.]{1,2}[-–][0-9]{1,2}$/, ['Value', 'NumberRange']], //7-8\n [/^[0-9][0-9,\\.]*(st|nd|rd|r?th)$/, ['NumericValue', 'Ordinal']], //like 5th\n [/[0-9]\\+$/, ['Cardinal', 'NumericValue']], //10+\n [/^[0-9]+(st|nd|rd|th)$/, 'Ordinal'], //like 5th\n [/^[0-9\\.]+([a-z]{1,4})$/, 'Value'], //like 5tbsp\n]\n","const regex = require('./data/startsWith')\n\nconst romanNumeral = /^[IVXLCDM]{2,}$/\nconst romanNumValid = /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/ // https://stackoverflow.com/a/267405/168877\n\n//try each of the ^regexes in our list\nconst checkRegex = function(term, world) {\n let str = term.text\n // do them all!\n for (let r = 0; r < regex.length; r += 1) {\n if (regex[r][0].test(str) === true) {\n term.tagSafe(regex[r][1], 'regex #' + r, world)\n break\n }\n }\n // do some more!\n //roman numberals - XVII\n if (term.text.length >= 2 && romanNumeral.test(str) && romanNumValid.test(str)) {\n term.tag('RomanNumeral', 'xvii', world)\n }\n}\nmodule.exports = checkRegex\n","//regex suffix patterns and their most common parts of speech,\n//built using wordnet, by spencer kelly.\n//this mapping shrinks-down the uglified build\nconst Adj = 'Adjective'\nconst Inf = 'Infinitive'\nconst Pres = 'PresentTense'\nconst Sing = 'Singular'\nconst Past = 'PastTense'\nconst Adverb = 'Adverb'\nconst Exp = 'Expression'\nconst Actor = 'Actor'\nconst Verb = 'Verb'\nconst Noun = 'Noun'\nconst Last = 'LastName'\n//the order here matters.\n\n//regexes indexed by mandated last-character\nmodule.exports = {\n a: [\n [/.[aeiou]na$/, Noun],\n [/.[oau][wvl]ska$/, Last], //polish (female)\n [/.[^aeiou]ica$/, Sing],\n [/^([hyj]a)+$/, Exp], //hahah\n ],\n c: [[/.[^aeiou]ic$/, Adj]],\n d: [\n [/.[ia]sed$/, Adj],\n [/.[gt]led$/, Adj],\n [/.[td]ed$/, Past],\n [/.[aeiou]red$/, Past],\n [/.[^aeiou]led$/, Past], //rumbled\n [/[^aeiou]ard$/, Sing],\n [/[aeiou][^aeiou]id$/, Adj],\n [/[aeiou]c?ked$/, Past], //hooked\n [/[^aeiou][aeiou][tvx]ed$/, Past], //boxed\n [/.[vrl]id$/, Adj],\n ],\n e: [\n [/.[lnr]ize$/, Inf],\n [/.[^aeiou]ise$/, Inf],\n [/.[aeiou]te$/, Inf],\n [/.[^aeiou][ai]ble$/, Adj],\n [/.[^aeiou]eable$/, Adj],\n [/.[ts]ive$/, Adj],\n ],\n h: [\n [/.[^aeiouf]ish$/, Adj],\n [/.v[iy]ch$/, Last], //east-europe\n [/^ug?h+$/, Exp], //uhh\n [/^uh[ -]?oh$/, Exp], //uhoh\n ],\n i: [\n [/.[oau][wvl]ski$/, Last], //polish (male)\n ],\n k: [\n [/^(k)+$/, Exp], //kkkk\n ],\n l: [\n [/.[gl]ial$/, Adj],\n [/.[^aeiou]ful$/, Adj],\n [/.[nrtumcd]al$/, Adj],\n [/.[^aeiou][ei]al$/, Adj],\n ],\n m: [\n [/.[^aeiou]ium$/, Sing],\n [/[^aeiou]ism$/, Sing],\n [/^h*u*m+$/, Exp], //mmmmmmm / ummmm / huuuuuummmmmm\n [/^\\d+ ?[ap]m$/, 'Date'],\n ],\n n: [\n [/.[lsrnpb]ian$/, Adj],\n [/[^aeiou]ician$/, Actor],\n ],\n o: [\n [/^no+$/, Exp], //noooo\n [/^(yo)+$/, Exp], //yoyo\n [/^woo+[pt]?$/, Exp], //woo\n ],\n r: [\n [/.[bdfklmst]ler$/, 'Noun'],\n [/.[ilk]er$/, 'Comparative'],\n [/[aeiou][pns]er$/, Sing],\n [/[^i]fer$/, Inf],\n [/.[^aeiou][ao]pher$/, Actor],\n ],\n t: [\n [/.[di]est$/, 'Superlative'],\n [/.[icldtgrv]ent$/, Adj],\n [/[aeiou].*ist$/, Adj],\n [/^[a-z]et$/, Verb],\n ],\n s: [\n [/.[rln]ates$/, Pres],\n [/.[^z]ens$/, Verb],\n [/.[lstrn]us$/, Sing],\n [/[aeiou][^aeiou]is$/, Sing],\n [/[a-z]\\'s$/, Noun],\n [/^yes+$/, Exp], //yessss\n ],\n v: [\n [/.[^aeiou][ai][kln]ov$/, Last], //east-europe\n ],\n y: [\n [/.[cts]hy$/, Adj],\n [/.[st]ty$/, Adj],\n [/.[gk]y$/, Adj],\n [/.[tnl]ary$/, Adj],\n [/.[oe]ry$/, Sing],\n [/[rdntkbhs]ly$/, Adverb],\n [/...lly$/, Adverb],\n [/[bszmp]{2}y$/, Adj],\n [/.(gg|bb|zz)ly$/, Adj],\n [/.[aeiou]my$/, Adj],\n [/[ea]{2}zy$/, Adj],\n [/.[^aeiou]ity$/, Sing],\n ],\n}\n","//just a foolish lookup of known suffixes\nconst Adj = 'Adjective'\nconst Inf = 'Infinitive'\nconst Pres = 'PresentTense'\nconst Sing = 'Singular'\nconst Past = 'PastTense'\nconst Avb = 'Adverb'\nconst Plrl = 'Plural'\nconst Actor = 'Actor'\nconst Vb = 'Verb'\nconst Noun = 'Noun'\nconst Last = 'LastName'\nconst Modal = 'Modal'\n\n// find any issues - https://observablehq.com/@spencermountain/suffix-word-lookup\nmodule.exports = [\n null, //0\n null, //1\n {\n //2-letter\n ea: Sing,\n ia: Noun,\n ic: Adj,\n ly: Avb,\n \"'n\": Vb,\n \"'t\": Vb,\n },\n {\n //3-letter\n que: Adj,\n lar: Adj,\n ffy: Adj,\n nny: Adj,\n rmy: Adj,\n azy: Adj,\n oid: Adj,\n mum: Adj,\n ous: Adj,\n end: Vb,\n sis: Sing,\n rol: Sing,\n ize: Inf,\n ify: Inf,\n zes: Pres,\n nes: Pres,\n ing: 'Gerund', //likely to be converted to Adj after lexicon pass\n ' so': Avb,\n \"'ll\": Modal,\n \"'re\": 'Copula',\n },\n {\n //4-letter\n teen: 'Value',\n tors: Noun,\n amed: Past,\n ched: Past,\n ends: Vb,\n oses: Pres,\n fies: Pres,\n ects: Pres,\n nded: Past,\n cede: Inf,\n tage: Inf,\n gate: Inf,\n vice: Sing,\n tion: Sing,\n cted: Past,\n ette: Sing,\n some: Adj,\n llen: Adj,\n ried: Adj,\n gone: Adj,\n made: Adj,\n fore: Avb,\n less: Avb,\n ices: Plrl,\n ions: Plrl,\n ints: Plrl,\n aped: Past,\n lked: Past,\n ould: Modal,\n tive: Actor,\n sson: Last, //swedish male\n czyk: Last, //polish (male)\n chuk: Last, //east-europe\n enko: Last, //east-europe\n akis: Last, //greek\n nsen: Last, //norway\n },\n {\n //5-letter\n fully: Avb,\n where: Avb,\n wards: Avb,\n urned: Past,\n tized: Past,\n eased: Past,\n ances: Plrl,\n tures: Plrl,\n ports: Plrl,\n ettes: Plrl,\n ities: Plrl,\n rough: Adj,\n ology: Noun,\n bound: Adj,\n tieth: 'Ordinal',\n ishes: Pres,\n tches: Pres,\n nssen: Last, //norway\n marek: Last, //polish (male)\n },\n {\n //6-letter\n keeper: Actor,\n logist: Actor,\n auskas: Last, //lithuania\n teenth: 'Value',\n },\n {\n //7-letter\n sdottir: Last, //swedish female\n opoulos: Last, //greek\n },\n]\n","const endsWith = require('./data/endsWith')\nconst suffixMap = require('./data/suffixMap')\n\nconst endRegexs = function(term, world) {\n let str = term.clean\n let char = str[str.length - 1]\n if (endsWith.hasOwnProperty(char) === true) {\n let regs = endsWith[char]\n for (let r = 0; r < regs.length; r += 1) {\n if (regs[r][0].test(str) === true) {\n term.tagSafe(regs[r][1], `endReg ${char} #${r}`, world)\n break\n }\n }\n }\n}\n\n//sweep-through all suffixes\nconst knownSuffixes = function(term, world) {\n const len = term.clean.length\n let max = 7\n if (len <= max) {\n max = len - 1\n }\n for (let i = max; i > 1; i -= 1) {\n let str = term.clean.substr(len - i, len)\n if (suffixMap[str.length].hasOwnProperty(str) === true) {\n let tag = suffixMap[str.length][str]\n term.tagSafe(tag, 'suffix -' + str, world)\n break\n }\n }\n}\n\n//all-the-way-down!\nconst checkRegex = function(term, world) {\n knownSuffixes(term, world)\n endRegexs(term, world)\n}\nmodule.exports = checkRegex\n","//just some of the most common emoticons\n//faster than\n//http://stackoverflow.com/questions/28077049/regex-matching-emoticons\nmodule.exports = {\n ':(': true,\n ':)': true,\n ':P': true,\n ':p': true,\n ':O': true,\n ':3': true,\n ':|': true,\n ':/': true,\n ':\\\\': true,\n ':$': true,\n ':*': true,\n ':@': true,\n ':-(': true,\n ':-)': true,\n ':-P': true,\n ':-p': true,\n ':-O': true,\n ':-3': true,\n ':-|': true,\n ':-/': true,\n ':-\\\\': true,\n ':-$': true,\n ':-*': true,\n ':-@': true,\n ':^(': true,\n ':^)': true,\n ':^P': true,\n ':^p': true,\n ':^O': true,\n ':^3': true,\n ':^|': true,\n ':^/': true,\n ':^\\\\': true,\n ':^$': true,\n ':^*': true,\n ':^@': true,\n '):': true,\n '(:': true,\n '$:': true,\n '*:': true,\n ')-:': true,\n '(-:': true,\n '$-:': true,\n '*-:': true,\n ')^:': true,\n '(^:': true,\n '$^:': true,\n '*^:': true,\n '<3': true,\n ' {\n if (raw.charAt(0) === ':') {\n //end comma can be last or second-last ':haircut_tone3:‍♀️'\n if (raw.match(/:.?$/) === null) {\n return false\n }\n //ensure no spaces\n if (raw.match(' ')) {\n return false\n }\n //reasonably sized\n if (raw.length > 35) {\n return false\n }\n return true\n }\n return false\n}\n\n//check against emoticon whitelist\nconst isEmoticon = str => {\n str = str.replace(/^[:;]/, ':') //normalize the 'eyes'\n return emoticon.hasOwnProperty(str)\n}\n\nconst tagEmoji = (term, world) => {\n let raw = term.pre + term.text + term.post\n raw = raw.trim()\n //test for :keyword: emojis\n if (isCommaEmoji(raw) === true) {\n term.tag('Emoji', 'comma-emoji', world)\n term.text = raw\n term.pre = term.pre.replace(':', '')\n term.post = term.post.replace(':', '')\n }\n //test for unicode emojis\n if (term.text.match(emojiReg)) {\n term.tag('Emoji', 'unicode-emoji', world)\n term.text = raw\n }\n //test for emoticon ':)' emojis\n if (isEmoticon(raw) === true) {\n term.tag('Emoticon', 'emoticon-emoji', world)\n term.text = raw\n }\n}\n\nmodule.exports = tagEmoji\n","const steps = {\n lexicon: require('./01-lexicon'),\n punctuation: require('./02-punctuation'),\n regex: require('./03-prefixes'),\n suffix: require('./04-suffixes'),\n emoji: require('./05-emoji'),\n}\n\n//'lookups' look at a term by itself\nconst lookups = function(doc) {\n let terms = doc.termList()\n let world = doc.world\n //our list of known-words\n steps.lexicon(terms, world)\n\n //try these other methods\n for (let i = 0; i < terms.length; i += 1) {\n let term = terms[i]\n //or maybe some helpful punctuation\n steps.punctuation(terms, i, world)\n //mostly prefix checks\n steps.regex(term, world)\n //maybe we can guess\n steps.suffix(term, world)\n //emoji and emoticons\n steps.emoji(term, world)\n }\n return doc\n}\nmodule.exports = lookups\n","//markov-like stats about co-occurance, for hints about unknown terms\n//basically, a little-bit better than the noun-fallback\n//just top n-grams from nlp tags, generated from nlp-corpus\n\n//after this word, here's what happens usually\nlet afterThisWord = {\n i: 'Verb', //44% //i walk..\n first: 'Noun', //50% //first principles..\n it: 'Verb', //33%\n there: 'Verb', //35%\n not: 'Verb', //33%\n because: 'Noun', //31%\n if: 'Noun', //32%\n but: 'Noun', //26%\n who: 'Verb', //40%\n this: 'Noun', //37%\n his: 'Noun', //48%\n when: 'Noun', //33%\n you: 'Verb', //35%\n very: 'Adjective', // 39%\n old: 'Noun', //51%\n never: 'Verb', //42%\n before: 'Noun', //28%\n}\n\n//in advance of this word, this is what happens usually\nlet beforeThisWord = {\n there: 'Verb', //23% // be there\n me: 'Verb', //31% //see me\n man: 'Adjective', // 80% //quiet man\n only: 'Verb', //27% //sees only\n him: 'Verb', //32% //show him\n were: 'Noun', //48% //we were\n took: 'Noun', //38% //he took\n himself: 'Verb', //31% //see himself\n went: 'Noun', //43% //he went\n who: 'Noun', //47% //person who\n jr: 'Person',\n}\n\n//following this POS, this is likely\nlet afterThisPOS = {\n Adjective: 'Noun', //36% //blue dress\n Possessive: 'Noun', //41% //his song\n Determiner: 'Noun', //47%\n Adverb: 'Verb', //20%\n Pronoun: 'Verb', //40%\n Value: 'Noun', //47%\n Ordinal: 'Noun', //53%\n Modal: 'Verb', //35%\n Superlative: 'Noun', //43%\n Demonym: 'Noun', //38%\n Honorific: 'Person', //\n}\n\n//in advance of this POS, this is likely\nlet beforeThisPOS = {\n Copula: 'Noun', //44% //spencer is\n PastTense: 'Noun', //33% //spencer walked\n Conjunction: 'Noun', //36%\n Modal: 'Noun', //38%\n Pluperfect: 'Noun', //40%\n PerfectTense: 'Verb', //32%\n}\nmodule.exports = {\n beforeThisWord: beforeThisWord,\n afterThisWord: afterThisWord,\n\n beforeThisPos: beforeThisPOS,\n afterThisPos: afterThisPOS,\n}\n","const markov = require('./data/markov')\nconst afterKeys = Object.keys(markov.afterThisPos)\nconst beforeKeys = Object.keys(markov.beforeThisPos)\n\nconst checkNeighbours = function(terms, world) {\n for (let i = 0; i < terms.length; i += 1) {\n let term = terms[i]\n //do we still need a tag?\n if (term.isKnown() === true) {\n continue\n }\n //ok, this term needs a tag.\n //look at previous word for clues..\n let lastTerm = terms[i - 1]\n if (lastTerm) {\n // 'foobar term'\n if (markov.afterThisWord.hasOwnProperty(lastTerm.clean) === true) {\n let tag = markov.afterThisWord[lastTerm.clean]\n term.tag(tag, 'after-' + lastTerm.clean, world)\n continue\n }\n // 'Tag term'\n // (look at previous POS tags for clues..)\n let foundTag = afterKeys.find(tag => lastTerm.tags[tag])\n if (foundTag !== undefined) {\n let tag = markov.afterThisPos[foundTag]\n term.tag(tag, 'after-' + foundTag, world)\n continue\n }\n }\n\n //look at next word for clues..\n let nextTerm = terms[i + 1]\n if (nextTerm) {\n // 'term foobar'\n if (markov.beforeThisWord.hasOwnProperty(nextTerm.clean) === true) {\n let tag = markov.beforeThisWord[nextTerm.clean]\n term.tag(tag, 'before-' + nextTerm.clean, world)\n continue\n }\n // 'term Tag'\n // (look at next POS tags for clues..)\n let foundTag = beforeKeys.find(tag => nextTerm.tags[tag])\n if (foundTag !== undefined) {\n let tag = markov.beforeThisPos[foundTag]\n term.tag(tag, 'before-' + foundTag, world)\n continue\n }\n }\n }\n}\nmodule.exports = checkNeighbours\n","const titleCase = /^[A-Z][a-z'\\u00C0-\\u00FF]/\nconst hasNumber = /[0-9]/\n\n/** look for any grammar signals based on capital/lowercase */\nconst checkCase = function(terms, world) {\n terms.forEach((term, i) => {\n //is it a titlecased word?\n if (titleCase.test(term.text) === true && hasNumber.test(term.text) === false) {\n // tag it as titlecase, if possible\n if (i !== 0) {\n term.tag('TitleCase', 'case', world)\n } else if (term.tags.Person || term.tags.Organization || term.tags.Place) {\n term.tag('TitleCase', 'case-person', world)\n }\n // can we call it a noun?\n if (i !== 0) {\n //sure!\n term.tag('ProperNoun', 'case-noun', world)\n }\n }\n })\n}\nmodule.exports = checkCase\n","const hasPrefix = /^(re|un)-?[a-z\\u00C0-\\u00FF]/\nconst prefix = /^(re|un)-?/\n\n/** check 'rewatch' in lexicon as 'watch' */\nconst checkPrefix = function(terms, world) {\n let lex = world.words\n terms.forEach(term => {\n // skip if we have a good tag already\n if (term.isKnown() === true) {\n return\n }\n //does it start with 'un|re'\n if (hasPrefix.test(term.clean) === true) {\n // look for the root word in the lexicon:\n let stem = term.clean.replace(prefix, '')\n if (stem && stem.length > 3 && lex[stem] !== undefined && lex.hasOwnProperty(stem) === true) {\n term.tag(lex[stem], 'stem-' + stem, world)\n }\n }\n })\n}\nmodule.exports = checkPrefix\n","//similar to plural/singularize rules, but not the same\nconst isPlural = [\n /(^v)ies$/i,\n /ises$/i,\n /ives$/i,\n /(antenn|formul|nebul|vertebr|vit)ae$/i,\n /(octop|vir|radi|nucle|fung|cact|stimul)i$/i,\n /(buffal|tomat|tornad)oes$/i,\n /(analy|ba|diagno|parenthe|progno|synop|the)ses$/i,\n /(vert|ind|cort)ices$/i,\n /(matr|append)ices$/i,\n /(x|ch|ss|sh|s|z|o)es$/i,\n /is$/i,\n /men$/i,\n /news$/i,\n /.tia$/i,\n /(^f)ves$/i,\n /(lr)ves$/i,\n /(^aeiouy|qu)ies$/i,\n /(m|l)ice$/i,\n /(cris|ax|test)es$/i,\n /(alias|status)es$/i,\n /ics$/i,\n]\n\n//similar to plural/singularize rules, but not the same\nconst isSingular = [\n /(ax|test)is$/i,\n /(octop|vir|radi|nucle|fung|cact|stimul)us$/i,\n /(octop|vir)i$/i,\n /(rl)f$/i,\n /(alias|status)$/i,\n /(bu)s$/i,\n /(al|ad|at|er|et|ed|ad)o$/i,\n /(ti)um$/i,\n /(ti)a$/i,\n /sis$/i,\n /(?:(^f)fe|(lr)f)$/i,\n /hive$/i,\n /s[aeiou]+ns$/i, // sans, siens\n /(^aeiouy|qu)y$/i,\n /(x|ch|ss|sh|z)$/i,\n /(matr|vert|ind|cort)(ix|ex)$/i,\n /(m|l)ouse$/i,\n /(m|l)ice$/i,\n /(antenn|formul|nebul|vertebr|vit)a$/i,\n /.sis$/i,\n /^(?!talis|.*hu)(.*)man$/i,\n]\nmodule.exports = {\n isSingular: isSingular,\n isPlural: isPlural,\n}\n","//these tags don't have plurals\nconst noPlurals = ['Uncountable', 'Pronoun', 'Place', 'Value', 'Person', 'Month', 'WeekDay', 'Holiday']\nconst rules = require('./data/isPlural')\nconst notPlural = [/ss$/, /sis$/, /[^aeiou][uo]s$/, /'s$/]\nconst notSingular = [/i$/, /ae$/]\n\n/** turn nouns into singular/plural */\nconst checkPlural = function(t, world) {\n if (t.tags.Noun && !t.tags.Acronym) {\n let str = t.clean\n //skip existing tags, fast\n if (t.tags.Singular || t.tags.Plural) {\n return\n }\n //too short\n if (str.length <= 3) {\n t.tag('Singular', 'short-singular', world)\n return\n }\n //is it impossible to be plural?\n if (noPlurals.find(tag => t.tags[tag])) {\n return\n }\n // isPlural suffix rules\n if (rules.isPlural.find(reg => reg.test(str))) {\n t.tag('Plural', 'plural-rules', world)\n return\n }\n // isSingular suffix rules\n if (rules.isSingular.find(reg => reg.test(str))) {\n t.tag('Singular', 'singular-rules', world)\n return\n }\n\n // finally, fallback 'looks plural' rules..\n if (/s$/.test(str) === true) {\n //avoid anything too sketchy to be plural\n if (notPlural.find(reg => reg.test(str))) {\n return\n }\n t.tag('Plural', 'plural-fallback', world)\n return\n }\n //avoid anything too sketchy to be singular\n if (notSingular.find(reg => reg.test(str))) {\n return\n }\n t.tag('Singular', 'singular-fallback', world)\n }\n}\nmodule.exports = checkPlural\n","//nouns that also signal the title of an unknown organization\n//todo remove/normalize plural forms\nconst orgWords = [\n 'academy',\n 'administration',\n 'agence',\n 'agences',\n 'agencies',\n 'agency',\n 'airlines',\n 'airways',\n 'army',\n 'assoc',\n 'associates',\n 'association',\n 'assurance',\n 'authority',\n 'autorite',\n 'aviation',\n 'bank',\n 'banque',\n 'board',\n 'boys',\n 'brands',\n 'brewery',\n 'brotherhood',\n 'brothers',\n 'building society',\n 'bureau',\n 'cafe',\n 'caisse',\n 'capital',\n 'care',\n 'cathedral',\n 'center',\n 'central bank',\n 'centre',\n 'chemicals',\n 'choir',\n 'chronicle',\n 'church',\n 'circus',\n 'clinic',\n 'clinique',\n 'club',\n 'co',\n 'coalition',\n 'coffee',\n 'collective',\n 'college',\n 'commission',\n 'committee',\n 'communications',\n 'community',\n 'company',\n 'comprehensive',\n 'computers',\n 'confederation',\n 'conference',\n 'conseil',\n 'consulting',\n 'containers',\n 'corporation',\n 'corps',\n 'corp',\n 'council',\n 'crew',\n 'daily news',\n 'data',\n 'departement',\n 'department',\n 'department store',\n 'departments',\n 'design',\n 'development',\n 'directorate',\n 'division',\n 'drilling',\n 'education',\n 'eglise',\n 'electric',\n 'electricity',\n 'energy',\n 'ensemble',\n 'enterprise',\n 'enterprises',\n 'entertainment',\n 'estate',\n 'etat',\n 'evening news',\n 'faculty',\n 'federation',\n 'financial',\n 'fm',\n 'foundation',\n 'fund',\n 'gas',\n 'gazette',\n 'girls',\n 'government',\n 'group',\n 'guild',\n 'health authority',\n 'herald',\n 'holdings',\n 'hospital',\n 'hotel',\n 'hotels',\n 'inc',\n 'industries',\n 'institut',\n 'institute',\n 'institute of technology',\n 'institutes',\n 'insurance',\n 'international',\n 'interstate',\n 'investment',\n 'investments',\n 'investors',\n 'journal',\n 'laboratory',\n 'labs',\n // 'law',\n 'liberation army',\n 'limited',\n 'local authority',\n 'local health authority',\n 'machines',\n 'magazine',\n 'management',\n 'marine',\n 'marketing',\n 'markets',\n 'media',\n 'memorial',\n 'mercantile exchange',\n 'ministere',\n 'ministry',\n 'military',\n 'mobile',\n 'motor',\n 'motors',\n 'musee',\n 'museum',\n // 'network',\n 'news',\n 'news service',\n 'observatory',\n 'office',\n 'oil',\n 'optical',\n 'orchestra',\n 'organization',\n 'partners',\n 'partnership',\n // 'party',\n \"people's party\",\n 'petrol',\n 'petroleum',\n 'pharmacare',\n 'pharmaceutical',\n 'pharmaceuticals',\n 'pizza',\n 'plc',\n 'police',\n 'polytechnic',\n 'post',\n 'power',\n 'press',\n 'productions',\n 'quartet',\n 'radio',\n 'regional authority',\n 'regional health authority',\n 'reserve',\n 'resources',\n 'restaurant',\n 'restaurants',\n 'savings',\n 'school',\n 'securities',\n 'service',\n 'services',\n 'social club',\n 'societe',\n 'society',\n 'sons',\n 'standard',\n 'state police',\n 'state university',\n 'stock exchange',\n 'subcommittee',\n 'syndicat',\n 'systems',\n 'telecommunications',\n 'telegraph',\n 'television',\n 'times',\n 'tribunal',\n 'tv',\n 'union',\n 'university',\n 'utilities',\n 'workers',\n]\n\nmodule.exports = orgWords.reduce(function(h, str) {\n h[str] = 'Noun'\n return h\n}, {})\n","let orgWords = require('./data/organizations')\n\n//could this word be an organization\nconst maybeOrg = function(t) {\n //must be a noun\n if (!t.tags.Noun) {\n return false\n }\n //can't be these things\n if (t.tags.Pronoun || t.tags.Comma || t.tags.Possessive) {\n return false\n }\n //must be one of these\n if (t.tags.Organization || t.tags.Acronym || t.tags.Place || t.titleCase()) {\n return true\n }\n return false\n}\n\nconst tagOrgs = function(terms, world) {\n for (let i = 0; i < terms.length; i += 1) {\n let t = terms[i]\n if (orgWords[t.clean] !== undefined && orgWords.hasOwnProperty(t.clean) === true) {\n // look-backward - eg. 'Toronto University'\n let lastTerm = terms[i - 1]\n if (lastTerm !== undefined && maybeOrg(lastTerm) === true) {\n lastTerm.tagSafe('Organization', 'org-word-1', world)\n t.tagSafe('Organization', 'org-word-2', world)\n continue\n }\n //look-forward - eg. University of Toronto\n let nextTerm = terms[i + 1]\n if (nextTerm !== undefined && nextTerm.clean === 'of') {\n if (terms[i + 2] && maybeOrg(terms[i + 2])) {\n t.tagSafe('Organization', 'org-of-word-1', world)\n nextTerm.tagSafe('Organization', 'org-of-word-2', world)\n terms[i + 2].tagSafe('Organization', 'org-of-word-3', world)\n continue\n }\n }\n }\n }\n}\nmodule.exports = tagOrgs\n","const step = {\n neighbours: require('./01-neighbours'),\n case: require('./02-case'),\n stem: require('./03-stem'),\n plural: require('./04-plurals'),\n organizations: require('./05-organizations'),\n}\n//\nconst fallbacks = function(doc) {\n let terms = doc.termList()\n let world = doc.world\n\n // if it's empty, consult it's neighbours, first\n step.neighbours(terms, world)\n\n // is there a case-sensitive clue?\n step.case(terms, world)\n\n // check 'rewatch' as 'watch'\n step.stem(terms, world)\n\n // ... fallback to a noun!\n terms.forEach(t => {\n if (t.isKnown() === false) {\n t.tag('Noun', 'noun-fallback', doc.world)\n }\n })\n\n // turn 'Foo University' into an Org\n step.organizations(terms, world)\n\n //are the nouns singular or plural?\n terms.forEach(t => {\n step.plural(t, doc.world)\n })\n\n return doc\n}\nmodule.exports = fallbacks\n","const hasNegative = /n't$/\n\nconst irregulars = {\n \"won't\": ['will', 'not'],\n wont: ['will', 'not'],\n \"can't\": ['can', 'not'],\n cant: ['can', 'not'],\n cannot: ['can', 'not'],\n \"shan't\": ['should', 'not'],\n dont: ['do', 'not'],\n dun: ['do', 'not'],\n // \"ain't\" is ambiguous for is/was\n}\n\nconst checkNegative = function(term) {\n //check named-ones\n if (irregulars.hasOwnProperty(term.clean) === true) {\n return irregulars[term.clean]\n }\n //try it normally\n if (hasNegative.test(term.clean) === true) {\n let main = term.clean.replace(hasNegative, '')\n return [main, 'not']\n }\n return null\n}\nmodule.exports = checkNegative\n","const contraction = /([a-z\\u00C0-\\u00FF]+)'([a-z]{1,2})$/i\n\n//these ones don't seem to be ambiguous\nconst easy = {\n ll: 'will',\n ve: 'have',\n re: 'are',\n m: 'am',\n \"n't\": 'not',\n}\n//\nconst checkApostrophe = function(term) {\n let parts = term.text.match(contraction)\n if (parts === null) {\n return null\n }\n if (easy.hasOwnProperty(parts[2])) {\n return [parts[1], easy[parts[2]]]\n }\n return null\n}\nmodule.exports = checkApostrophe\n","const irregulars = {\n wanna: ['want', 'to'],\n gonna: ['going', 'to'],\n im: ['i', 'am'],\n alot: ['a', 'lot'],\n ive: ['i', 'have'],\n imma: ['I', 'will'],\n\n \"where'd\": ['where', 'did'],\n whered: ['where', 'did'],\n \"when'd\": ['when', 'did'],\n whend: ['when', 'did'],\n \"how'd\": ['how', 'did'],\n howd: ['how', 'did'],\n \"what'd\": ['what', 'did'],\n whatd: ['what', 'did'],\n // \"let's\": ['let', 'us'], //too weird\n\n //multiple word contractions\n dunno: ['do', 'not', 'know'],\n brb: ['be', 'right', 'back'],\n gtg: ['got', 'to', 'go'],\n irl: ['in', 'real', 'life'],\n tbh: ['to', 'be', 'honest'],\n imo: ['in', 'my', 'opinion'],\n til: ['today', 'i', 'learned'],\n rn: ['right', 'now'],\n twas: ['it', 'was'],\n '@': ['at'],\n}\n\n// either 'is not' or 'are not'\nconst doAint = function(term, phrase) {\n let terms = phrase.terms()\n let index = terms.indexOf(term)\n let before = terms.slice(0, index)\n //look for the preceding noun\n let noun = before.find(t => {\n return t.tags.Noun\n })\n if (noun && noun.tags.Plural) {\n return ['are', 'not']\n }\n return ['is', 'not']\n}\n\n//\nconst checkIrregulars = function(term, phrase) {\n //this word needs it's own logic:\n if (term.clean === `ain't` || term.clean === 'aint') {\n return doAint(term, phrase)\n }\n //check white-list\n if (irregulars.hasOwnProperty(term.clean)) {\n return irregulars[term.clean]\n }\n return null\n}\nmodule.exports = checkIrregulars\n","const hasApostropheS = /([a-z\\u00C0-\\u00FF]+)'s$/i\n\nconst blacklist = {\n that: true,\n there: true,\n}\nconst isPossessive = (term, pool) => {\n // if we already know it\n if (term.tags.Possessive) {\n return true\n }\n //a pronoun can't be possessive - \"he's house\"\n if (term.tags.Pronoun || term.tags.QuestionWord) {\n return false\n }\n if (blacklist.hasOwnProperty(term.clean)) {\n return false\n }\n //if end of sentence, it is possessive - \"was spencer's\"\n let nextTerm = pool.get(term.next)\n if (!nextTerm) {\n return true\n }\n //a gerund suggests 'is walking'\n if (nextTerm.tags.Verb) {\n //fix 'jamie's bite'\n if (nextTerm.tags.Infinitive) {\n return true\n }\n return false\n }\n\n //spencer's house\n if (nextTerm.tags.Noun) {\n return true\n }\n //rocket's red glare\n let twoTerm = pool.get(nextTerm.next)\n if (twoTerm && twoTerm.tags.Noun && !twoTerm.tags.Pronoun) {\n return true\n }\n //othwerwise, an adjective suggests 'is good'\n if (nextTerm.tags.Adjective || nextTerm.tags.Adverb || nextTerm.tags.Verb) {\n return false\n }\n return false\n}\n\nconst isHas = (term, phrase) => {\n let terms = phrase.terms()\n let index = terms.indexOf(term)\n let after = terms.slice(index + 1, index + 3)\n //look for a past-tense verb\n return after.find(t => {\n return t.tags.PastTense\n })\n}\n\nconst checkPossessive = function(term, phrase, world) {\n //the rest of 's\n let found = term.text.match(hasApostropheS)\n if (found !== null) {\n //spencer's thing vs spencer-is\n if (isPossessive(term, phrase.pool) === true) {\n term.tag('#Possessive', 'isPossessive', world)\n return null\n }\n //'spencer is'\n if (found !== null) {\n if (isHas(term, phrase)) {\n return [found[1], 'has']\n }\n return [found[1], 'is']\n }\n }\n return null\n}\nmodule.exports = checkPossessive\n","const hasPerfect = /[a-z\\u00C0-\\u00FF]'d$/\n\n/** split `i'd` into 'i had', or 'i would' */\nconst checkPerfect = function(term, phrase) {\n if (hasPerfect.test(term.clean)) {\n let root = term.clean.replace(/'d$/, '')\n //look at the next few words\n let terms = phrase.terms()\n let index = terms.indexOf(term)\n let after = terms.slice(index + 1, index + 4)\n //is it before a past-tense verb? - 'i'd walked'\n for (let i = 0; i < after.length; i++) {\n let t = after[i]\n if (t.tags.Verb) {\n if (t.tags.PastTense) {\n return [root, 'had']\n }\n return [root, 'would']\n }\n }\n //otherwise, 'i'd walk'\n return [root, 'would']\n }\n return null\n}\nmodule.exports = checkPerfect\n","const isRange = /^([0-9]+)[-–—]([0-9]+)$/i\n\n//split '2-4' into '2 to 4'\nconst checkRange = function(term) {\n if (term.tags.PhoneNumber === true) {\n return null\n }\n let parts = term.text.match(isRange)\n if (parts !== null) {\n return [parts[1], 'to', parts[2]]\n }\n return null\n}\nmodule.exports = checkRange\n","const checkLexicon = require('../01-init/01-lexicon')\nconst tokenize = require('../../01-tokenizer')\nconst checkNegative = require('./01-negative')\nconst checkApostrophe = require('./02-simple')\nconst checkIrregulars = require('./03-irregulars')\nconst checkPossessive = require('./04-possessive')\nconst checkPerfect = require('./05-perfectTense')\nconst checkRange = require('./06-ranges')\nconst isNumber = /^[0-9]+$/\n\nconst createPhrase = function(found, doc) {\n //create phrase from ['would', 'not']\n let phrase = tokenize.fromText(found.join(' '), doc.world, doc.pool())[0]\n //tag it\n let terms = phrase.terms()\n checkLexicon(terms, doc.world)\n //make these terms implicit\n terms.forEach(t => {\n t.implicit = t.text\n t.text = ''\n t.clean = ''\n // remove whitespace for implicit terms\n t.pre = ''\n t.post = ''\n // tag number-ranges\n if (isNumber.test(t.implicit)) {\n t.tags.Number = true\n t.tags.Cardinal = true\n }\n })\n return phrase\n}\n\nconst contractions = function(doc) {\n let world = doc.world\n doc.list.forEach(p => {\n let terms = p.terms()\n for (let i = 0; i < terms.length; i += 1) {\n let term = terms[i]\n let found = checkNegative(term)\n found = found || checkApostrophe(term)\n found = found || checkIrregulars(term, p)\n found = found || checkPossessive(term, p, world)\n found = found || checkPerfect(term, p)\n found = found || checkRange(term, p)\n //add them in\n if (found !== null) {\n let newPhrase = createPhrase(found, doc)\n //set text as contraction\n let firstTerm = newPhrase.terms(0)\n firstTerm.text = term.text\n //grab sub-phrase to remove\n let match = p.buildFrom(term.id, 1, doc.pool())\n match.replace(newPhrase, doc, true)\n }\n }\n })\n return doc\n}\nmodule.exports = contractions\n","//mostly pos-corections here\nconst miscCorrection = function(doc) {\n //misc:\n //foot/feet\n doc.match('(foot|feet)').tag('Noun', 'foot-noun')\n // blood, sweat, and tears\n doc.match('(#Noun && @hasComma) #Noun (and|or) [#PresentTense]').tag('#Noun', 'noun-list')\n //3 feet\n doc.match('#Value [(foot|feet)]').tag('Unit', 'foot-unit')\n //'u' as pronoun\n doc.match('#Conjunction [u]').tag('Pronoun', 'u-pronoun-2')\n //6 am\n doc.match('#Holiday (day|eve)').tag('Holiday', 'holiday-day')\n // the captain who\n doc.match('#Noun [(who|whom)]').tag('Determiner', 'captain-who')\n //timezones\n doc.match('(standard|daylight|summer|eastern|pacific|central|mountain) standard? time').tag('Time', 'timezone')\n //Brazilian pesos\n doc.match('#Demonym #Currency').tag('Currency', 'demonym-currency')\n //about to go\n doc.match('[about to] #Adverb? #Verb').tag(['Auxiliary', 'Verb'], 'about-to')\n //right of way\n doc.match('(right|rights) of .').tag('Noun', 'right-of')\n // a bit\n doc.match('[much] #Adjective').tag('Adverb', 'bit-1')\n doc.match('a [bit]').tag('Noun', 'bit-2')\n doc.match('a bit much').tag('Determiner Adverb Adjective', 'bit-3')\n doc.match('too much').tag('Adverb Adjective', 'bit-4')\n // u r cool\n doc.match('u r').tag('Pronoun #Copula', 'u r')\n // well, ...\n doc.match('^(well|so|okay)').tag('Expression', 'well-')\n\n // some conditional statements\n let m = doc.clauses()\n\n // had he survived,\n m.match('^had #Noun+ #PastTense')\n .firstTerm()\n .tag('Condition', 'had-he')\n // were he to survive\n m.match('^were #Noun+ to #Infinitive')\n .firstTerm()\n .tag('Condition', 'were-he')\n\n //swear-words as non-expression POS\n //nsfw\n doc.match('holy (shit|fuck|hell)').tag('Expression', 'swears-expression')\n doc.match('#Determiner [(shit|damn|hell)]').tag('Noun', 'swears-noun')\n doc.match('[(shit|damn|fuck)] (#Determiner|#Possessive|them)').tag('Verb', 'swears-verb')\n doc\n .match('#Copula fucked up?')\n .not('#Copula')\n .tag('Adjective', 'swears-adjective')\n\n //ambig prepositions/conjunctions\n let so = doc.if('so')\n if (so.found === true) {\n //so funny\n so.match('[so] #Adjective').tag('Adverb', 'so-adv')\n //so the\n so.match('[so] #Noun').tag('Conjunction', 'so-conj')\n //do so\n so.match('do [so]').tag('Noun', 'so-noun')\n }\n\n let all = doc.if('all')\n if (all.found === true) {\n //all students\n all.match('[all] #Determiner? #Noun').tag('Adjective', 'all-noun')\n //it all fell apart\n all.match('[all] #Verb').tag('Adverb', 'all-verb')\n }\n\n //the ambiguous word 'that' and 'which'\n let which = doc.if('which')\n if (which.found === true) {\n //remind john that\n which.match('#Verb #Adverb? #Noun [(that|which)]').tag('Preposition', 'that-prep')\n //that car goes\n which.match('that #Noun [#Verb]').tag('Determiner', 'that-determiner')\n //work, which has been done.\n which.match('@hasComma [which] (#Pronoun|#Verb)').tag('Preposition', 'which-copula')\n }\n\n //like\n let like = doc.if('like')\n if (like.found === true) {\n like.match('just [like]').tag('Preposition', 'like-preposition')\n //folks like her\n like.match('#Noun [like] #Noun').tag('Preposition', 'noun-like')\n //look like\n like.match('#Verb [like]').tag('Adverb', 'verb-like')\n //exactly like\n like\n .match('#Adverb like')\n .notIf('(really|generally|typically|usually|sometimes|often) [like]')\n .tag('Adverb', 'adverb-like')\n }\n\n let title = doc.if('@titleCase')\n if (title.found === true) {\n //FitBit Inc\n title.match('@titleCase (ltd|co|inc|dept|assn|bros)').tag('Organization', 'org-abbrv')\n //Foo District\n title\n .match('@titleCase+ (district|region|province|county|prefecture|municipality|territory|burough|reservation)')\n .tag('Region', 'foo-district')\n //District of Foo\n title\n .match('(district|region|province|municipality|territory|burough|state) of @titleCase')\n .tag('Region', 'district-of-Foo')\n }\n\n let hyph = doc.if('@hasHyphen')\n if (hyph.found === true) {\n //air-flow\n hyph\n .match('@hasHyphen .')\n .match('#Noun #Verb')\n .tag('Noun', 'hyphen-verb')\n //connect hyphenated expressions - 'ooh-wee'\n hyph\n .if('#Expression')\n .match('@hasHyphen+')\n .tag('Expression', 'ooh-wee')\n }\n\n let place = doc.if('#Place')\n if (place.found === true) {\n //West Norforlk\n place.match('(west|north|south|east|western|northern|southern|eastern)+ #Place').tag('Region', 'west-norfolk')\n //some us-state acronyms (exlude: al, in, la, mo, hi, me, md, ok..)\n place\n .match('#City [#Acronym]')\n .match('(al|ak|az|ar|ca|ct|dc|fl|ga|id|il|nv|nh|nj|ny|oh|or|pa|sc|tn|tx|ut|vt|pr)')\n .tag('Region', 'us-state')\n }\n\n return doc\n}\n\nmodule.exports = miscCorrection\n","//Determiner-signals\nconst fixThe = function(doc) {\n let det = doc.if('#Determiner')\n\n if (det.found === true) {\n let adj = det.if('#Adjective')\n if (adj.found) {\n //the nice swim\n adj.match('(the|this|those|these) #Adjective [#Verb]').tag('Noun', 'the-adj-verb')\n // the truly nice swim\n adj.match('(the|this|those|these) #Adverb #Adjective [#Verb]').tag('Noun', 'correction-determiner4')\n //the orange is\n adj.match('#Determiner [#Adjective] (#Copula|#PastTense|#Auxiliary)').tag('Noun', 'the-adj-2')\n //the orange.\n adj\n .match('#Determiner #Adjective$')\n .notIf('(#Comparative|#Superlative)')\n .terms(1)\n .tag('Noun', 'the-adj-1')\n }\n\n let inf = det.if('#Infinitive')\n if (inf.found) {\n // a stream runs\n inf.match('(the|this|a|an) [#Infinitive] #Adverb? #Verb').tag('Noun', 'correction-determiner5')\n //the test string\n inf.match('#Determiner [#Infinitive] #Noun').tag('Noun', 'correction-determiner7')\n //by a bear.\n inf.match('#Determiner [#Infinitive]$').tag('Noun', 'a-inf')\n }\n\n //the wait to vote\n det.match('(the|this) [#Verb] #Preposition .').tag('Noun', 'correction-determiner1')\n //a sense of\n det.match('#Determiner [#Verb] of').tag('Noun', 'the-verb-of')\n //the threat of force\n det.match('#Determiner #Noun of [#Verb]').tag('Noun', 'noun-of-noun')\n //a close\n det.match('#Determiner #Adverb? [close]').tag('Adjective', 'a-close')\n //the western line\n det.match('#Determiner [(western|eastern|northern|southern|central)] #Noun').tag('Noun', 'western-line')\n //the swim\n det.match('(the|those|these) [(#Infinitive|#PresentTense|#PastTense)]').tag('Noun', 'correction-determiner2')\n }\n\n let an = doc.if('(a|an)')\n if (an.found === true) {\n //a staggering cost\n an.match('(a|an) [#Gerund]').tag('Adjective', 'correction-a|an')\n //did a 900, paid a 20\n an.match('#Verb (a|an) [#Value]').tag('Singular', 'a-value')\n //a tv show\n an.match('(a|an) #Noun [#Infinitive]').tag('Noun', 'a-noun-inf')\n //a great run\n an.match('(a|an) #Adjective (#Infinitive|#PresentTense)')\n .terms(2)\n .tag('Noun', 'correction-a|an2')\n //'a/an' can mean 1 - \"a hour\"\n an.match('[(a|an)] (#Duration|hundred|thousand|million|billion|trillion)')\n .ifNo('#Plural')\n .tag('Value', 'a-is-one')\n }\n\n return doc\n}\nmodule.exports = fixThe\n","//\nconst fixNouns = function(doc) {\n let noun = doc.if('#Noun')\n if (noun.found === true) {\n //'more' is not always an adverb\n noun.match('more #Noun').tag('Noun', 'more-noun')\n //he quickly foo\n noun.match('#Noun #Adverb [#Noun]').tag('Verb', 'quickly-foo')\n //fix for busted-up phrasalVerbs\n noun.match('#Noun [#Particle]').tag('Preposition', 'repair-noPhrasal')\n //John & Joe's\n noun.match('#Noun (&|n) #Noun').tag('Organization', 'Noun-&-Noun')\n //Aircraft designer\n noun.match('#Noun #Actor').tag('Actor', 'thing-doer')\n //j.k Rowling\n doc.match('#Noun van der? #Noun').tagSafe('#Person', 'von der noun')\n //king of spain\n doc.match('(king|queen|prince|saint|lady) of? #Noun').tagSafe('#Person', 'king-of-noun')\n // addresses\n doc.match('#Value #Noun (st|street|rd|road|crescent|cr|way|tr|terrace|avenue|ave)').tag('Address')\n // schools\n doc.match('#Noun+ (public|private) school').tag('School')\n //the word 'second'\n noun\n .match('[second] #Noun')\n .notIf('#Honorific')\n .unTag('Unit')\n .tag('Ordinal', 'second-noun')\n //linear algebra\n noun\n .match('(#Determiner|#Value) [(linear|binary|mobile|lexical|technical|computer|scientific|formal)] #Noun')\n .tag('Noun', 'technical-noun')\n\n //organization\n let org = noun.if('#Organization')\n if (org.found === true) {\n org.match('#Organization of the? @titleCase').tagSafe('Organization', 'org-of-place')\n org.match('#Organization #Country').tag('Organization', 'org-country')\n org.match('(world|global|international|national|#Demonym) #Organization').tag('Organization', 'global-org')\n org\n .match('#TitleCase #Organization')\n .ifNo('@hasComma')\n .tag('Organization', 'titlecase-org')\n }\n\n let plural = noun.if('#Plural')\n if (plural.found === true) {\n //some pressing issues\n plural.match('some [#Verb] #Plural').tag('Noun', 'correction-determiner6')\n\n //this rocks\n noun.match('(this|that) [#Plural]').tag('PresentTense', 'this-verbs')\n }\n }\n\n //acronyms\n let acronym = doc.if('#Acronym')\n if (acronym.found === true) {\n acronym\n .match('the [#Acronym]')\n .notIf('(iou|fomo|yolo|diy|dui|nimby)')\n .tag('Organization', 'the-acronym')\n acronym\n .match('#Acronym')\n .match('#Possessive')\n .tag('Organization', 'possessive-acronym')\n }\n\n //possessives\n let poss = doc.if('#Possessive')\n if (poss.found === true) {\n //my buddy\n poss.match('#Possessive [#FirstName]').unTag('Person', 'possessive-name')\n //spencer kelly's\n poss\n .match('#FirstName #Acronym? #Possessive')\n .ifNo('@hasComma')\n .match('#FirstName #Acronym? #LastName')\n .tag('Possessive')\n //Super Corp's fundraiser\n poss\n .match('#Organization+ #Possessive')\n .ifNo('@hasComma')\n .tag('Possessive')\n //Los Angeles's fundraiser\n poss\n .match('#Place+ #Possessive')\n .ifNo('@hasComma')\n .tag('Possessive')\n //her polling\n poss.match('#Possessive [#Verb]').tag('Noun', 'correction-possessive')\n }\n return doc\n}\nmodule.exports = fixNouns\n","const maybeNoun =\n '(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)'\nconst maybeVerb = '(pat|wade|ollie|will|rob|buck|bob|mark|jack)'\nconst maybeAdj = '(misty|rusty|dusty|rich|randy)'\nconst maybeDate = '(april|june|may|jan|august|eve)'\nconst maybePlace = '(paris|alexandria|houston|kobe|salvador|sydney)'\n\nconst fixPerson = function(doc) {\n // clues from honorifics\n let hon = doc.if('#Honorific')\n if (hon.found === true) {\n //mr Putin\n doc.match('(mr|mrs|ms|dr) (#TitleCase|#Possessive)+').tag('#Person', 'mr-putin')\n //mr X\n hon.match('#Honorific #Acronym').tag('Person', 'Honorific-TitleCase')\n //remove single 'mr'\n hon.match('^#Honorific$').unTag('Person', 'single-honorific')\n //first general..\n hon.match('[(1st|2nd|first|second)] #Honorific').tag('Honorific', 'ordinal-honorific')\n }\n\n //methods requiring a titlecase\n let title = doc.if('#TitleCase')\n if (title.found === true) {\n title.match('#Acronym #TitleCase').tagSafe('#Person', 'acronym-titlecase')\n //ludwig van beethovan\n title.match('#TitleCase (van|al|bin) #TitleCase').tagSafe('Person', 'titlecase-van-titlecase')\n //jose de Sucre\n title.match('#TitleCase (de|du) la? #TitleCase').tagSafe('Person', 'titlecase-van-titlecase')\n\n //pope francis\n title\n .match('(lady|queen|sister) #TitleCase')\n .ifNo('#Date')\n .ifNo('#Honorific')\n .tag('#FemaleName', 'lady-titlecase')\n title\n .match('(king|pope|father) #TitleCase')\n .ifNo('#Date')\n .tag('#MaleName', 'poe')\n\n // jean Foobar\n title.match(maybeNoun + ' #Acronym? #TitleCase').tagSafe('Person', 'ray-smith')\n // rob Foobar\n title.match(maybeVerb + ' #Acronym? #TitleCase').tag('Person', 'rob-smith')\n // rusty Foobar\n title.match(maybeAdj + ' #Acronym? #TitleCase').tag('Person', 'rusty-smith')\n // june Foobar\n title.match(maybeDate + ' #Acronym? (#TitleCase && !#Month)').tagSafe('Person', 'june-smith')\n }\n\n let person = doc.if('#Person')\n if (person.found === true) {\n //Frank jr\n person.match('#Person (jr|sr|md)').tag('Person', 'person-honorific')\n //peter II\n person.match('#Person #Person the? #RomanNumeral').tag('Person', 'roman-numeral')\n //'Professor Fink', 'General McCarthy'\n person.match('#Honorific #Person').tag('Person', 'Honorific-Person')\n // 'john E rockefeller'\n person.match('#FirstName [/^[^aiurck]$/]').tag(['Acronym', 'Person'], 'john-e')\n //Doctor john smith jr\n person.match('#Honorific #Person').tag('Person', 'honorific-person')\n //general pearson\n person\n .match('[(private|general|major|corporal|lord|lady|secretary|premier)] #Honorific? #Person')\n .tag('Honorific', 'ambg-honorifics')\n //Morgan Shlkjsfne\n title\n .match('#Person #TitleCase')\n .match('#TitleCase #Noun')\n .tagSafe('Person', 'person-titlecase')\n //a bunch of ambiguous first names\n\n //Nouns: 'viola' or 'sky'\n let ambigNoun = person.if(maybeNoun)\n if (ambigNoun.found === true) {\n // ambigNoun.match('(#Determiner|#Adverb|#Pronoun|#Possessive) [' + maybeNoun + ']').tag('Noun', 'the-ray')\n ambigNoun.match(maybeNoun + ' #Person').tagSafe('Person', 'ray-smith')\n }\n\n //Verbs: 'pat' or 'wade'\n let ambigVerb = person.if(maybeVerb)\n if (ambigVerb === true) {\n ambigVerb.match('(#Modal|#Adverb) [' + maybeVerb + ']').tag('Verb', 'would-mark')\n ambigVerb.match(maybeVerb + ' #Person').tag('Person', 'rob-smith')\n }\n\n //Adjectives: 'rusty' or 'rich'\n let ambigAdj = person.if(maybeAdj)\n if (ambigAdj.found === true) {\n ambigAdj.match('#Adverb [' + maybeAdj + ']').tag('Adjective', 'really-rich')\n ambigAdj.match(maybeAdj + ' #Person').tag('Person', 'randy-smith')\n }\n\n //Dates: 'june' or 'may'\n let ambigDate = person.if(maybeDate)\n if (ambigDate.found === true) {\n ambigDate.match(String(maybeDate) + ' #Person').tagSafe('Person', 'june-smith')\n ambigDate.match('(in|during|on|by|before|#Date) [' + maybeDate + ']').tagSafe('Date', 'in-june')\n ambigDate.match(maybeDate + ' (#Date|#Value)').tagSafe('Date', 'june-5th')\n }\n\n //Places: paris or syndey\n let ambigPlace = person.if(maybePlace)\n if (ambigPlace.found === true) {\n ambigPlace.match('(in|near|at|from|to|#Place) [' + maybePlace + ']').tagSafe('Place', 'in-paris')\n ambigPlace.match('[' + maybePlace + '] #Place').tagSafe('Place', 'paris-france')\n // ambigPlace.match('[' + maybePlace + '] #Person').tagSafe('Person', 'paris-hilton')\n }\n\n //this one is tricky\n let al = person.if('al')\n if (al.found === true) {\n al.match('al (#Person|#TitleCase)').tagSafe('#Person', 'al-borlen')\n al.match('#TitleCase al #TitleCase').tagSafe('#Person', 'arabic-al-arabic')\n }\n\n let firstName = person.if('#FirstName')\n if (firstName.found === true) {\n //ferdinand de almar\n firstName.match('#FirstName de #Noun').tag('#Person', 'firstname-de-noun')\n //Osama bin Laden\n firstName.match('#FirstName (bin|al) #Noun').tag('#Person', 'firstname-al-noun')\n //John L. Foo\n firstName.match('#FirstName #Acronym #TitleCase').tag('Person', 'firstname-acronym-titlecase')\n //Andrew Lloyd Webber\n firstName.match('#FirstName #FirstName #TitleCase').tag('Person', 'firstname-firstname-titlecase')\n //Mr Foo\n firstName.match('#Honorific #FirstName? #TitleCase').tag('Person', 'Honorific-TitleCase')\n //peter the great\n firstName.match('#FirstName the #Adjective').tag('Person', 'determiner5')\n\n //very common-but-ambiguous lastnames\n firstName\n .match('#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)')\n .tag('#Person', 'firstname-maybe')\n\n //John Foo\n firstName\n .match('#FirstName #TitleCase #TitleCase?')\n .match('#Noun+')\n .tag('Person', 'firstname-titlecase')\n //Joe K. Sombrero\n firstName\n .match('#FirstName #Acronym #Noun')\n .ifNo('#Date')\n .tag('#Person', 'n-acro-noun')\n .lastTerm()\n .tag('#LastName', 'n-acro-noun')\n\n // Dwayne 'the rock' Johnson\n firstName\n .match('#FirstName [#Determiner #Noun] #LastName')\n .tag('#NickName', 'first-noun-last')\n .tag('#Person', 'first-noun-last')\n\n //john bodego's\n firstName\n .match('#FirstName (#Singular|#Possessive)')\n .ifNo('(#Date|#Pronoun|#NickName)')\n .tag('#Person', 'first-possessive')\n .lastTerm()\n .tag('#LastName', 'first-possessive')\n\n // Firstname x (dangerous)\n let tmp = firstName\n .match('#FirstName (#Noun|#TitleCase)')\n .ifNo('^#Possessive')\n .ifNo('#ClauseEnd .')\n .ifNo('#Pronoun')\n tmp.lastTerm().tag('#LastName', 'firstname-noun')\n }\n\n let lastName = person.if('#LastName')\n if (lastName.found === true) {\n //is foo Smith\n lastName.match('#Copula [(#Noun|#PresentTense)] #LastName').tag('#FirstName', 'copula-noun-lastname')\n // x Lastname\n lastName\n .match('[#Noun] #LastName')\n .canBe('#FirstName')\n .tag('#FirstName', 'noun-lastname')\n //ambiguous-but-common firstnames\n lastName\n .match(\n '[(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill)] #LastName'\n )\n .tag('#FirstName', 'maybe-lastname')\n //Jani K. Smith\n lastName\n .match('(#TitleCase|#Singular) #Acronym? #LastName')\n .ifNo('#Date')\n .tag('#Person', 'title-acro-noun')\n .lastTerm()\n .tag('#LastName', 'title-acro-noun')\n }\n }\n\n return doc\n}\nmodule.exports = fixPerson\n","const advb = '(#Adverb|not)+?'\n//\nconst fixVerb = function(doc) {\n let vb = doc.if('#Verb')\n if (vb.found) {\n vb.match('[(do|does|will|have|had)] (not|#Adverb)? #Verb').tag('Auxiliary', 'have-had')\n //still make\n vb.match('[still] #Verb').tag('Adverb', 'still-verb')\n //'u' as pronoun\n vb.match('[u] #Verb').tag('Pronoun', 'u-pronoun-1')\n //is no walk\n vb.match('is no [#Verb]').tag('Noun', 'is-no-verb')\n //different views than\n vb.match('[#Verb] than').tag('Noun', 'correction')\n // smoked poutine is\n vb.match('[#PastTense] #Singular is').tag('#Adjective', 'smoked-poutine')\n // baked onions are\n vb.match('[#PastTense] #Plural are').tag('#Adjective', 'baked-onions')\n // goes to sleep\n vb.match('(go|goes|went) to [#Infinitive]').tag('#Noun', 'goes-to-verb')\n\n //there are reasons\n vb.match('there (are|were) #Adjective? [#PresentTense]').tag('Plural', 'there-are')\n //jack seems guarded\n vb.match('#Singular (seems|appears) #Adverb? [#PastTense$]').tag('Adjective', 'seems-filled')\n //fall over\n vb.match('#PhrasalVerb [#PhrasalVerb]').tag('Particle', 'phrasal-particle')\n //went to sleep\n // vb.match('#Verb to #Verb').lastTerm().tag('Noun', 'verb-to-verb');\n //been walking\n vb.match(`(be|been) ${advb} #Gerund`)\n .not('#Verb$')\n .tag('Auxiliary', 'be-walking')\n\n // directive verb - 'use reverse'\n vb.match('(try|use|attempt|build|make) #Verb')\n .ifNo('(@hasComma|#Negative|#Copula|will|be)')\n .lastTerm()\n .tag('#Noun', 'do-verb')\n //infinitive verbs suggest plural nouns - 'XYZ walk to the store'\n // r.match(`#Singular+ #Infinitive`).match('#Singular+').tag('Plural', 'infinitive-make-plural');\n\n let modal = vb.if('(#Modal|did|had|has)')\n if (modal.found === true) {\n //support a splattering of auxillaries before a verb\n modal\n .match(`(has|had) ${advb} #PastTense`)\n .not('#Verb$')\n .tag('Auxiliary', 'had-walked')\n //would walk\n modal\n .match(`(#Modal|did) ${advb} #Verb`)\n .not('#Verb$')\n .tag('Auxiliary', 'modal-verb')\n //would have had\n modal\n .match(`#Modal ${advb} have ${advb} had ${advb} #Verb`)\n .not('#Verb$')\n .tag('Auxiliary', 'would-have')\n //would be walking\n modal\n .match(`#Modal ${advb} be ${advb} #Verb`)\n .not('#Verb$')\n .tag('Auxiliary', 'would-be')\n //would been walking\n modal\n .match(`(#Modal|had|has) ${advb} been ${advb} #Verb`)\n .not('#Verb$')\n .tag('Auxiliary', 'would-be')\n }\n\n let copula = vb.if('#Copula')\n if (copula.found === true) {\n //was walking\n copula\n .match(`#Copula ${advb} #Gerund`)\n .not('#Verb$')\n .tag('Auxiliary', 'copula-walking')\n //is mark hughes\n copula.match('#Copula [#Infinitive] #Noun').tag('Noun', 'is-pres-noun')\n //\n copula.match('[#Infinitive] #Copula').tag('Noun', 'inf-copula')\n //sometimes not-adverbs\n copula.match('#Copula [(just|alone)]$').tag('Adjective', 'not-adverb')\n //jack is guarded\n copula.match('#Singular is #Adverb? [#PastTense$]').tag('Adjective', 'is-filled')\n //is eager to go\n copula.match('#Copula [#Adjective to] #Verb').tag('Verb', 'adj-to')\n\n //sometimes adverbs - 'pretty good','well above'\n copula\n .match('#Copula (pretty|dead|full|well) (#Adjective|#Noun)')\n .ifNo('@hasComma')\n .tag('#Copula #Adverb #Adjective', 'sometimes-adverb')\n }\n\n //Gerund - 'walking'\n let gerund = vb.if('#Gerund')\n if (gerund.found === true) {\n //walking is cool\n gerund.match('[#Gerund] #Adverb? not? #Copula').tag('Activity', 'gerund-copula')\n //walking should be fun\n gerund.match('[#Gerund] #Modal').tag('Activity', 'gerund-modal')\n //running-a-show\n gerund.match('#Gerund #Determiner [#Infinitive]').tag('Noun', 'running-a-show')\n //setting records\n // doc.match('#Gerund [#PresentTense]').tag('Plural', 'setting-records');\n }\n\n //'will be'\n let willBe = vb.if('will #Adverb? not? #Adverb? be')\n if (willBe.found === true) {\n //will be running (not copula\n if (willBe.has('will #Adverb? not? #Adverb? be #Gerund') === false) {\n //tag it all\n willBe.match('will not? be').tag('Copula', 'will-be-copula')\n //for more complex forms, just tag 'be'\n willBe\n .match('will #Adverb? not? #Adverb? be #Adjective')\n .match('be')\n .tag('Copula', 'be-copula')\n }\n }\n }\n\n //question words\n let m = doc.if('(who|what|where|why|how|when)')\n if (m.found) {\n //the word 'how'\n m.match('^how').tag('QuestionWord', 'how-question')\n m.match('[how] (#Determiner|#Copula|#Modal|#PastTense)').tag('QuestionWord', 'how-is')\n // //the word 'which'\n m.match('^which').tag('QuestionWord', 'which-question')\n m.match('[which] . (#Noun)+ #Pronoun').tag('QuestionWord', 'which-question2')\n m.match('which').tag('QuestionWord', 'which-question3')\n\n //how he is driving\n m.match('[#QuestionWord] #Noun #Copula #Adverb? (#Verb|#Adjective)')\n .unTag('QuestionWord')\n .tag('Conjunction', 'how-he-is-x')\n\n //when i go fishing\n m.match('#QuestionWord #Noun #Adverb? #Infinitive not? #Gerund')\n .unTag('QuestionWord')\n .tag('Conjunction', 'when i go fishing')\n }\n\n return doc\n}\nmodule.exports = fixVerb\n","//\nconst fixAdjective = function(doc) {\n let adj = doc.if('#Adjective')\n if (adj.found) {\n //still good\n adj.match('[still] #Adjective').tag('Adverb', 'still-advb')\n //barely even walk\n adj.match('(barely|hardly) even').tag('#Adverb', 'barely-even')\n //big dreams, critical thinking\n adj.match('#Adjective [#PresentTense]').tag('Noun', 'adj-presentTense')\n //will secure our\n adj.match('will [#Adjective]').tag('Verb', 'will-adj')\n //cheering hard - dropped -ly's\n adj.match('#PresentTense [(hard|quick|long|bright|slow)]').tag('Adverb', 'lazy-ly')\n //his fine\n adj.match('(his|her|its) [#Adjective]').tag('Noun', 'his-fine')\n //he left\n adj.match('#Noun #Adverb? [left]').tag('PastTense', 'left-verb')\n //he disguised the thing\n adj.match('#Pronoun [#Adjective] #Determiner #Adjective? #Noun').tag('Verb', 'he-adj-the')\n }\n return doc\n}\nmodule.exports = fixAdjective\n","const units = '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)'\n\n//\nconst fixValue = function(doc) {\n let val = doc.if('#Value')\n if (val.found === true) {\n //1 800 PhoneNumber\n val.match('1 #Value #PhoneNumber').tag('PhoneNumber', '1-800-Value')\n //(454) 232-9873\n val.match('#NumericValue #PhoneNumber').tag('PhoneNumber', '(800) PhoneNumber')\n //three trains\n val.match('#Value [#PresentTense]').tag('Plural', 'value-presentTense')\n //money\n let m = val.match('#Value+ #Currency')\n m.lastTerm().tag('Unit', 'money-unit')\n m.match('#Value+').tag('Money', 'value-currency')\n }\n //5 kg.\n val.match('#Value #Abbreviation').tag('Value', 'value-abbr')\n //seven point five\n val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value')\n //minus 7\n val.match('(minus|negative) #Value').tag('Value', 'minus-value')\n // ten grand\n val.match('#Value grand').tag('Value', 'value-grand')\n //quarter million\n val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal')\n //eg 'trillion'\n let mult = val.if(units)\n if (mult.found === true) {\n mult.match('a #Value').tag('Value', 'a-value') //?\n // mult.match('#Ordinal (half|quarter)').tag('Value', 'ordinal-half');//not ready\n mult.match(`${units} and #Value`).tag('Value', 'magnitude-and-value')\n }\n return doc\n}\nmodule.exports = fixValue\n","const preps = '(in|by|before|during|on|until|after|of|within|all)' //6\nconst people = '(january|april|may|june|summer|autumn|jan|sep)' //ambiguous month-names\nconst verbs = '(may|march)' //ambiguous month-verbs\n\nconst fixDates = function(doc) {\n //ambiguous month - person forms\n let person = doc.if(people)\n if (person.found === true) {\n //give to april\n person.match(`#Infinitive #Determiner? #Adjective? #Noun? (to|for) [${people}]`).tag('Person', 'ambig-person')\n //remind june\n person.match(`#Infinitive [${people}]`).tag('Person', 'infinitive-person')\n //may waits for\n person.match(`[${people}] #PresentTense (to|for)`).tag('Person', 'ambig-active')\n //april will\n person.match(`[${people}] #Modal`).tag('Person', 'ambig-modal')\n //would april\n person.match(`#Modal [${people}]`).tag('Person', 'modal-ambig')\n //with april\n person.match(`(that|with|for) [${people}]`).tag('Person', 'that-month')\n //it is may\n person.match(`#Copula [${people}]`).tag('Person', 'is-may')\n //may is\n person.match(`[${people}] #Copula`).tag('Person', 'may-is')\n //april the 5th\n person.match(`[${people}] the? #Value`).tag('Month', 'person-value')\n //wednesday april\n person.match(`#Date [${people}]`).tag('Month', 'correction-may')\n //may 5th\n person.match(`[${people}] the? #Value`).tag('Month', 'may-5th')\n //5th of may\n person.match(`#Value of [${people}]`).tag('Month', '5th-of-may')\n //by april\n person\n .match(`${preps} [${people}]`)\n .ifNo('#Holiday')\n .tag('Month', 'preps-month')\n //this april\n person.match(`(next|this|last) [${people}]`).tag('Month', 'correction-may') //maybe not 'this'\n }\n\n //ambiguous month - verb-forms\n let verb = doc.if(verbs)\n if (verb.found === true) {\n //quickly march\n verb.match(`#Adverb [${verbs}]`).tag('Infinitive', 'ambig-verb')\n verb.match(`${verbs} [#Adverb]`).tag('Infinitive', 'ambig-verb')\n //all march\n verb.match(`${preps} [${verbs}]`).tag('Month', 'in-month')\n //this march\n verb.match(`(next|this|last) [${verbs}]`).tag('Month', 'this-month')\n //with date\n verb.match(`[${verbs}] the? #Value`).tag('Month', 'march-5th')\n verb.match(`#Value of? [${verbs}]`).tag('Month', '5th-of-march')\n //nearby\n verb.match(`[${verbs}] .? #Date`).tag('Month', 'march-and-feb')\n verb.match(`#Date .? [${verbs}]`).tag('Month', 'feb-and-march')\n\n let march = doc.if('march')\n if (march.found === true) {\n //march to\n march.match('[march] (up|down|back|to|toward)').tag('Infinitive', 'march-to')\n //must march\n march.match('#Modal [march]').tag('Infinitive', 'must-march')\n }\n }\n //sun 5th\n let sun = doc.if('sun')\n if (sun.found === true) {\n //sun feb 2\n sun.match('[sun] #Date').tag('WeekDay', 'sun-feb')\n //sun the 5th\n sun\n .match('sun the #Ordinal')\n .tag('Date')\n .firstTerm()\n .tag('WeekDay', 'sun-the-5th')\n //the sun\n sun.match('#Determiner [sun]').tag('Singular', 'the-sun')\n }\n\n //sat, nov 5th\n let sat = doc.if('sat')\n if (sat.found) {\n //sat november\n sat.match('[sat] #Date').tag('WeekDay', 'sat-feb')\n //this sat\n sat.match(`${preps} [sat]`).tag('WeekDay', 'sat')\n }\n\n //months:\n let month = doc.if('#Month')\n if (month.found === true) {\n //June 5-7th\n month.match(`#Month #DateRange+`).tag('Date', 'correction-numberRange')\n //5th of March\n month.match('#Value of #Month').tag('Date', 'value-of-month')\n //5 March\n month.match('#Cardinal #Month').tag('Date', 'cardinal-month')\n //march 5 to 7\n month.match('#Month #Value to #Value').tag('Date', 'value-to-value')\n //march the 12th\n month.match('#Month the #Value').tag('Date', 'month-the-value')\n }\n\n //months:\n let val = doc.if('#Value')\n if (val.found === true) {\n //values\n val.match('#Value #Abbreviation').tag('Value', 'value-abbr')\n //seven point five\n val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value')\n //minus 7\n val.match('(minus|negative) #Value').tag('Value', 'minus-value')\n // ten grand\n val.match('#Value grand').tag('Value', 'value-grand')\n //quarter million\n val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal')\n //june 7\n val\n .match('(#WeekDay|#Month) #Value')\n .ifNo('#Money')\n .tag('Date', 'date-value')\n\n //7 june\n val\n .match('#Value (#WeekDay|#Month)')\n .ifNo('#Money')\n .tag('Date', 'value-date')\n\n //may twenty five\n val\n .match('#TextValue #TextValue')\n .if('#Date')\n .tag('#Date', 'textvalue-date')\n }\n\n return doc\n}\nmodule.exports = fixDates\n","const fixMisc = require('./fixMisc')\nconst fixDeterminer = require('./fixThe')\nconst fixNouns = require('./fixNouns')\nconst fixPerson = require('./fixPerson')\nconst fixVerb = require('./fixVerb')\nconst fixAdjective = require('./fixAdjective')\nconst fixValue = require('./fixValue')\nconst fixDates = require('./fixDates')\n\n// det: 131.338ms\n// verb: 100.828ms\n// dates: 80.874ms\n// person: 66.054ms\n// nouns: 51.340ms\n// adj: 19.760ms\n// value: 12.950ms\n// misc: 43.359ms\n\n//sequence of match-tag statements to correct mis-tags\nconst corrections = function(doc) {\n // console.time('det')\n fixDeterminer(doc) //27\n // console.timeEnd('det')\n\n // console.time('nouns')\n fixNouns(doc) //30\n // // console.timeEnd('nouns')\n\n // // console.time('person')\n fixPerson(doc) //58\n // // console.timeEnd('person')\n\n // // console.time('verb')\n fixVerb(doc) //50\n // // console.timeEnd('verb')\n\n // // console.time('adj')\n fixAdjective(doc) //8\n // // console.timeEnd('adj')\n\n // // console.time('value')\n fixValue(doc) //12\n // // console.timeEnd('value')\n\n // // console.time('dates')\n fixDates(doc) //92\n // // console.timeEnd('dates')\n\n // // console.time('misc')\n fixMisc(doc) //43\n // console.timeEnd('misc')\n return doc\n}\nmodule.exports = corrections\n","const init = require('./01-init')\nconst fallbacks = require('./02-fallbacks')\nconst contractions = require('./03-contractions')\nconst corrections = require('./04-correction')\n\n/** POS-tag all terms in this document */\nconst tagger = function(doc) {\n let terms = doc.termList()\n // check against any known-words\n doc = init(doc, terms)\n\n // everything has gotta be something. ¯\\_(:/)_/¯\n doc = fallbacks(doc, terms)\n\n // support \"didn't\" & \"spencer's\"\n doc = contractions(doc)\n\n //set our cache, to speed things up\n doc.cache()\n\n // wiggle-around the results, so they make more sense\n doc = corrections(doc)\n\n //remove our cache\n // doc.uncache()\n\n // run any user-given tagger functions\n doc.world.taggers.forEach(fn => {\n fn(doc)\n })\n\n return doc\n}\nmodule.exports = tagger\n","const addMethod = function(Doc) {\n /** */\n class Abbreviations extends Doc {\n stripPeriods() {\n this.termList().forEach(t => {\n if (t.tags.Abbreviation === true && t.next) {\n t.post = t.post.replace(/^\\./, '')\n }\n let str = t.text.replace(/\\./, '')\n t.set(str)\n })\n return this\n }\n addPeriods() {\n this.termList().forEach(t => {\n t.post = t.post.replace(/^\\./, '')\n t.post = '.' + t.post\n })\n return this\n }\n }\n Abbreviations.prototype.unwrap = Abbreviations.prototype.stripPeriods\n\n Doc.prototype.abbreviations = function(n) {\n let match = this.match('#Abbreviation')\n if (typeof n === 'number') {\n match = match.get(n)\n }\n return new Abbreviations(match.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n","const addMethod = function(Doc) {\n /** */\n class Acronyms extends Doc {\n stripPeriods() {\n this.termList().forEach(t => {\n let str = t.text.replace(/\\./g, '')\n t.set(str)\n })\n return this\n }\n addPeriods() {\n this.termList().forEach(t => {\n let str = t.text.replace(/\\./g, '')\n str = str.split('').join('.')\n t.set(str)\n })\n return this\n }\n }\n Acronyms.prototype.unwrap = Acronyms.prototype.stripPeriods\n Acronyms.prototype.strip = Acronyms.prototype.stripPeriods\n\n Doc.prototype.acronyms = function(n) {\n let match = this.match('#Acronym')\n if (typeof n === 'number') {\n match = match.get(n)\n }\n return new Acronyms(match.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n","const addMethod = function(Doc) {\n /** split into approximate sub-sentence phrases */\n Doc.prototype.clauses = function(n) {\n // an awkward way to disambiguate a comma use\n let commas = this.if('@hasComma')\n .notIf('@hasComma @hasComma') //fun, cool...\n .notIf('@hasComma . .? (and|or) .') //cool, and fun\n .notIf('(#City && @hasComma) #Country') //'toronto, canada'\n .notIf('(#Date && @hasComma) #Year') //'july 6, 1992'\n .notIf('@hasComma (too|also)$') //at end of sentence\n .match('@hasComma')\n let found = this.splitAfter(commas)\n\n let quotes = found.quotations()\n found = found.splitOn(quotes)\n\n let parentheses = found.parentheses()\n found = found.splitOn(parentheses)\n\n // it is cool and it is ..\n let conjunctions = found.if('#Copula #Adjective #Conjunction (#Pronoun|#Determiner) #Verb').match('#Conjunction')\n found = found.splitBefore(conjunctions)\n\n // if it is this then that\n let condition = found.if('if .{2,9} then .').match('then')\n found = found.splitBefore(condition)\n\n // misc clause partitions\n found = found.splitBefore('as well as .')\n found = found.splitBefore('such as .')\n found = found.splitBefore('in addition to .')\n\n // semicolons, dashes\n found = found.splitAfter('@hasSemicolon')\n found = found.splitAfter('@hasDash')\n\n // does there appear to have relative/subordinate clause still?\n let tooLong = found.filter(d => d.wordCount() > 5 && d.match('#Verb+').length >= 2)\n if (tooLong.found) {\n let m = tooLong.splitAfter('#Noun .* #Verb .* #Noun+')\n found = found.splitOn(m.eq(0))\n }\n\n if (typeof n === 'number') {\n found = found.get(n)\n }\n return new Doc(found.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n","const addMethod = function(Doc) {\n /** */\n class Contractions extends Doc {\n constructor(list, from, world) {\n super(list, from, world)\n this.contracted = null\n }\n /** turn didn't into 'did not' */\n expand() {\n this.list.forEach(p => {\n let terms = p.terms()\n //change the case?\n let isTitlecase = terms[0].isTitleCase()\n\n terms.forEach((t, i) => {\n //use the implicit text\n // console.log(t.clean)\n t.set(t.implicit || t.text)\n t.implicit = undefined\n\n //add whitespace\n if (i < terms.length - 1 && t.post === '') {\n t.post += ' '\n }\n })\n //set titlecase\n if (isTitlecase) {\n terms[0].toTitleCase()\n }\n })\n return this\n }\n }\n\n //find contractable, expanded-contractions\n // const findExpanded = r => {\n // let remain = r.not('#Contraction')\n // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)')\n // m.concat(remain.match('(they|we|you|i) have'))\n // m.concat(remain.match('i am'))\n // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not'))\n // return m\n // }\n\n Doc.prototype.contractions = function(n) {\n //find currently-contracted\n let found = this.match('@hasContraction+') //(may want to split these up)\n //todo: split consecutive contractions\n if (typeof n === 'number') {\n found = found.get(n)\n }\n return new Contractions(found.list, this, this.world)\n }\n\n //aliases\n Doc.prototype.expanded = Doc.prototype.isExpanded\n Doc.prototype.contracted = Doc.prototype.isContracted\n return Doc\n}\nmodule.exports = addMethod\n","const addMethod = function(Doc) {\n //pull it apart..\n const parse = function(doc) {\n let things = doc.splitAfter('@hasComma').not('(and|or) not?')\n let beforeLast = doc.match('[.] (and|or)')\n return {\n things: things,\n conjunction: doc.match('(and|or) not?'),\n beforeLast: beforeLast,\n hasOxford: beforeLast.has('@hasComma'),\n }\n }\n\n /** cool, fun, and nice */\n class Lists extends Doc {\n /** coordinating conjunction */\n conjunctions() {\n return this.match('(and|or)')\n }\n /** split-up by list object */\n parts() {\n return this.splitAfter('(@hasComma|#Conjunction)')\n }\n /** remove the conjunction */\n items() {\n return this.parts().notIf('#Conjunction')\n }\n /** add a new unit to the list */\n add(str) {\n this.forEach(p => {\n let beforeLast = parse(p).beforeLast\n beforeLast.append(str)\n //add a comma to it\n beforeLast.termList(0).addPunctuation(',')\n })\n return this\n }\n /** remove any matching unit from the list */\n remove() {\n return this\n }\n\n /** return only lists that use a serial comma */\n hasOxfordComma() {\n return this.filter(doc => parse(doc).hasOxford)\n }\n addOxfordComma() {\n return this\n }\n removeOxfordComma() {\n return this\n }\n }\n // aliases\n Lists.prototype.things = Lists.prototype.items\n\n Doc.prototype.lists = function(n) {\n let m = this.if('@hasComma+ .? (and|or) not? .')\n\n // person-list\n let nounList = m.match('(#Noun|#Adjective)+ #Conjunction not? #Adjective? #Noun+')\n let adjList = m.match('(#Adjective|#Adverb)+ #Conjunction not? #Adverb? #Adjective+')\n let verbList = m.match('(#Verb|#Adverb)+ #Conjunction not? #Adverb? #Verb+')\n let result = nounList.concat(adjList)\n result = result.concat(verbList)\n result = result.if('@hasComma')\n\n if (typeof n === 'number') {\n result = m.get(n)\n }\n return new Lists(result.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n","const noPlural =\n '(#Pronoun|#Place|#Value|#Person|#Uncountable|#Month|#WeekDay|#Holiday|#Possessive)'\n\n//certain words can't be plural, like 'peace'\nconst hasPlural = function(doc) {\n if (doc.has('#Plural') === true) {\n return true\n }\n // these can't be plural\n if (doc.has(noPlural) === true) {\n return false\n }\n return true\n}\n\nmodule.exports = hasPlural\n","'use strict'\n\n//chooses an indefinite aricle 'a/an' for a word\nconst irregulars = {\n hour: 'an',\n heir: 'an',\n heirloom: 'an',\n honest: 'an',\n honour: 'an',\n honor: 'an',\n uber: 'an', //german u\n}\n//pronounced letters of acronyms that get a 'an'\nconst an_acronyms = {\n a: true,\n e: true,\n f: true,\n h: true,\n i: true,\n l: true,\n m: true,\n n: true,\n o: true,\n r: true,\n s: true,\n x: true,\n}\n//'a' regexes\nconst a_regexs = [\n /^onc?e/i, //'wu' sound of 'o'\n /^u[bcfhjkqrstn][aeiou]/i, // 'yu' sound for hard 'u'\n /^eul/i,\n]\n\nconst makeArticle = function(doc) {\n //no 'the john smith', but 'a london hotel'\n if (doc.has('#Person') || doc.has('#Place')) {\n return ''\n }\n //no a/an if it's plural\n if (doc.has('#Plural')) {\n return 'the'\n }\n let str = doc.text('normal').trim()\n //explicit irregular forms\n if (irregulars.hasOwnProperty(str)) {\n return irregulars[str]\n }\n //spelled-out acronyms\n let firstLetter = str.substr(0, 1)\n if (doc.has('^@isAcronym') && an_acronyms.hasOwnProperty(firstLetter)) {\n return 'an'\n }\n //'a' regexes\n for (let i = 0; i < a_regexs.length; i++) {\n if (a_regexs[i].test(str)) {\n return 'a'\n }\n }\n //basic vowel-startings\n if (/^[aeiou]/i.test(str)) {\n return 'an'\n }\n return 'a'\n}\n\nmodule.exports = makeArticle\n","//similar to plural/singularize rules, but not the same\nconst isPlural = [\n /(antenn|formul|nebul|vertebr|vit)ae$/i,\n /(octop|vir|radi|nucle|fung|cact|stimul)i$/i,\n /men$/i,\n /.tia$/i,\n /(m|l)ice$/i,\n]\n\n//similar to plural/singularize rules, but not the same\nconst isSingular = [\n /(ax|test)is$/i,\n /(octop|vir|radi|nucle|fung|cact|stimul)us$/i,\n /(octop|vir)i$/i,\n /(rl)f$/i,\n /(alias|status)$/i,\n /(bu)s$/i,\n /(al|ad|at|er|et|ed|ad)o$/i,\n /(ti)um$/i,\n /(ti)a$/i,\n /sis$/i,\n /(?:(^f)fe|(lr)f)$/i,\n /hive$/i,\n /(^aeiouy|qu)y$/i,\n /(x|ch|ss|sh|z)$/i,\n /(matr|vert|ind|cort)(ix|ex)$/i,\n /(m|l)ouse$/i,\n /(m|l)ice$/i,\n /(antenn|formul|nebul|vertebr|vit)a$/i,\n /.sis$/i,\n /^(?!talis|.*hu)(.*)man$/i,\n]\nmodule.exports = {\n isSingular: isSingular,\n isPlural: isPlural,\n}\n","const rules = require('./_rules')\nconst endS = /s$/\n// double-check this term, if it is not plural, or singular.\n// (this is a partial copy of ./tagger/fallbacks/plural)\n// fallback plural if it ends in an 's'.\nconst isPlural = function(str) {\n // isSingular suffix rules\n if (rules.isSingular.find(reg => reg.test(str))) {\n return false\n }\n // does it end in an s?\n if (endS.test(str) === true) {\n return true\n }\n // is it a plural like 'fungi'?\n if (rules.isPlural.find(reg => reg.test(str))) {\n return true\n }\n return null\n}\nmodule.exports = isPlural\n","const exceptions = {\n he: 'his',\n she: 'hers',\n they: 'theirs',\n we: 'ours',\n i: 'mine',\n you: 'yours',\n\n her: 'hers',\n their: 'theirs',\n our: 'ours',\n my: 'mine',\n your: 'yours',\n}\n\n// turn \"David\" to \"David's\"\nconst toPossessive = function(doc) {\n let str = doc.text('text').trim()\n // exceptions\n if (exceptions.hasOwnProperty(str)) {\n doc.replaceWith(exceptions[str], true, true)\n doc.tag('Possessive', 'toPossessive')\n return\n }\n // flanders'\n if (/s$/.test(str)) {\n str += \"'\"\n doc.replaceWith(str, true, true)\n doc.tag('Possessive', 'toPossessive')\n return\n }\n //normal form:\n str += \"'s\"\n doc.replaceWith(str, true, true)\n doc.tag('Possessive', 'toPossessive')\n return\n}\nmodule.exports = toPossessive\n","// .nouns() supports some noun-phrase-ish groupings\n// pull these apart, if necessary\nconst parse = function(doc) {\n let res = {\n main: doc,\n }\n //support 'mayor of chicago' as one noun-phrase\n if (doc.has('#Noun (of|by|for) .')) {\n let m = doc.splitAfter('[#Noun+]')\n res.main = m.eq(0)\n res.post = m.eq(1)\n }\n return res\n}\nmodule.exports = parse\n","const hasPlural = require('./plural/hasPlural')\nconst getArticle = require('./getArticle')\nconst isPlural = require('./plural/isPlural')\nconst toPossessive = require('./toPossessive')\nconst parse = require('./parse')\n\nconst methods = {\n /** overload the original json with noun information */\n json: function(options) {\n let n = null\n if (typeof options === 'number') {\n n = options\n options = null\n }\n options = options || { text: true, normal: true, trim: true, terms: true }\n let res = []\n this.forEach(doc => {\n let json = doc.json(options)[0]\n json.article = getArticle(doc)\n res.push(json)\n })\n if (n !== null) {\n return res[n]\n }\n return res\n },\n\n isPlural: function() {\n return this.if('#Plural') //assume tagger has run?\n },\n hasPlural: function() {\n return this.filter(d => hasPlural(d))\n },\n toPlural: function() {\n let toPlural = this.world.transforms.toPlural\n this.forEach(doc => {\n if (doc.has('#Plural') || hasPlural(doc) === false) {\n return\n }\n // double-check it isn't an un-tagged plural\n let main = parse(doc).main\n let str = main.text()\n if (!main.has('#Singular') && isPlural(str) === true) {\n return\n }\n str = toPlural(str, this.world)\n main.replace(str).tag('#Plural')\n })\n return this\n },\n toSingular: function() {\n let toSingular = this.world.transforms.toSingular\n this.forEach(doc => {\n if (doc.has('#Singular') || hasPlural(doc) === false) {\n return\n }\n // double-check it isn't an un-tagged plural\n let main = parse(doc).main\n let str = main.text()\n if (!main.has('#Plural') && isPlural(str) !== true) {\n return\n }\n str = toSingular(str, this.world)\n main.replace(str).tag('#Singular')\n })\n return this\n },\n toPossessive: function() {\n this.forEach(d => {\n toPossessive(d)\n })\n return this\n },\n}\nmodule.exports = methods\n","const methods = require('./methods')\n\nconst addMethod = function(Doc) {\n /** */\n class Nouns extends Doc {}\n // add-in our methods\n Object.assign(Nouns.prototype, methods)\n\n Doc.prototype.nouns = function(n) {\n let match = this.clauses()\n match = match.match('#Noun+ (of|by)? the? #Noun+?')\n //nouns that we don't want in these results, for weird reasons\n match = match.not('#Pronoun')\n match = match.not('(there|these)')\n match = match.not('(#Month|#WeekDay)') //allow Durations, Holidays\n // //allow possessives like \"spencer's\", but not generic ones like,\n match = match.not('(my|our|your|their|her|his)')\n match = match.not('(of|for|by|the)$')\n\n if (typeof n === 'number') {\n match = match.get(n)\n }\n return new Nouns(match.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n","const open = /\\(/\nconst close = /\\)/\n\nconst addMethod = function(Doc) {\n /** anything between (these things) */\n class Parentheses extends Doc {\n /** remove the parentheses characters */\n unwrap() {\n this.list.forEach(p => {\n let first = p.terms(0)\n first.pre = first.pre.replace(open, '')\n let last = p.lastTerm()\n last.post = last.post.replace(close, '')\n })\n return this\n }\n }\n\n Doc.prototype.parentheses = function(n) {\n let list = []\n this.list.forEach(p => {\n let terms = p.terms()\n //look for opening brackets\n for (let i = 0; i < terms.length; i += 1) {\n const t = terms[i]\n if (open.test(t.pre)) {\n //look for the closing bracket..\n for (let o = i; o < terms.length; o += 1) {\n if (close.test(terms[o].post)) {\n let len = o - i + 1\n list.push(p.buildFrom(t.id, len))\n i = o\n break\n }\n }\n }\n }\n })\n //support nth result\n if (typeof n === 'number') {\n if (list[n]) {\n list = [list[n]]\n } else {\n list = []\n }\n return new Parentheses(list, this, this.world)\n }\n return new Parentheses(list, this, this.world)\n }\n\n return Doc\n}\nmodule.exports = addMethod\n","const addMethod = function(Doc) {\n /** */\n class Possessives extends Doc {\n constructor(list, from, world) {\n super(list, from, world)\n this.contracted = null\n }\n /** turn didn't into 'did not' */\n strip() {\n this.list.forEach(p => {\n let terms = p.terms()\n terms.forEach(t => {\n let str = t.text.replace(/'s$/, '')\n t.set(str || t.text)\n })\n })\n return this\n }\n }\n\n //find contractable, expanded-contractions\n // const findExpanded = r => {\n // let remain = r.not('#Contraction')\n // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)')\n // m.concat(remain.match('(they|we|you|i) have'))\n // m.concat(remain.match('i am'))\n // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not'))\n // return m\n // }\n\n Doc.prototype.possessives = function(n) {\n //find currently-contracted\n let found = this.match('#Noun+? #Possessive')\n //todo: split consecutive contractions\n if (typeof n === 'number') {\n found = found.get(n)\n }\n return new Possessives(found.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n","const pairs = {\n '\\u0022': '\\u0022', // 'StraightDoubleQuotes'\n '\\uFF02': '\\uFF02', // 'StraightDoubleQuotesWide'\n '\\u0027': '\\u0027', // 'StraightSingleQuotes'\n '\\u201C': '\\u201D', // 'CommaDoubleQuotes'\n '\\u2018': '\\u2019', // 'CommaSingleQuotes'\n '\\u201F': '\\u201D', // 'CurlyDoubleQuotesReversed'\n '\\u201B': '\\u2019', // 'CurlySingleQuotesReversed'\n '\\u201E': '\\u201D', // 'LowCurlyDoubleQuotes'\n '\\u2E42': '\\u201D', // 'LowCurlyDoubleQuotesReversed'\n '\\u201A': '\\u2019', // 'LowCurlySingleQuotes'\n '\\u00AB': '\\u00BB', // 'AngleDoubleQuotes'\n '\\u2039': '\\u203A', // 'AngleSingleQuotes'\n // Prime 'non quotation'\n '\\u2035': '\\u2032', // 'PrimeSingleQuotes'\n '\\u2036': '\\u2033', // 'PrimeDoubleQuotes'\n '\\u2037': '\\u2034', // 'PrimeTripleQuotes'\n // Prime 'quotation' variation\n '\\u301D': '\\u301E', // 'PrimeDoubleQuotes'\n '\\u0060': '\\u00B4', // 'PrimeSingleQuotes'\n '\\u301F': '\\u301E', // 'LowPrimeDoubleQuotesReversed'\n}\n\nconst hasOpen = RegExp('(' + Object.keys(pairs).join('|') + ')')\n\nconst addMethod = function(Doc) {\n /** \"these things\" */\n class Quotations extends Doc {\n /** remove the quote characters */\n unwrap() {\n return this\n }\n }\n\n Doc.prototype.quotations = function(n) {\n let list = []\n this.list.forEach(p => {\n let terms = p.terms()\n //look for opening quotes\n for (let i = 0; i < terms.length; i += 1) {\n const t = terms[i]\n if (hasOpen.test(t.pre)) {\n let char = (t.pre.match(hasOpen) || [])[0]\n let want = pairs[char]\n // if (!want) {\n // console.warn('missing quote char ' + char)\n // }\n //look for the closing bracket..\n for (let o = i; o < terms.length; o += 1) {\n if (terms[o].post.indexOf(want) !== -1) {\n let len = o - i + 1\n list.push(p.buildFrom(t.id, len))\n i = o\n break\n }\n }\n }\n }\n })\n //support nth result\n if (typeof n === 'number') {\n if (list[n]) {\n list = [list[n]]\n } else {\n list = []\n }\n return new Quotations(list, this, this.world)\n }\n return new Quotations(list, this, this.world)\n }\n // alias\n Doc.prototype.quotes = Doc.prototype.quotations\n\n return Doc\n}\nmodule.exports = addMethod\n","// walked => walk - turn a verb into it's root form\nconst toInfinitive = function(parsed, world) {\n let verb = parsed.verb\n\n //1. if it's already infinitive\n let str = verb.text('normal')\n if (verb.has('#Infinitive')) {\n return str\n }\n\n // 2. world transform does the heavy-lifting\n let tense = null\n if (verb.has('#PastTense')) {\n tense = 'PastTense'\n } else if (verb.has('#Gerund')) {\n tense = 'Gerund'\n } else if (verb.has('#PresentTense')) {\n tense = 'PresentTense'\n } else if (verb.has('#Participle')) {\n tense = 'Participle'\n } else if (verb.has('#Actor')) {\n tense = 'Actor'\n }\n return world.transforms.toInfinitive(str, world, tense)\n}\nmodule.exports = toInfinitive\n","// spencer walks -> singular\n// we walk -> plural\n\n// the most-recent noun-phrase, before this verb.\nconst findNoun = function(vb) {\n let noun = vb.lookBehind('#Noun+').last()\n return noun\n}\n\n//sometimes you can tell if a verb is plural/singular, just by the verb\n// i am / we were\n// othertimes you need its subject 'we walk' vs 'i walk'\nconst isPlural = function(parsed) {\n let vb = parsed.verb\n if (vb.has('(are|were|does)') || parsed.auxiliary.has('(are|were|does)')) {\n return true\n }\n if (vb.has('(is|am|do|was)') || parsed.auxiliary.has('(is|am|do|was)')) {\n return false\n }\n //consider its prior noun\n let noun = findNoun(vb)\n if (noun.has('(we|they|you)')) {\n return true\n }\n if (noun.has('#Plural')) {\n return true\n }\n if (noun.has('#Singular')) {\n return false\n }\n return null\n}\nmodule.exports = isPlural\n","const toInfinitive = require('./toInfinitive')\nconst isPlural = require('./isPlural')\n// #Modal : would walk -> 'would not walk'\n// #Copula : is -> 'is not'\n// #PastTense : walked -> did not walk\n// #PresentTense : walks -> does not walk\n// #Gerund : walking: -> not walking\n// #Infinitive : walk -> do not walk\n\nconst toNegative = function(parsed, world) {\n let vb = parsed.verb\n // if it's already negative...\n if (parsed.negative.found) {\n return\n }\n\n // would walk -> would not walk\n if (parsed.auxiliary.found) {\n parsed.auxiliary.eq(0).append('not')\n return\n }\n // is walking -> is not walking\n if (vb.has('(#Copula|will|has|had|do)')) {\n vb.append('not')\n return\n }\n // walked -> did not walk\n if (vb.has('#PastTense')) {\n let inf = toInfinitive(parsed, world)\n vb.replaceWith(inf, true, true)\n vb.prepend('did not')\n return\n }\n // walks -> does not walk\n if (vb.has('#PresentTense')) {\n let inf = toInfinitive(parsed, world)\n vb.replaceWith(inf, true, true)\n if (isPlural(parsed, world)) {\n vb.prepend('do not')\n } else {\n vb.prepend('does not')\n }\n return\n }\n //walking -> not walking\n if (vb.has('#Gerund')) {\n let inf = toInfinitive(parsed, world)\n vb.replaceWith(inf, true, true)\n vb.prepend('not')\n return\n }\n\n //fallback 1: walk -> does not walk\n if (isPlural(parsed, world)) {\n vb.prepend('does not')\n return\n }\n //fallback 2: walk -> do not walk\n vb.prepend('do not')\n return\n}\nmodule.exports = toNegative\n","// turn 'would not really walk up' into parts\nconst parseVerb = function(vb) {\n let parsed = {\n adverb: vb.match('#Adverb+'), // 'really'\n negative: vb.match('#Negative'), // 'not'\n auxiliary: vb.match('#Auxiliary').not('(#Negative|#Adverb)'), // 'will' of 'will go'\n particle: vb.match('#Particle'), // 'up' of 'pull up'\n verb: vb.match('#Verb').not('(#Adverb|#Negative|#Auxiliary|#Particle)'),\n }\n // fallback, if no verb found\n if (!parsed.verb.found) {\n // blank-everything\n Object.keys(parsed).forEach(k => {\n parsed[k] = parsed[k].not('.')\n })\n // it's all the verb\n parsed.verb = vb\n return parsed\n }\n //\n if (parsed.adverb && parsed.adverb.found) {\n let match = parsed.adverb.text('reduced') + '$'\n if (vb.has(match)) {\n parsed.adverbAfter = true\n }\n }\n // console.log(parsed.adverb.json({ index: true })[0])\n return parsed\n}\nmodule.exports = parseVerb\n","const isPlural = require('../isPlural')\n\n/** too many special cases for is/was/will be*/\nconst toBe = parsed => {\n let isI = false\n let plural = isPlural(parsed)\n let isNegative = parsed.negative.found\n //account for 'i is' -> 'i am' irregular\n // if (vb.parent && vb.parent.has('i #Adverb? #Copula')) {\n // isI = true;\n // }\n\n // 'i look', not 'i looks'\n if (parsed.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) {\n isI = true\n }\n\n let obj = {\n PastTense: 'was',\n PresentTense: 'is',\n FutureTense: 'will be',\n Infinitive: 'is',\n Gerund: 'being',\n Actor: '',\n PerfectTense: 'been',\n Pluperfect: 'been',\n }\n //\"i is\" -> \"i am\"\n if (isI === true) {\n obj.PresentTense = 'am'\n obj.Infinitive = 'am'\n }\n if (plural) {\n obj.PastTense = 'were'\n obj.PresentTense = 'are'\n obj.Infinitive = 'are'\n }\n if (isNegative) {\n obj.PastTense += ' not'\n obj.PresentTense += ' not'\n obj.FutureTense = 'will not be'\n obj.Infinitive += ' not'\n obj.PerfectTense = 'not ' + obj.PerfectTense\n obj.Pluperfect = 'not ' + obj.Pluperfect\n obj.Gerund = 'not ' + obj.Gerund\n }\n return obj\n}\nmodule.exports = toBe\n","const toInfinitive = require('../toInfinitive')\nconst toBe = require('./toBe')\n\nconst conjugate = function(parsed, world) {\n let verb = parsed.verb\n\n //special handling of 'is', 'will be', etc.\n if (verb.has('#Copula') || (verb.out('normal') === 'be' && parsed.auxiliary.has('will'))) {\n return toBe(parsed, world)\n }\n\n let infinitive = toInfinitive(parsed, world)\n if (!infinitive) {\n return {}\n }\n // console.log(infinitive)\n let forms = world.transforms.conjugate(infinitive, world)\n forms.Infinitive = infinitive\n\n // add particle to phrasal verbs ('fall over')\n if (parsed.particle.found) {\n let particle = parsed.particle.text()\n Object.keys(forms).forEach(k => (forms[k] += ' ' + particle))\n }\n //put the adverb at the end?\n if (parsed.adverb.found) {\n let adverb = parsed.adverb.text()\n if (parsed.adverbAfter === true) {\n Object.keys(forms).forEach(k => (forms[k] += ' ' + adverb))\n } else {\n Object.keys(forms).forEach(k => (forms[k] = adverb + ' ' + forms[k]))\n }\n }\n\n //apply negative\n const isNegative = parsed.negative.found\n if (isNegative) {\n forms.PastTense = 'did not ' + forms.Infinitive\n forms.PresentTense = 'does not ' + forms.Infinitive\n forms.Gerund = 'not ' + forms.Gerund\n }\n //future Tense is pretty straightforward\n if (!forms.FutureTense) {\n if (isNegative) {\n forms.FutureTense = 'will not ' + forms.Infinitive\n } else {\n forms.FutureTense = 'will ' + forms.Infinitive\n }\n }\n if (isNegative) {\n forms.Infinitive = 'not ' + forms.Infinitive\n }\n return forms\n}\nmodule.exports = conjugate\n","const toNegative = require('./toNegative')\nconst parseVerb = require('./parse')\nconst isPlural = require('./isPlural')\nconst conjugate = require('./conjugate')\nconst toInfinitive = require('./toInfinitive')\n\nmodule.exports = {\n /** overload the original json with verb information */\n json: function(options) {\n let n = null\n if (typeof options === 'number') {\n n = options\n options = null\n }\n options = options || { text: true, normal: true, trim: true, terms: true }\n let res = []\n this.forEach(p => {\n let json = p.json(options)[0]\n let parsed = parseVerb(p)\n json.parts = {}\n Object.keys(parsed).forEach(k => {\n json.parts[k] = parsed[k].text('normal')\n })\n json.isNegative = p.has('#Negative')\n json.conjugations = conjugate(parsed, this.world)\n res.push(json)\n })\n if (n !== null) {\n return res[n]\n }\n return res\n },\n\n /** grab the adverbs describing these verbs */\n adverbs: function() {\n let list = []\n // look at internal adverbs\n this.forEach(vb => {\n let advb = parseVerb(vb).adverb\n if (advb.found) {\n list = list.concat(advb.list)\n }\n })\n // look for leading adverbs\n let m = this.lookBehind('#Adverb$')\n if (m.found) {\n list = m.list.concat(list)\n }\n // look for trailing adverbs\n m = this.lookAhead('^#Adverb')\n if (m.found) {\n list = list.concat(m.list)\n }\n return this.buildFrom(list)\n },\n /**return verbs like 'we walk' and not 'spencer walks' */\n isPlural: function() {\n let list = []\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n if (isPlural(parsed, this.world) === true) {\n list.push(vb.list[0])\n }\n })\n return this.buildFrom(list)\n },\n /** return verbs like 'spencer walks' and not 'we walk' */\n isSingular: function() {\n let list = []\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n if (isPlural(parsed, this.world) === false) {\n list.push(vb.list[0])\n }\n })\n return this.buildFrom(list)\n },\n\n /** */\n conjugate: function() {\n let result = []\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n let forms = conjugate(parsed, this.world)\n result.push(forms)\n })\n return result\n },\n /** */\n toPastTense: function() {\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n let str = conjugate(parsed, this.world).PastTense\n if (str) {\n vb.replaceWith(str, false, true)\n // vb.tag('PastTense')\n }\n })\n return this\n },\n /** */\n toPresentTense: function() {\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n let obj = conjugate(parsed, this.world)\n let str = obj.PresentTense\n // 'i look', not 'i looks'\n if (vb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) {\n str = obj.Infinitive\n }\n if (str) {\n vb.replaceWith(str, false, true)\n vb.tag('PresentTense')\n }\n })\n return this\n },\n /** */\n toFutureTense: function() {\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n let str = conjugate(parsed, this.world).FutureTense\n if (str) {\n vb.replaceWith(str, false, true)\n vb.tag('FutureTense')\n }\n })\n return this\n },\n /** */\n toInfinitive: function() {\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n let str = toInfinitive(parsed, this.world)\n if (str) {\n vb.replaceWith(str, false, true)\n vb.tag('Infinitive')\n }\n })\n return this\n },\n /** */\n toGerund: function() {\n this.forEach(vb => {\n let parsed = parseVerb(vb)\n let str = conjugate(parsed, this.world).Gerund\n if (str) {\n vb.replaceWith(str, false, true)\n vb.tag('Gerund')\n }\n })\n return this\n },\n\n /** return only verbs with 'not'*/\n isNegative: function() {\n return this.if('#Negative')\n },\n /** return only verbs without 'not'*/\n isPositive: function() {\n return this.ifNo('#Negative')\n },\n /** add a 'not' to these verbs */\n toNegative: function() {\n this.list.forEach(p => {\n let doc = this.buildFrom([p])\n let parsed = parseVerb(doc)\n toNegative(parsed, doc.world)\n })\n return this\n },\n /** remove 'not' from these verbs */\n toPositive: function() {\n let m = this.match('do not #Verb')\n if (m.found) {\n m.remove('do not')\n }\n return this.remove('#Negative')\n },\n}\n","const methods = require('./methods')\n\nconst addMethod = function(Doc) {\n /** */\n class Verbs extends Doc {}\n // add-in our methods\n Object.assign(Verbs.prototype, methods)\n\n // aliases\n Verbs.prototype.negate = Verbs.prototype.toNegative\n\n Doc.prototype.verbs = function(n) {\n let match = this.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+')\n // try to ignore leading and trailing adverbs\n match = match.not('^#Adverb+')\n match = match.not('#Adverb+$')\n // handle commas:\n // don't split 'really, really'\n let keep = match.match('(#Adverb && @hasComma) #Adverb')\n // // but split the other commas\n let m = match.not(keep).splitAfter('@hasComma')\n // // combine them back together\n m = m.concat(keep)\n m.sort('index')\n\n //handle slashes?\n\n //ensure there's actually a verb\n m = m.if('#Verb')\n\n //grab (n)th result\n if (typeof n === 'number') {\n m = m.get(n)\n }\n let vb = new Verbs(m.list, this, this.world)\n return vb\n }\n return Doc\n}\nmodule.exports = addMethod\n","const addMethod = function(Doc) {\n /** */\n class People extends Doc {\n // honorifics(){}\n // firstNames(){}\n // lastNames(){}\n // pronouns(){}\n // toPronoun(){}\n // fromPronoun(){}\n }\n\n Doc.prototype.people = function(n) {\n let match = this.splitAfter('@hasComma')\n match = match.match('#Person+')\n\n //grab (n)th result\n if (typeof n === 'number') {\n match = match.get(n)\n }\n return new People(match.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n","const subsets = require('./_simple')\nconst subclass = [\n require('./Abbreviations'),\n require('./Acronyms'),\n require('./Clauses'),\n require('./Contractions'),\n require('./Lists'),\n require('./Nouns'),\n require('./Parentheses'),\n require('./Possessives'),\n require('./Quotations'),\n require('./Verbs'),\n require('./People'),\n]\n\nconst extend = function(Doc) {\n // add basic methods\n Object.keys(subsets).forEach(k => (Doc.prototype[k] = subsets[k]))\n // add subclassed methods\n subclass.forEach(addFn => addFn(Doc))\n return Doc\n}\nmodule.exports = extend\n","const methods = {\n misc: require('./methods'),\n selections: require('../Subset/_simple'),\n}\nconst tagger = require('../02-tagger')\nconst tokenize = require('../01-tokenizer')\nconst extend = require('../Subset')\n\n/** a parsed text object */\nclass Doc {\n constructor(list, from, world) {\n this.list = list\n //quiet these properties in console.logs\n Object.defineProperty(this, 'from', {\n enumerable: false,\n value: from,\n writable: true,\n })\n //borrow some missing data from parent\n if (world === undefined && from !== undefined) {\n world = from.world\n }\n //'world' getter\n Object.defineProperty(this, 'world', {\n enumerable: false,\n value: world,\n // writable: true, //todo: add me?\n })\n //fast-scans for our data\n\n //'found' getter\n Object.defineProperty(this, 'found', {\n get: () => this.list.length > 0,\n })\n //'length' getter\n Object.defineProperty(this, 'length', {\n get: () => this.list.length,\n })\n // this is way easier than .constructor.name...\n Object.defineProperty(this, 'isA', {\n get: () => 'Doc',\n })\n }\n\n /** run part-of-speech tagger on all results*/\n tagger() {\n return tagger(this)\n }\n\n /** pool is stored on phrase objects */\n pool() {\n if (this.list.length > 0) {\n return this.list[0].pool\n }\n return this.all().list[0].pool\n }\n}\n\n/** create a new Document object */\nDoc.prototype.buildFrom = function(list) {\n list = list.map(p => p.clone(true))\n // new this.constructor()\n let doc = new Doc(list, this, this.world)\n return doc\n}\n\n/** create a new Document from plaintext. */\nDoc.prototype.fromText = function(str) {\n let list = tokenize.fromText(str, this.world, this.pool())\n return this.buildFrom(list)\n}\n\nObject.assign(Doc.prototype, methods.misc)\nObject.assign(Doc.prototype, methods.selections)\n\n//add sub-classes\nextend(Doc)\n\n//aliases\nconst aliases = {\n untag: 'unTag',\n and: 'match',\n notIf: 'ifNo',\n only: 'if',\n onlyIf: 'if',\n}\nObject.keys(aliases).forEach(k => (Doc.prototype[k] = Doc.prototype[aliases[k]]))\nmodule.exports = Doc\n","const tokenize = require('./01-tokenizer')\nconst version = require('./_version')\nconst World = require('./World/World')\nconst Doc = require('./Doc/Doc')\n\n//blast-out our word-lists, just once\nlet world = new World()\n\n/** parse and tag text into a compromise object */\nconst nlp = function(text = '', lexicon) {\n if (lexicon) {\n world.addWords(lexicon)\n }\n let list = tokenize.fromText(text, world)\n let doc = new Doc(list, null, world)\n doc.tagger()\n return doc\n}\n\n/** parse text into a compromise object, without running POS-tagging */\nnlp.tokenize = function(text = '', lexicon) {\n if (lexicon) {\n world.addWords(lexicon)\n }\n let list = tokenize.fromText(text, world)\n let doc = new Doc(list, null, world)\n return doc\n}\n\n/** mix in a compromise-plugin */\nnlp.extend = function(fn) {\n fn(Doc, world)\n return this\n}\n\n/** make a deep-copy of the library state */\nnlp.clone = function() {\n world = world.clone()\n return this\n}\n\n/** re-generate a Doc object from .json() results */\nnlp.load = function(json) {\n let list = tokenize.fromJSON(json, world)\n return new Doc(list, null, world)\n}\n\n/** log our decision-making for debugging */\nnlp.verbose = function(bool = true) {\n world.verbose(bool)\n return this\n}\n\n/** current version of the library */\nnlp.version = version\n// alias\nnlp.import = nlp.load\n\nmodule.exports = nlp\n"],"names":["chars","split","makeId","str","text","i","Math","floor","random","length","compact","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","unicode","Object","keys","forEach","killUnicode","join","periodAcronym","oneLetterAcronym","noPeriodAcronym","lowerCaseAcronym","isAcronym","test","hasSlash","clean","toLowerCase","trim","original","replace","reduced","startings","endings","hasApostrophe","minusNumber","parseTerm","pre","post","found","after","normalize","parsed","reduce","word","alias","titleCase","upperCase","exports","toUpperCase","isTitleCase","startQuote","endQuote","punct","indexOf","hasPost","hyphen","Boolean","implicit","wrapMatch","doesMatch","reg","index","id","anything","start","end","undefined","hasOwnProperty","soft","root","tag","tags","method","regex","choices","operator","every","some","result","negative","boring","world","transform","transforms","Plural","toSingular","Verb","Negative","Infinitive","tense","PastTense","Gerund","PresentTense","Participle","Actor","toInfinitive","hasSpace","isUpperCase","options","showPre","showPost","before","normal","titlecase","ProperNoun","Acronym","lowercase","acronyms","whitespace","last","punctuation","hasEllipses","abbreviations","Abbreviation","boringTags","Auxiliary","Possessive","rankTags","term","tagSet","sort","lineage","isA","jsonDefault","offset","bestTag","assign","require$$0","require$$1","require$$2","require$$3","require$$4","padEnd","width","toString","reason","log","console","arr","prototype","call","charAt","substr","addTag","tagset","fns","isVerbose","logTag","down","unTag","notA","addTags","isArray","logUntag","untagAll","canBe","enemies","add","Term","String","obj","prev","next","clone","methods","tagMethods","terms","pool","get","error","push","isShallow","buildFrom","newTerms","map","wantId","lastId","filter","trimEnd","isFirst","isLast","isFull","txt","textOut","lastTerm","endOfSentence","combinePost","match","addWhitespace","beforeTerms","newTerm","stitchIn","main","newPhrase","afterId","afterTerm","beforeId","unique","list","appendPhrase","doc","toStretch","hasId","docs","concat","parents","parent","shouldChange","joinPhrase","starterId","shrinkAll","deleteLength","phrase","find","deletePhrase","set","append","prepend","firstLength","tmp","findIndex","slice","res","json","regs","getAfter","all","getBefore","require$$5","failFast","optional","cache","words","getGreedy","until","count","max","min","greedyTo","nextReg","tryHere","captures","hasNeeds","remain","greedy","skipto","startAt","capture","isImplicit","hasMinMax","andSign","stripStart","stripEnd","stripBoth","parseToken","RegExp","Number","byParentheses","byWords","byArray","postProcess","tokens","captureArr","first","reverse","fromDoc","ids","syntax","input","matchAll","matchOne","minLength","matches","tryMatch","notMatch","ts","current","results","previous","can","Phrase","defineProperty","enumerable","writable","value","matchMethods","aliases","Pool","initSplit","hasSomething","hasEllipse","newLine","hasLetter","startWhitespace","naiive_split","lines","isSentence","abbrevs","lastWord","splitSentences","sentences","chunks","splits","ws","wordlike","isBoundary","naiiveSplit","isSlash","notWord","hasHyphen","combineSlashes","splitHyphens","hyphens","splitWords","carry","addLinks","fromText","splitTerms","phrases","parseTags","tagList","numList","parseInt","num","warn","fromJSON","JSON","parse","tagArr","entity","Noun","Singular","Person","FirstName","MaleName","FemaleName","LastName","Honorific","Place","Country","City","Region","Address","Organization","SportsTeam","School","Company","Uncountable","Pronoun","Activity","Unit","Demonym","FutureTense","Copula","Modal","PerfectTense","Pluperfect","PhrasalVerb","Particle","Value","Ordinal","Cardinal","RomanNumeral","TextValue","NumericValue","Money","Percent","Adjective","Comparable","Comparative","Superlative","NumberRange","Adverb","Date","Month","WeekDay","Determiner","Conjunction","Preposition","QuestionWord","Currency","Expression","Url","PhoneNumber","HashTag","AtMention","Emoji","Emoticon","Email","Condition","colorMap","addColors","color","inferIsA","len","inferNotA","key","inferLineage","validate","inferTags","inferColor","addIn","build","nouns","verbs","values","misc","seq","toAlphaCode","fromCharCode","fromAlphaCode","charCodeAt","encoding","symbols","nodes","exec","symCount","syms","indexFromRef","toArray","unpack","unpack_1","unpack_1$1","Array","addWord","lex","addMore","lexicon","hasCompound","plural","toPlural","conj","conjugate","adjectives","addIrregulars","irregulars","inf","forms","g8","vh1","q1","q2","q3","q4","addendum","alga","alumna","alumnus","analysis","antenna","appendix","avocado","axis","bacillus","barracks","beau","bus","cactus","chateau","child","circus","clothes","corpus","criterion","curriculum","database","deer","diagnosis","echo","embargo","epoch","foot","formula","fungus","genus","goose","halo","hippopotamus","larva","leaf","libretto","loaf","man","matrix","memorandum","modulus","mosquito","mouse","move","nebula","nucleus","octopus","opus","ovum","ox","parenthesis","person","phenomenon","prognosis","quiz","radius","referendum","rodeo","sex","shoe","sombrero","stimulus","stomach","syllabus","synopsis","tableau","thesis","thief","tooth","tornado","tuxedo","vertebra","mapping","prt","perf","pst","fut","pres","pluperf","conjugations","act","age","aim","arise","babysit","ban","be","beat","become","begin","being","bend","bet","bind","bite","bleed","blow","boil","brake","breed","bring","broadcast","budget","burn","burst","buy","choose","cling","come","compete","cost","creep","cut","deal","develop","die","dig","dive","draw","dream","drink","drive","drop","eat","edit","egg","fall","feed","feel","fight","flee","fling","fly","forbid","forget","forgive","free","freeze","give","go","grow","hang","have","hear","hide","hit","hold","hurt","ice","imply","is","keep","kneel","know","lay","lead","leap","leave","lend","lie","light","loose","lose","make","mean","meet","miss","pay","prove","puke","put","quit","read","ride","ring","rise","rub","run","say","seat","see","seek","sell","send","sew","shake","shave","shed","shine","shoot","show","shut","sing","sink","sit","ski","slay","sleep","slide","smash","sneak","speak","speed","spend","spill","spin","spit","spread","spring","stand","steal","stick","sting","stink","stream","strew","strike","suit","sware","swear","sweep","swim","swing","take","teach","tear","tell","think","thrive","tie","undergo","understand","upset","wait","wake","wear","weave","weep","win","wind","withdraw","wring","write","final","full","endsWith","repl","pr","pa","gr","ar","posMap","doTransform","pos","checkSuffix","suffixes","hasY","generic","genericFill","do_rules","dont_rules","nice","late","hard","inner","outer","far","worse","bad","good","big","large","to_superlative","grey","gray","green","yellow","red","well","sad","to_comparative","toSuperlative","toComparative","sup","comp","addE","trySuffix","rules","pluralize","invertObj","invert","to","guessVerb","guessTense","three","guess","two","one","irregs","rule","require$$6","World","defaultTags","unpackWords","lexData","getByTag","bool","addLex","inferTagSet","fn","taggers","plurals","irregular","compounds","postProcessors","stringify","w2","from","addParent","doShallow","wordCount","setRoot","eq","parseSyntax","not","has","lookAhead","lookBehind","befores","tagTerms","safe","why","setTag","detachParent","sub","findStart","lookups","tokenize","keepTags","keepCase","uncache","newPhrases","merge","tmpDoc","tagger","oldTags","tagSafe","replaceWith","arguments","arg","toRemove","showFull","trimPre","trimPost","jsonDefaults","termOffsets","elapsed","offsets","termList","frequency","freq","already","reset","cli","blue","magenta","cyan","black","tagString","debug","module","topk","counts","reduceTags","implied","phraseList","allTags","tagMap","alpha","left","right","byFreq","sortSequential","order","alphabetical","wordcount","seqNames","sequence","sequential","chron","chronological","isPunct","quotes","termArr","hasDash","quotations","adverbs","remove","defaults","emoji","contractions","parentheses","possessives","honorifics","medium","heavy","strip","contraction","expand","unwrap","possessive","splitOn","foundEm","parts","splitAfter","splitBefore","segment","eachTerm","toTitleCase","dehyphenate","toQuotations","removed","increase","postPunct","setContraction","suffix","require$$7","require$$8","require$$9","require$$10","require$$11","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","emojis","atmentions","atMentions","phoneNumbers","money","places","organizations","clauses","entities","yup","people","ignore","things","topics","tryMultiple","checkLexicon","foundWords","apostrophes","oneLetterWord","A","checkPunctuation","endChar","romanNumeral","romanNumValid","checkRegex","Adj","Inf","Pres","Sing","Past","Exp","Last","Avb","Plrl","Vb","ea","ia","ic","ly","que","lar","ffy","nny","rmy","azy","oid","mum","ous","sis","rol","ize","ify","zes","nes","ing","teen","tors","amed","ched","ends","oses","fies","ects","nded","cede","tage","gate","vice","tion","cted","ette","llen","ried","gone","made","fore","less","ices","ions","ints","aped","lked","ould","tive","sson","czyk","chuk","enko","akis","nsen","fully","where","wards","urned","tized","eased","ances","tures","ports","ettes","ities","rough","ology","bound","tieth","ishes","tches","nssen","marek","keeper","logist","auskas","teenth","sdottir","opoulos","endRegexs","char","knownSuffixes","suffixMap","emojiReg","isCommaEmoji","raw","isEmoticon","emoticon","tagEmoji","steps","afterThisWord","it","there","because","but","who","his","when","you","very","old","never","beforeThisWord","me","only","him","were","took","himself","went","jr","afterThisPOS","beforeThisPOS","beforeThisPos","afterThisPos","afterKeys","markov","beforeKeys","checkNeighbours","isKnown","foundTag","nextTerm","hasNumber","checkCase","hasPrefix","prefix","checkPrefix","stem","isPlural","isSingular","noPlurals","notPlural","notSingular","checkPlural","orgWords","maybeOrg","Comma","tagOrgs","step","neighbours","fallbacks","hasNegative","wont","cant","cannot","dont","dun","checkNegative","easy","ll","ve","re","checkApostrophe","wanna","gonna","im","alot","ive","imma","whered","whend","howd","whatd","dunno","brb","gtg","irl","tbh","imo","til","rn","twas","doAint","noun","checkIrregulars","hasApostropheS","blacklist","that","isPossessive","twoTerm","isHas","checkPossessive","hasPerfect","checkPerfect","isRange","checkRange","isNumber","createPhrase","firstTerm","miscCorrection","so","which","like","notIf","title","hyph","place","fixThe","det","adj","an","ifNo","fixNouns","org","acronym","poss","maybeNoun","maybeVerb","maybeAdj","maybeDate","maybePlace","fixPerson","hon","ambigNoun","ambigVerb","ambigAdj","ambigDate","ambigPlace","al","firstName","lastName","advb","fixVerb","vb","modal","copula","gerund","willBe","fixAdjective","units","fixValue","val","mult","preps","fixDates","verb","march","sun","sat","month","corrections","fixDeterminer","fixMisc","init","addMethod","Doc","Abbreviations","stripPeriods","Acronyms","commas","conjunctions","condition","tooLong","Contractions","contracted","isTitlecase","expanded","isExpanded","isContracted","beforeLast","conjunction","hasOxford","Lists","addPunctuation","items","lists","nounList","adjList","verbList","noPlural","hasPlural","hour","heir","heirloom","honest","honour","honor","uber","an_acronyms","a_regexs","makeArticle","firstLetter","endS","exceptions","he","she","they","we","her","their","our","my","your","toPossessive","article","getArticle","Nouns","open","close","Parentheses","Possessives","pairs","hasOpen","Quotations","want","findNoun","auxiliary","toNegative","parseVerb","adverb","particle","adverbAfter","toBe","isI","isNegative","out","infinitive","toPastTense","toPresentTense","toFutureTense","toGerund","isPositive","toPositive","Verbs","negate","People","subclass","extend","subsets","addFn","selections","untag","and","onlyIf","nlp","addWords","load","verbose","version"],"mappings":"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"} \ No newline at end of file diff --git a/builds/compromise.min.js b/builds/compromise.min.js index 107c68fd5..9d82e1d06 100644 --- a/builds/compromise.min.js +++ b/builds/compromise.min.js @@ -1,6 +1 @@ -/* compromise v11.14.3 - github.com/nlp-compromise/compromise - MIT -*/ - -!function(t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).nlp=t()}(function(){return function t(e,r,n){function a(o,s){if(!r[o]){if(!e[o]){var u="function"==typeof require&&require;if(!s&&u)return u(o,!0);if(i)return i(o,!0);var l=new Error("Cannot find module '"+o+"'");throw l.code="MODULE_NOT_FOUND",l}var c=r[o]={exports:{}};e[o][0].call(c.exports,function(t){return a(e[o][1][t]||t)},c,c.exports,t,e,r,n)}return r[o].exports}for(var i="function"==typeof require&&require,o=0;o=0;r--,i*=36){let n=t.charCodeAt(r)-48;n>10&&(n-=7),e+=n*i}return e};const i=function(t,e,r){const n=a(e);return n{const r=e.split("¦");return t[r[0]]=r[1],t},{}),r={};return Object.keys(e).forEach(function(t){const n=function(t){const e={nodes:t.split(";"),syms:[],symCount:0};return t.match(":")&&function(t){const e=new RegExp("([0-9A-Z]+):([0-9A-Z]+)");for(let r=0;r{let o=t.nodes[n];"!"===o[0]&&(e.push(a),o=o.slice(1));const s=o.split(/([A-Z0-9,]+)/g);for(let o=0;o (http://spencermounta.in)",name:"compromise",description:"natural language processing in the browser",version:"11.14.3",main:"./builds/compromise.js",unpkg:"./builds/compromise.min.js",types:"types",repository:{type:"git",url:"git://github.com/nlp-compromise/compromise.git"},scripts:{test:'tape "./test/unit/**/*.test.js" | tap-dancer',"test:spec":'tape "./test/unit/**/*.test.js" | tap-spec',testb:'TESTENV=prod tape "./test/unit/**/*.test.js" | tap-dancer',buildTest:"TESTENV=prod node ./scripts/test.js","test:types":"dtslint types",browserTest:"node ./scripts/browserTest.js",benchmark:"node ./scripts/benchmark.js",build:"node ./scripts/build/index.js",pack:"node ./scripts/pack.js",prepublishOnly:"node ./scripts/prepublish && npm run test:types",postpublish:"node ./scripts/postpublish",watch:"amble ./scratch.js",filesize:"node ./scripts/lib/filesize.js",coverage:"node ./scripts/postpublish/coverage.js",lint:"node ./scripts/prepublish/linter.js"},files:["builds/","docs/","types/index.d.ts"],prettier:{trailingComma:"none",tabWidth:2,semi:!0,singleQuote:!0,printWidth:100},dependencies:{"efrt-unpack":"2.2.0"},devDependencies:{"@babel/core":"7.5.5","@babel/preset-env":"7.5.5",amble:"0.0.7",babelify:"10.0.0",babili:"0.1.4",browserify:"16.5.0",chalk:"2.4.2",codecov:"3.5.0","compromise-plugin":"0.0.9",derequire:"2.0.6",dtslint:"0.9.3",nyc:"14.1.1",shelljs:"0.8.3","tap-dancer":"0.2.0",tape:"4.11.0",terser:"4.2.1"},license:"MIT"}},{}],3:[function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var a=t("./tags"),i={reset:"",red:"",green:"",yellow:"",blue:"",magenta:"",cyan:"",black:""};void 0===e&&Object.keys(i).forEach(function(t){i[t]=""}),r.ensureString=function(t){return"string"==typeof t?t:"number"==typeof t?String(t):""},r.ensureObject=function(t){return"object"!==n(t)?{}:null===t||t instanceof Array?{}:t},r.titleCase=function(t){return t.charAt(0).toUpperCase()+t.substr(1)},r.copy=function(t){var e={};return t=r.ensureObject(t),Object.keys(t).forEach(function(r){e[r]=t[r]}),e},r.extend=function(t,e){t=r.copy(t);for(var n=Object.keys(e),a=0;a "+e,a+=n.leftPad(r||"",15),console.log("%c"+a," color: #a2c99c")},untag:function(t,e,r){var a=t.normal||"["+t.silent_term+"]";a=n.leftPad("'"+a+"'",12),a+=" ~* "+e,a+=" "+(r||""),console.log("%c"+a," color: #b66a6a")}}},{"../fns":3}],6:[function(t,e,r){"use strict";var n=t("./client"),a=t("./server"),i=!1;e.exports={enable:function(t){void 0===t&&(t=!0),i=t},tag:function(t,e,r){!0!==i&&"tagger"!==i||("undefined"!=typeof window?n.tag(t,e,r):a.tag(t,e,r))},unTag:function(t,e,r){!0!==i&&"tagger"!==i||("undefined"!=typeof window?n.untag(t,e,r):a.untag(t,e,r))}}},{"./client":5,"./server":7}],7:[function(t,e,r){"use strict";var n=t("../fns");e.exports={tag:function(t,e,r){var a=t.normal||"["+t.silent_term+"]";a=n.yellow(a),a=n.leftPad("'"+a+"'",20),a+=" -> "+n.printTag(e),a=n.leftPad(a,54),console.log(" "+a+"("+n.cyan(r||"")+")")},untag:function(t,e,r){var a="-"+t.normal+"-";a=n.red(a),a=n.leftPad(a,20),a+=" ~* "+n.red(e),a=n.leftPad(a,54),console.log(" "+a+"("+n.red(r||"")+")")}}},{"../fns":3}],8:[function(t,e,r){"use strict";e.exports={fns:t("./fns"),Terms:t("./terms")}},{"./fns":3,"./terms":165}],9:[function(t,e,r){"use strict";var n=t("../../text");e.exports=n.makeSubset({stripPeriods:function(){return this.list.forEach(function(t){t.terms.forEach(function(t){var e=t._text.split(".");e.length>2&&(t.text=e.join(""))})}),this},addPeriods:function(){return this.list.forEach(function(t){t.terms.forEach(function(t){if(t._text.split(".").length>2){var e=t._text.replace(/\./g,"");t.text=e.split("").join(".")+"."}})}),this},data:function(){return this.terms().list.map(function(t){var e=t.terms[0],r=e.text.toUpperCase().replace(/\./g,"").split("");return{periods:r.join("."),normal:r.join(""),text:e.text}})}},function(t,e){return t=t.match("#Acronym"),"number"==typeof e&&(t=t.get(e)),t})},{"../../text":192}],10:[function(t,e,r){"use strict";var n=t("../../text"),a=t("./methods"),i={data:function(){var t=this;return this.list.map(function(e){var r=e.out("normal"),n={normal:r,text:t.out("text"),comparative:"more "+r,superlative:"most "+r,adverbForm:null,nounForm:null};return!0===function(t,e){return!(!t||t.length<=3)&&("Comparable"===e[t]||"Adjective"!==e[t]&&-1===t.indexOf(" "))}(r,t.world().words)&&(n.comparative=a.toComparative(r)||n.comparative,n.superlative=a.toSuperlative(r)||n.superlative,n.adverbForm=a.toAdverb(r),n.nounForm=a.toNoun(r)),n})}};e.exports=n.makeSubset(i,function(t,e){return t=t.match("#Adjective"),"number"==typeof e&&(t=t.get(e)),t})},{"../../text":192,"./methods":11}],11:[function(t,e,r){"use strict";e.exports={toNoun:t("./toNoun"),toSuperlative:t("./toSuperlative"),toComparative:t("./toComparative"),toAdverb:t("./toAdverb"),toVerb:t("./toVerb")}},{"./toAdverb":12,"./toComparative":13,"./toNoun":14,"./toSuperlative":15,"./toVerb":16}],12:[function(t,e,r){"use strict";var n=[/airs$/,/ll$/,/ee.$/,/ile$/,/y$/],a=t("../../../world/more-data/irregularAdjectives").toAdverb,i=[{reg:/al$/i,repl:"ally"},{reg:/ly$/i,repl:"ly"},{reg:/(.{3})y$/i,repl:"$1ily"},{reg:/que$/i,repl:"quely"},{reg:/ue$/i,repl:"uly"},{reg:/ic$/i,repl:"ically"},{reg:/ble$/i,repl:"bly"},{reg:/l$/i,repl:"ly"}];e.exports=function(t){if(!0===a.hasOwnProperty(t))return a[t];for(var e=0;e0)},s=function(t){return!!(t&&t>1e3&&t<3e3)};e.exports=function(t){var e={month:null,date:null,weekday:null,year:null,named:null,time:null},r=t.match("(#Holiday|today|tomorrow|yesterday)");if(r.found&&(e.named=r.out("normal")),(r=t.match("#Month")).found&&(e.month=i.index(r.list[0].terms[0])),(r=t.match("#WeekDay")).found&&(e.weekday=a.index(r.list[0].terms[0])),(r=t.match("#Time")).found&&(e.time=n(t),t.not("#Time")),(r=t.match("#Month #Value #Year")).found){var u=r.values().numbers();o(u[0])&&(e.date=u[0]);var l=parseInt(t.match("#Year").out("normal"),10);s(l)&&(e.year=l)}if(!r.found){if((r=t.match("#Month #Value")).found){var c=r.values().numbers()[0];o(c)&&(e.date=c)}if((r=t.match("#Month #Year")).found){var h=parseInt(t.match("#Year").out("normal"),10);s(h)&&(e.year=h)}}if((r=t.match("#Value of #Month")).found){var m=r.values().numbers()[0];o(m)&&(e.date=m)}return e}},{"./month":27,"./parseTime":29,"./weekday":31}],29:[function(t,e,r){"use strict";var n=/([12]?[0-9]) ?(am|pm)/i,a=/([12]?[0-9]):([0-9][0-9]) ?(am|pm)?/i,i=function(t){return!!(t&&t>0&&t<25)};e.exports=function(t){var e={logic:null,hour:null,minute:null,second:null,timezone:null},r=t.match("(by|before|for|during|at|until|after) #Time").firstTerm();return r.found&&(e.logic=r.out("normal")),t.match("#Time").terms().list.forEach(function(t){var r,o=t.terms[0],s=o.text.match(n);null!==s&&(e.hour=parseInt(s[1],10),"pm"===s[2]&&(e.hour+=12),!1===i(e.hour)&&(e.hour=null)),null!==(s=o.text.match(a))&&(e.hour=parseInt(s[1],10),e.minute=parseInt(s[2],10),(r=e.minute)&&r>0&&r<60||(e.minute=null),"pm"===s[3]&&(e.hour+=12),!1===i(e.hour)&&(e.hour=null))}),e}},{}],30:[function(t,e,r){"use strict";r.longDays={sunday:0,monday:1,tuesday:2,wednesday:3,thursday:4,friday:5,saturday:6},r.shortDays={sun:0,mon:1,tues:2,wed:3,weds:3,thurs:4,fri:5,sat:6}},{}],31:[function(t,e,r){"use strict";var n=t("./data"),a=n.shortDays,i=n.longDays;e.exports={index:function(t){if(t.tags.WeekDay){if(void 0!==i[t.normal])return i[t.normal];if(void 0!==a[t.normal])return a[t.normal]}return null},toShortForm:function(t){if(t.tags.WeekDay&&void 0!==i[t.normal]){var e=Object.keys(a);t.text=e[i[t.normal]]}return t},toLongForm:function(t){if(t.tags.WeekDay&&void 0!==a[t.normal]){var e=Object.keys(i);t.text=e[a[t.normal]]}return t}}},{"./data":30}],32:[function(t,e,r){"use strict";var n=t("./index"),a=t("./getGrams"),i=function(t,e,r){n.call(this,t,e,r)};i.prototype=Object.create(n.prototype),i.find=function(t,e,r){var n={size:[1,2,3,4],edge:"end"};r&&(n.size=[r]);var o=a(t,n);return(t=new i(o)).sort(),"number"==typeof e&&(t=t.get(e)),t},e.exports=i},{"./getGrams":33,"./index":35}],33:[function(t,e,r){"use strict";var n=t("./gram"),a=function(t){return t.terms.filter(function(t){return""!==t._text})};e.exports=function(t,e){(e=e||{}).size=e.size||[1,2,3],"number"==typeof e.size&&(e.size=[e.size]);var r={};return e.size.forEach(function(i){t.list.forEach(function(t){var o,s,u=[];"start"===e.edge?(o=i,u=(s=a(t)).lengthe.count?-1:t.count===e.count&&(t.size>e.size||t.key.length>e.key.length)?-1:1}),t},o={data:function(){return this.list.map(function(t){return{normal:t.out("normal"),count:t.count,size:t.size}})},unigrams:function(){return this.list=this.list.filter(function(t){return 1===t.size}),this},bigrams:function(){return this.list=this.list.filter(function(t){return 2===t.size}),this},trigrams:function(){return this.list=this.list.filter(function(t){return 3===t.size}),this},sort:function(){return i(this)}};e.exports=n.makeSubset(o,function(t,e){var r=[];"number"==typeof e&&(e={n:e});for(var o=(e=e||{}).max||4,s=1;s<=o;s++)r.push(s);e.size&&(r=[e.size]);var u=a(t,{size:r});return t=new n(u),t=i(t),void 0!==e.n&&(t=t.get(e.n)),t})},{"../../text":192,"./getGrams":33}],36:[function(t,e,r){"use strict";var n=t("./index"),a=t("./getGrams"),i=function(t,e,r){n.call(this,t,e,r)};i.prototype=Object.create(n.prototype),i.find=function(t,e,r){var n={size:[1,2,3,4],edge:"start"};r&&(n.size=[r]);var o=a(t,n);return(t=new i(o)).sort(),"number"==typeof e&&(t=t.get(e)),t},e.exports=i},{"./getGrams":33,"./index":35}],37:[function(t,e,r){"use strict";e.exports=function(t){if(!t.tags.Noun)return!1;if(t.tags.Plural)return!0;for(var e=["Pronoun","Place","Value","Person","Month","WeekDay","RelativeDay","Holiday"],r=0;r3}},{"./hasPlural":37,"./methods/data/indicators":41}],40:[function(t,e,r){"use strict";var n={hour:"an",heir:"an",heirloom:"an",honest:"an",honour:"an",honor:"an",uber:"an"},a={a:!0,e:!0,f:!0,h:!0,i:!0,l:!0,m:!0,n:!0,o:!0,r:!0,s:!0,x:!0},i=[/^onc?e/i,/^u[bcfhjkqrstn][aeiou]/i,/^eul/i];e.exports=function(t){var e=t.normal;if(t.tags.Person)return"";if(t.tags.Plural)return"the";if(n.hasOwnProperty(e))return n[e];var r=e.substr(0,1);if(t.isAcronym()&&a.hasOwnProperty(r))return"an";for(var o=0;o1){var i=this.not("(#Acronym|#Honorific)");this.firstName=i.first(),this.lastName=i.last()}return this};i.prototype=Object.create(n.prototype);var o={data:function(){return{text:this.out("text"),normal:this.out("normal"),firstName:this.firstName.out("normal"),middleName:this.middleName.out("normal"),nickName:this.nickName.out("normal"),lastName:this.lastName.out("normal"),genderGuess:this.guessGender(),pronoun:this.pronoun(),honorifics:this.honorifics.out("array")}},guessGender:function(){if(this.honorifics.match("(mr|mister|sr|sir|jr)").found)return"Male";if(this.honorifics.match("(mrs|miss|ms|misses|mme|mlle)").found)return"Female";if(this.firstName.match("#MaleName").found)return"Male";if(this.firstName.match("#FemaleName").found)return"Female";var t=this.firstName.out("normal");return a(t)},pronoun:function(){var t=this.firstName.out("normal"),e=this.guessGender(t);return"Male"===e?"he":"Female"===e?"she":"they"},root:function(){var t=this.firstName.out("root"),e=this.lastName.out("root");return t&&e?t+" "+e:e||t||this.out("root")}};Object.keys(o).forEach(function(t){i.prototype[t]=o[t]}),e.exports=i},{"../../paths":8,"./guessGender":48}],51:[function(t,e,r){"use strict";var n=t("../../text");e.exports=n.makeSubset({strip:function(){return this.list.forEach(function(t){var e=t.terms[t.terms.length-1];e.text=e.text.replace(/'s$/,""),e.unTag("Possessive",".strip()")}),this}},function(t,e){return t=(t=t.match("#Possessive+")).splitAfter("#Comma"),"number"==typeof e&&(t=t.get(e)),t})},{"../../text":192}],52:[function(t,e,r){"use strict";var n=t("../../text"),a=t("./sentence"),i={toPastTense:function(){return this.list=this.list.map(function(t){return t=t.toPastTense(),new a(t.terms,t.world,t.refText,t.refTerms)}),this},toPresentTense:function(){return this.list=this.list.map(function(t){return t=t.toPresentTense(),new a(t.terms,t.world,t.refText,t.refTerms)}),this},toFutureTense:function(){return this.list=this.list.map(function(t){return t=t.toFutureTense(),new a(t.terms,t.world,t.refText,t.refTerms)}),this},toContinuous:function(){return this.list=this.list.map(function(t){return t=t.toContinuous(),new a(t.terms,t.world,t.refText,t.refTerms)}),this},toNegative:function(){return this.list=this.list.map(function(t){return t=t.toNegative(),new a(t.terms,t.world,t.refText,t.refTerms)}),this},toPositive:function(){return this.list=this.list.map(function(t){return t=t.toPositive(),new a(t.terms,t.world,t.refText,t.refTerms)}),this},isPassive:function(){return this.list=this.list.filter(function(t){return t.isPassive()}),this},isQuestion:function(){return this.questions()},prepend:function(t){return this.list=this.list.map(function(e){return e.prepend(t)}),this},append:function(t){return this.list=this.list.map(function(e){return e.append(t)}),this},toExclamation:function(){return this.list.forEach(function(t){t.setPunctuation("!")}),this},toQuestion:function(){return this.list.forEach(function(t){t.setPunctuation("?")}),this},toStatement:function(){return this.list.forEach(function(t){t.setPunctuation(".")}),this}};e.exports=n.makeSubset(i,function(t,e){return t=t.all(),"number"==typeof e&&(t=t.get(e)),t.list=t.list.map(function(t){return new a(t.terms,t.world,t.refText,t.refTerms)}),t})},{"../../text":192,"./sentence":54}],53:[function(t,e,r){"use strict";e.exports=function(t){var e=t.getPunctuation(),r=t.match("*").splitAfter("#Comma");return!(!0!==/\?/.test(e)&&(/\.\.$/.test(t.out("text"))||t.has("^#QuestionWord")&&t.has("#Comma")||!t.has("^#QuestionWord")&&!t.has("^(do|does|did|is|was|can|could|will|would|may) #Noun")&&!t.has("^(have|must) you")&&!r.has("^#QuestionWord")&&!r.has("(do|does|is|was) #Noun+ #Adverb? (#Adjective|#Infinitive)$")))}},{}],54:[function(t,e,r){"use strict";var n=t("../../paths").Terms,a=t("./toNegative"),i=t("./toPositive"),o=t("../verbs/verb"),s=t("./smartInsert"),u=function(t){var e=t.match("#Condition"),r=t.not("#Condition"),n=r.match("#VerbPhrase+").first(),a=n.out("normal"),i=r.match("#Determiner? #Adjective+? #Noun "+a).first().not("#VerbPhrase"),s=r.match(a+" #Preposition? #Determiner? #Noun").first().not("#VerbPhrase");return t.conditions=e,t.subject=i,t.verb=n,t.object=s,t.verb.found&&(t.verb=new o(t.verb.list[0].terms,t.world,t.refText,t.refTerms)),t},l=function(t){t.found&&t.contractions().expand()},c={toSingular:function(){return this.match("#Noun").match("!#Pronoun").firstTerm().things().toSingular(),this},toPlural:function(){return this.match("#Noun").match("!#Pronoun").firstTerm().things().toPlural(),this},mainVerb:function(){return u(this),this.verb.found?this.verb:null},toPastTense:function(){var t=this.mainVerb();if(t){var e=t.out("root");t.toPastTense();var r=this.match("#Contraction "+e);l(r);var n=t.out("root");return this.parentTerms.replace(e,n)}return this},toPresentTense:function(){var t=this.mainVerb();if(t){var e=t.out("normal");if(1==!(!this.subject.found||!this.subject.has("(i|we)")))this.has("(am|will|did) "+e)&&function(t){t.terms=t.terms.filter(function(t){if(t.silent_term){if("am"===t.silent_term||"will"===t.silent_term||"did"===t.silent_term)return!1;t.text=t.silent_term,t.silent_term=null,t.unTag("Contraction"),!0===t.tags.TitleCase&&t.toTitleCase()}return!0})}(this),t.toInfinitive();else{t.toPresentTense();var r=this.match("#Contraction "+e);l(r)}var n=t.out("normal");return this.parentTerms.replace(e,n)}return this},toFutureTense:function(){var t=this.mainVerb();if(t){var e=t.clone();t.toFutureTense();var r=this.match("#Contraction "+e.out("normal"));l(r);var n=t.out("normal");return this.parentTerms.replace(e,n)}return this},toContinuous:function(){var t=this.mainVerb();if(t){var e=t.clone();t.toGerund();var r=this.match("#Contraction "+e.out("normal"));l(r);var n=t.out("normal");return this.parentTerms.replace(e,n)}return this},isNegative:function(){return 1===this.match("#Negative").list.length},toNegative:function(){return this.isNegative()?this:a(this)},toPositive:function(){return this.isNegative()?i(this):this},append:function(t){return s.append(this,t)},prepend:function(t){return s.prepend(this,t)},isPassive:function(){return this.match("was #Adverb? #PastTense #Adverb? by").found}},h=function(t,e,r,a){n.call(this,t,e,r,a),u(this)};h.prototype=Object.create(n.prototype),Object.keys(c).forEach(function(t){h.prototype[t]=c[t]}),e.exports=h},{"../../paths":8,"../verbs/verb":94,"./smartInsert":55,"./toNegative":56,"./toPositive":57}],55:[function(t,e,r){"use strict";var n=/^[A-Z]/;e.exports={append:function(t,e){var r=t.terms[t.terms.length-1],n=t.getPunctuation();n&&r.killPunctuation(),t.insertAt(t.terms.length,e);var a=t.terms[t.terms.length-1];return n&&(a.text+=n),r.whitespace.after&&(a.whitespace.after=r.whitespace.after,r.whitespace.after=""),t},prepend:function(t,e){var r=t.terms[0];return t.insertAt(0,e),n.test(r.text)&&(!1===r.needsTitleCase()&&r.toLowerCase(),t.terms[0].toTitleCase()),t}}},{}],56:[function(t,e,r){"use strict";var n={everyone:"no one",everybody:"nobody",someone:"no one",somebody:"nobody",always:"never"};e.exports=function(t){var e=t.match("(everyone|everybody|someone|somebody|always)").first();if(e.found&&n[e.out("normal")]){var r=e.out("normal");return(t=t.match(r).replaceWith(n[r]).list[0]).parentTerms}var a=t.mainVerb();return a&&a.toNegative(),t}},{}],57:[function(t,e,r){"use strict";var n={never:"always",nothing:"everything"};e.exports=function(t){var e=t.match("(never|nothing)").first();if(e.found){var r=e.out("normal");if(n[r])return(t=t.match(r).replaceWith(n[r],!0).list[0]).parentTerms}return t.delete("#Negative"),t}},{}],58:[function(t,e,r){"use strict";var n=t("../../text"),a=t("../../paths").Terms,i={data:function(){return this.list.map(function(t){var e=t.terms[0];return{spaceBefore:e.whitespace.before,text:e.text,spaceAfter:e.whitespace.after,normal:e.normal,implicit:e.silent_term,bestTag:e.bestTag(),tags:Object.keys(e.tags)}})}};e.exports=n.makeSubset(i,function(t,e){var r=[];return t.list.forEach(function(e){e.terms.forEach(function(n){r.push(new a([n],e.world,t))})}),t=new n(r,t.world,t.parent),"number"==typeof e&&(t=t.get(e)),t})},{"../../paths":8,"../../text":192}],59:[function(t,e,r){"use strict";var n=t("./numOrdinal"),a=t("./textOrdinal"),i=t("./textCardinal"),o=t("./niceNumber"),s={nice:function(t){return o(t)},ordinal:function(t){return n(t)},cardinal:function(t){return String(t)},niceOrdinal:function(t){return t=n(t),o(t)},text:function(t){return i(t).join(" ")},textOrdinal:function(t){return a(t)}};e.exports=s},{"./niceNumber":60,"./numOrdinal":61,"./textCardinal":62,"./textOrdinal":63}],60:[function(t,e,r){"use strict";e.exports=function(t){if(!t&&0!==t)return null;for(var e=(t=String(t)).split("."),r=e[0],n=e.length>1?"."+e[1]:"",a=/(\d+)(\d{3})/;a.test(r);)r=r.replace(a,"$1,$2");return r+n}},{}],61:[function(t,e,r){"use strict";var n=t("./toString");e.exports=function(t){if(!t&&0!==t)return null;var e=t%100;if(e>10&&e<20)return String(t)+"th";var r={0:"th",1:"st",2:"nd",3:"rd"},a=n(t),i=a.slice(a.length-1,a.length);return a+(r[i]?r[i]:"th")}},{"./toString":64}],62:[function(t,e,r){"use strict";var n=t("./toString"),a=[["ninety",90],["eighty",80],["seventy",70],["sixty",60],["fifty",50],["forty",40],["thirty",30],["twenty",20]],i=["","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],o=[[1e24,"septillion"],[1e21,"sextillion"],[1e18,"quintillion"],[1e15,"quadrillion"],[1e12,"trillion"],[1e9,"billion"],[1e8,"hundred million"],[1e6,"million"],[1e5,"hundred thousand"],[1e3,"thousand"],[100,"hundred"],[1,"one"]],s=function(t){var e=[];if(t>100)return e;for(var r=0;r=a[r][1]&&(t-=a[r][1],e.push(a[r][0]));return i[t]&&e.push(i[t]),e};e.exports=function(t){if(t>1e21)return[String(t)];var e=[];t<0&&(e.push("negative"),t=Math.abs(t));for(var r=function(t){var e=t,r=[];return o.forEach(function(n){if(t>=n[0]){var a=Math.floor(e/n[0]);e-=a*n[0],a&&r.push({unit:n[1],count:a})}}),r}(t),a=0;a1&&e.push("and")),(e=e.concat(s(r[a].count))).push(i)}return 0===(e=(e=e.concat(function(t){var e=["zero","one","two","three","four","five","six","seven","eight","nine"],r=[],a=n(t).match(/\.([0-9]+)/);if(!a||!a[0])return r;r.push("point");for(var i=a[0].split(""),o=0;ot}),this},lessThan:function(t){return t=i(t),this.list=this.list.filter(function(e){return null!==t&&e.number()t&&ni[o].length)return n[i[o]];return null}},{"./suffix_rules":88}],88:[function(t,e,r){"use strict";for(var n={Gerund:["ing"],Actor:["erer"],Infinitive:["ate","ize","tion","rify","then","ress","ify","age","nce","ect","ise","ine","ish","ace","ash","ure","tch","end","ack","and","ute","ade","ock","ite","ase","ose","use","ive","int","nge","lay","est","ain","ant","ent","eed","er","le","own","unk","ung","en"],PastTense:["ed","lt","nt","pt","ew","ld"],PresentTense:["rks","cks","nks","ngs","mps","tes","zes","ers","les","acks","ends","ands","ocks","lays","eads","lls","els","ils","ows","nds","ays","ams","ars","ops","ffs","als","urs","lds","ews","ips","es","ts","ns","s"]},a={},i=Object.keys(n),o=i.length,s=0;s1&&!0===a.test(t.text)&&t.canBe("RomanNumeral")}(r)&&r.tag("RomanNumeral","is-roman-numeral"),!0===/[0-9]\+$/.test(r.text)&&r.tag("NumericValue","number-plus")}),t}},{}],100:[function(t,e,r){"use strict";var n=t("./rules/emoji_regex"),a=t("./rules/emoticon_list"),i=function(t){return!(":"!==t.text.charAt(0)||null===t.text.match(/:.?$/)||t.text.match(" ")||t.text.length>35)},o=function(t){var e=t.text.replace(/^[:;]/,":");return!0===a.hasOwnProperty(e)};e.exports=function(t){for(var e=0;e0;s-=1){var u=a+" "+i.slice(0,s).join(" ");if(!0===n.hasOwnProperty(u))return t.slice(e,e+s+1).tag(n[u],"multi-lexicon-"+u),s}return 0};e.exports=function(t){t.world.cache=t.world.cache||{};for(var e=t.world.cache.firstWords||{},r=0;r1;n-=1){var i=t.normal.substr(e-n,e);if(void 0!==a[n][i])return a[n][i]}return null},s=function(t){var e=t.normal.charAt(t.normal.length-1);if(void 0===n[e])return null;for(var r=n[e],a=0;a1e3&&r<3e3&&t.terms[0].tag("Year",e)})},u=function(t,e){!0===t.found&&t.list.forEach(function(t){var r=parseInt(t.terms[0].normal,10);r&&r>1900&&r<2030&&t.terms[0].tag("Year",e)})};e.exports=function(t){var e="(january|april|may|june|summer|autumn|jan|sep)";t.has(e)&&(t.match("#Infinitive #Determiner? #Adjective? #Noun? (to|for) ".concat(e)).lastTerm().tag("Person","ambig-person"),t.match("#Infinitive ".concat(e)).lastTerm().tag("Person","infinitive-person"),t.match("".concat(e," #PresentTense (to|for)")).firstTerm().tag("Person","ambig-active"),t.match("".concat(e," #Modal")).firstTerm().tag("Person","ambig-modal"),t.match("#Modal ".concat(e)).lastTerm().tag("Person","modal-ambig"),t.match("(that|with|for) ".concat(e)).term(1).tag("Person","that-month"),t.match("#Copula ".concat(e)).term(1).tag("Person","is-may"),t.match("".concat(e," #Copula")).term(0).tag("Person","may-is"),t.match("".concat(e," the? #Value")).term(0).tag("Month","person-value"),t.match("#Date ".concat(e)).term(1).tag("Month","correction-may"),t.match("".concat(e," the? #Value")).firstTerm().tag("Month","may-5th"),t.match("#Value of ".concat(e)).lastTerm().tag("Month","5th-of-may"),t.match("".concat(n," ").concat(e)).ifNo("#Holiday").term(1).tag("Month","preps-month"),t.match("(next|this|last) ".concat(e)).term(1).tag("Month","correction-may"));var r="(may|march)";if(t.has(r)&&(t.match("#Adverb ".concat(r)).lastTerm().tag("Infinitive","ambig-verb"),t.match("".concat(r," #Adverb")).lastTerm().tag("Infinitive","ambig-verb"),t.match("".concat(n," ").concat(r)).lastTerm().tag("Month","in-month"),t.match("(next|this|last) ".concat(r)).lastTerm().tag("Month","this-month"),t.match("".concat(r," the? #Value")).firstTerm().tag("Month","march-5th"),t.match("#Value of? ".concat(r)).lastTerm().tag("Month","5th-of-march"),t.match("[".concat(r,"] .? #Date")).lastTerm().tag("Month","march-and-feb"),t.match("#Date .? [".concat(r,"]")).lastTerm().tag("Month","feb-and-march"),t.has("march")&&(t.match("march (up|down|back|to|toward)").term(0).tag("Infinitive","march-to"),t.match("#Modal march").term(1).tag("Infinitive","must-march"))),t.has("sun")&&(t.match("sun #Date").firstTerm().tag("WeekDay","sun-feb"),t.match("sun the #Ordinal").tag("Date").firstTerm().tag("WeekDay","sun-the-5th"),t.match("#Determiner sun").lastTerm().tag("Singular","the-sun")),t.has("sat")&&(t.match("sat #Date").firstTerm().tag("WeekDay","sat-feb"),t.match("".concat(n," sat")).lastTerm().tag("WeekDay","sat")),t.has("#Month")&&(t.match("#Month #DateRange+").tag("Date","correction-numberRange"),t.match("#Value of #Month").tag("Date","value-of-month"),t.match("#Cardinal #Month").tag("Date","cardinal-month"),t.match("#Month #Value to #Value").tag("Date","value-to-value"),t.match("#Month the #Value").tag("Date","month-the-value")),t.match("in the (night|evening|morning|afternoon|day|daytime)").tag("Time","in-the-night"),t.match("(#Value|#Time) (am|pm)").tag("Time","value-ampm"),t.has("#Value")){t.match("for #Value #Duration").tag("Date","for-x-duration"),t.match("#Value #Abbreviation").tag("Value","value-abbr"),t.match("a #Value").if("(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)").tag("Value","a-value"),t.match("(minus|negative) #Value").tag("Value","minus-value"),t.match("#Value grand").tag("Value","value-grand"),t.match("(half|quarter) #Ordinal").tag("Value","half-ordinal"),t.match("(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion) and #Value").tag("Value","magnitude-and-value"),t.match("#Value (point|decimal) #Value").tag("Value","value-point-value"),t.match("".concat(n,"? #Value #Duration")).tag("Date","value-duration"),t.match("(#WeekDay|#Month) #Value").ifNo("#Money").tag("Date","date-value"),t.match("#Value (#WeekDay|#Month)").ifNo("#Money").tag("Date","value-date");var l=t.match("#TextValue #TextValue");l.found&&l.has("#Date")&&l.tag("#Date","textvalue-date"),t.match("#Value #Duration #Conjunction").tag("Date","val-duration-conjunction"),t.match("#Value #Duration old").unTag("Date","val-years-old")}if(t.has(o)&&(t.match("".concat(n,"? ").concat(a," ").concat(o)).tag("Date","thisNext-season"),t.match("the? ".concat(i," of ").concat(o)).tag("Date","section-season")),t.has("#Date")&&(t.match("#Date the? #Ordinal").tag("Date","correction-date"),t.match("".concat(a," #Date")).tag("Date","thisNext-date"),t.match("due? (by|before|after|until) #Date").tag("Date","by-date"),t.match("#Date (by|before|after|at|@|about) #Cardinal").not("^#Date").tag("Time","date-before-Cardinal"),t.match("#Date (am|pm)").term(1).unTag("Verb").unTag("Copula").tag("Time","date-am"),t.match("(last|next|this|previous|current|upcoming|coming|the) #Date").tag("Date","next-feb"),t.match("#Date (#Preposition|to) #Date").tag("Date","date-prep-date"),t.match("the? ".concat(i," of #Date")).tag("Date","section-of-date"),t.match("#Ordinal #Duration in #Date").tag("Date","duration-in-date"),t.match("(early|late) (at|in)? the? #Date").tag("Time","early-evening")),t.has("#Cardinal")){var c=t.match("#Date #Value #Cardinal").lastTerm();s(c,"date-value-year"),c=t.match("#Date+ #Cardinal").lastTerm(),s(c,"date-year"),c=t.match("#Month #Value #Cardinal").lastTerm(),s(c,"month-value-year"),c=t.match("#Month #Value to #Value #Cardinal").lastTerm(),s(c,"month-range-year"),c=t.match("(in|of|by|during|before|starting|ending|for|year) #Cardinal").lastTerm(),s(c,"in-year"),c=t.match("(q1|q2|q3|q4) [#Cardinal]"),s(c,"in-year"),c=t.match("#Ordinal quarter [#Cardinal]"),s(c,"in-year"),c=t.match("the year [#Cardinal]"),s(c,"in-year"),c=t.match("it (is|was) [#Cardinal]"),u(c,"in-year"),c=t.match("#Cardinal !#Plural").firstTerm(),u(c,"year-unsafe")}if(t.has("#Date")){t.has("#Time")&&(t.match("#Cardinal #Time").not("#Year").tag("Time","value-time"),t.match("(by|before|after|at|@|about) #Time").tag("Time","preposition-time"),t.match("#Time (eastern|pacific|central|mountain)").term(1).tag("Time","timezone"),t.match("#Time (est|pst|gmt)").term(1).tag("Time","timezone abbr"));var h=t.match("#Date+").splitOn("Clause");!1===h.has("(#Year|#Time)")&&h.match("#Value (#Month|#Weekday) #Value").lastTerm().unTag("Date")}return t}},{}],110:[function(t,e,r){"use strict";var n={do:!0,"don't":!0,does:!0,"doesn't":!0,will:!0,wont:!0,"won't":!0,have:!0,"haven't":!0,had:!0,"hadn't":!0,not:!0};e.exports=function(t){for(var e=0;e0&&s.tags.Conjunction)o=!0;else{if(s.tags[n]){if(s.tags.Comma){i+=1,a=0;continue}if(i>0&&o)return t.slice(r,e).tag("List"),!0}if((a+=1)>5)return!1;if("Value"===n)return!0}}return!1};e.exports=function(t){for(var e=0;e28);s++){for(var u=-1,l=0;l0&&(i(r)||i(t.terms[e-1]))&&t.terms[e-1].tags.Value){var o=new a("",t.world);return o.silent_term="to",t.insertAt(e,o),t.terms[e-1].tag("NumberRange","number-number1"),t.terms[e].tag("NumberRange","number-number2"),t.terms[e].whitespace.before="",t.terms[e].whitespace.after="",t.terms[e+1].tag("NumberRange","number-number3"),t}if(r.tags.NumberRange){var s=r.text.split(/(-|–|—)/);s[1]="to",(t=n(t,s,e)).terms[e].tag(["NumberRange","NumericValue"],"numRange-1"),t.terms[e+1].tag(["NumberRange","Preposition"],"numRange-silent"),t.terms[e+2].tag(["NumberRange","NumericValue"],"numRange-3"),e+=2}}}return t}},{"../../../term":143,"./fix":128}],128:[function(t,e,r){"use strict";var n=t("../../../term"),a={not:"Negative",will:"Verb",would:"Modal",have:"Verb",are:"Copula",is:"Copula",am:"Verb"},i=function(t){a[t.silent_term]&&t.tag(a[t.silent_term])};e.exports=function(t,e,r){var a=t.terms[r];if(a.silent_term=e[0],a.tag("Contraction","tagger-contraction"),e[1]){var o=new n("",t.world);o.silent_term=e[1],o.tag("Contraction","tagger-contraction"),t.insertAt(r+1,o),o.whitespace.before="",o.whitespace.after="",i(o)}if(e[2]){var s=new n("",t.world);s.silent_term=e[2],t.insertAt(r+2,s),s.tag("Contraction","tagger-contraction"),i(s)}return t}},{"../../../term":143}],129:[function(t,e,r){"use strict";var n=/^([a-z]+)'([a-z][a-z]?)$/i,a=/[a-z]s'$/i,i={re:1,ve:1,ll:1,t:1,s:1,d:1,m:1};e.exports=function(t){if("can't"===t.normal)return{start:"can",end:"n't"};var e=t.normal.match(n);return e&&e[1]&&1===i[e[2]]?("t"===e[2]&&e[1].match(/[a-z]n$/)&&(e[1]=e[1].replace(/n$/,""),e[2]="n't"),!0===t.tags.TitleCase&&(e[1]=e[1].replace(/^[a-z]/,function(t){return t.toUpperCase()})),{start:e[1],end:e[2]}):!0===a.test(t.text)?{start:t.normal.replace(/s'?$/,""),end:""}:null}},{}],130:[function(t,e,r){"use strict";e.exports=/(?:0\u20E3\n1\u20E3|2\u20E3|3\u20E3|4\u20E3|5\u20E3|6\u20E3|7\u20E3|8\u20E3|9\u20E3|#\u20E3|\*\u20E3|\uD83C(?:\uDDE6\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF2|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFD|\uDDFF)|\uDDE7\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFC|\uDDFE|\uDDFF)|\uDDE8\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDE9\uD83C(?:\uDDEA|\uDDEC|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDFF)|\uDDEA\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDED|\uDDF7|\uDDF8|\uDDF9|\uDDFA)|\uDDEB\uD83C(?:\uDDEE|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDF7)|\uDDEC\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF1|\uDDF2|\uDDF3|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFE)|\uDDED\uD83C(?:\uDDF0|\uDDF2|\uDDF3|\uDDF7|\uDDF9|\uDDFA)|\uDDEE\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9)|\uDDEF\uD83C(?:\uDDEA|\uDDF2|\uDDF4|\uDDF5)|\uDDF0\uD83C(?:\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDF2|\uDDF3|\uDDF5|\uDDF7|\uDDFC|\uDDFE|\uDDFF)|\uDDF1\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDEE|\uDDF0|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFE)|\uDDF2\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDF3\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFF)|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C(?:\uDDE6|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF7|\uDDF8|\uDDF9|\uDDFC|\uDDFE)|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C(?:\uDDEA|\uDDF4|\uDDF8|\uDDFA|\uDDFC)|\uDDF8\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDE9|\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFD|\uDDFE|\uDDFF)|\uDDF9\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF9|\uDDFB|\uDDFC|\uDDFF)|\uDDFA\uD83C(?:\uDDE6|\uDDEC|\uDDF2|\uDDF8|\uDDFE|\uDDFF)|\uDDFB\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDEE|\uDDF3|\uDDFA)|\uDDFC\uD83C(?:\uDDEB|\uDDF8)|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C(?:\uDDEA|\uDDF9)|\uDDFF\uD83C(?:\uDDE6|\uDDF2|\uDDFC)))|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD79\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED0\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3]|\uD83E[\uDD10-\uDD18\uDD80-\uDD84\uDDC0]/g},{}],131:[function(t,e,r){"use strict";e.exports={":(":!0,":)":!0,":P":!0,":p":!0,":O":!0,":3":!0,":|":!0,":/":!0,":\\":!0,":$":!0,":*":!0,":@":!0,":-(":!0,":-)":!0,":-P":!0,":-p":!0,":-O":!0,":-3":!0,":-|":!0,":-/":!0,":-\\":!0,":-$":!0,":-*":!0,":-@":!0,":^(":!0,":^)":!0,":^P":!0,":^p":!0,":^O":!0,":^3":!0,":^|":!0,":^/":!0,":^\\":!0,":^$":!0,":^*":!0,":^@":!0,"):":!0,"(:":!0,"$:":!0,"*:":!0,")-:":!0,"(-:":!0,"$-:":!0,"*-:":!0,")^:":!0,"(^:":!0,"$^:":!0,"*^:":!0,"<3":!0,"3&&!0===o.test(t.normal)&&!1===i.test(t.normal)&&!1===t.isAcronym()||!0===s.test(t.normal)&&!1===t.tags.hasOwnProperty("Value")&&!0===/[a-z][0-9][a-z]/.test(t.normal)))}};return Object.keys(e).forEach(function(r){t.prototype[r]=e[r]}),t}},{"./bestTag":145,"./normalize/isAcronym":148}],148:[function(t,e,r){"use strict";var n=/([A-Z]\.)+[A-Z]?,?$/,a=/^[A-Z]\.,?$/,i=/[A-Z]{2}('s|,)?$/;e.exports=function(t){return!0===n.test(t)||!0===a.test(t)||!0===i.test(t)}},{}],149:[function(t,e,r){"use strict";var n=t("./unicode"),a=t("./isAcronym");r.normalize=function(t){var e=t=(t=(t=t||"").toLowerCase()).trim();return t=(t=(t=(t=(t=(t=(t=n(t)).replace(/^[#@]/,"")).replace(/[,;.!?]+$/,"")).replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g,"'")).replace(/[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g,'"')).replace(/\u2026/g,"...")).replace(/\u2013/g,"-"),!0===/[a-z][^aeiou]in['’]$/.test(t)&&(t=t.replace(/in['’]$/,"ing")),!0===/^(re|un)-?[^aeiou]./.test(t)&&(t=t.replace("-","")),!1===/^[:;]/.test(t)&&(t=(t=(t=t.replace(/\.{3,}$/g,"")).replace(/['",\.!:;\?\)]+$/g,"")).replace(/^['"\(]+/g,"")),""===(t=t.trim())&&(t=e),t},r.addNormal=function(t){var e=t._text||"";e=r.normalize(e),a(t._text)&&(e=e.replace(/\./g,"")),e=e.replace(/([0-9]),([0-9])/g,"$1$2"),t.normal=e}},{"./isAcronym":148,"./unicode":151}],150:[function(t,e,r){"use strict";e.exports=function(t){var e=t.normal||t.silent_term||"";e=(e=e.replace(/'s\b/,"")).replace(/'$/,""),t.root=e}},{}],151:[function(t,e,r){"use strict";var n={"!":"¡","?":"¿Ɂ",'"':'“”"❝❞',"'":"‘‛❛❜","-":"—–",a:"ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАДадѦѧӐӑӒӓƛɅæ",b:"ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬбвъьѢѣҌҍҔҕƥƾ",c:"¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾϿЄСсєҀҁҪҫ",d:"ÐĎďĐđƉƊȡƋƌǷ",e:"ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ",f:"ƑƒϜϝӺӻҒғӶӷſ",g:"ĜĝĞğĠġĢģƓǤǥǦǧǴǵ",h:"ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ",I:"ÌÍÎÏ",i:"ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії",j:"ĴĵǰȷɈɉϳЈј",k:"ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ",l:"ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ",m:"ΜϺϻМмӍӎ",n:"ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ",o:"ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ¤ƍΏ",p:"ƤƿΡρϷϸϼРрҎҏÞ",q:"Ɋɋ",r:"ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ",s:"ŚśŜŝŞşŠšƧƨȘșȿςϚϛϟϨϩЅѕ",t:"ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮϯТт҂Ҭҭ",u:"µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύϑЏЦЧцџҴҵҶҷӋӌӇӈ",v:"νѴѵѶѷ",w:"ŴŵƜωώϖϢϣШЩшщѡѿ",x:"×ΧχϗϰХхҲҳӼӽӾӿ",y:"ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ",z:"ŹźŻżŽžƩƵƶȤȥɀΖζ"},a={};Object.keys(n).forEach(function(t){n[t].split("").forEach(function(e){a[e]=t})}),e.exports=function(t){var e=t.split("");return e.forEach(function(t,r){a[t]&&(e[r]=a[t])}),e.join("")}},{}],152:[function(t,e,r){"use strict";var n=t("../../paths"),a=n.fns,i=n.tags;e.exports=function(t){for(var e="silver",r=Object.keys(t.tags),n=0;n":">","&":"&",'"':""","'":"'"," ":" "};return t.replace(/[<>&"' ]/g,function(t){return e[t]})};e.exports=function(t){var e=Object.keys(t.tags).filter(function(t){return"Term"!==t});e=(e=e.map(function(t){return"nl-"+t})).join(" ");var r=function(t){var e,r="(?:[^\"'>]|\"[^\"]*\"|'[^']*')*",n=new RegExp("<(?:!--(?:(?:-*[^->])*--+|-?)|script\\b"+r+">[\\s\\S]*?[\\s\\S]*?","gi");do{e=t,t=t.replace(n,"")}while(t!==e);return t.replace(/'+(r=n(r))+"";return n(t.whitespace.before)+a+n(t.whitespace.after)}},{}],155:[function(t,e,r){"use strict";var n=t("../../paths").fns;e.exports=function(t){var e=Object.keys(t.tags).map(function(t){return n.printTag(t)}).join(", "),r=t.text;r="'"+n.yellow(r||"-")+"'";var a="";t.silent_term&&(a="["+t.silent_term+"]"),r=n.leftPad(r,20),r+=n.leftPad(a,8),console.log(" "+r+" - "+e)}},{"../../paths":161}],156:[function(t,e,r){"use strict";var n=/([a-z0-9 ])([,:;.!?]+)$/i;e.exports=function(t){var e={getPunctuation:function(){var t=this.text.match(n);return t?t[2]:(t=this.whitespace.after.match(n))?t[2]:null},setPunctuation:function(t){return this.killPunctuation(),this.text+=t,","===t&&(this.tags.Comma=!0),this},hasComma:function(){return","===this.getPunctuation()},killPunctuation:function(){return this.text=this._text.replace(n,"$1"),delete this.tags.Comma,delete this.tags.ClauseEnd,this}};return Object.keys(e).forEach(function(r){t.prototype[r]=e[r]}),t}},{}],157:[function(t,e,r){"use strict";e.exports=function t(e,r){var n=e.world.tags;if(void 0===n[r])return!0;for(var a=n[r].notA||[],i=0;i0&&(r[r.length-1]+=g),r.map(function(t){return new n(t,e)})}},{"../term":143}],164:[function(t,e,r){"use strict";e.exports={parent:{get:function(){return this.refText||this},set:function(t){return this.refText=t,this}},parentTerms:{get:function(){return this.refTerms||this},set:function(t){return this.refTerms=t,this}},dirty:{get:function(){for(var t=0;t0}},length:{get:function(){return this.terms.length}},isA:{get:function(){return"Terms"}},whitespace:{get:function(){var t=this;return{before:function(e){return t.firstTerm().whitespace.before=e,t},after:function(e){return t.lastTerm().whitespace.after=e,t}}}}}},{}],165:[function(t,e,r){"use strict";var n=t("./build"),a=t("./getters"),i=t("../world"),o=function(t,e,r,n){var o=this;this.terms=t,this.world=e||i,this.refText=r,this._refTerms=n,this.get=function(t){return o.terms[t]};for(var s=Object.keys(a),u=0;u0);r++){var i=a(this,r,e);if(i)return i}return null},has:function(t){return null!==this.matchOne(t)}};return Object.keys(e).forEach(function(r){t.prototype[r]=e[r]}),t}},{"../../text":192,"./lib":170,"./lib/startHere":174,"./lib/syntax":175}],167:[function(t,e,r){"use strict";e.exports=function(t,e){e.capture?t.captureGroup=!0:t.captureGroup=void 0}},{}],168:[function(t,e,r){"use strict";e.exports=function(t){var e=[];return t.forEach(function(t){if(0!==t.filter(function(t){return!0===t.captureGroup}).length){for(var r=[],n=0;n0&&(e.push(r),r=[]);r.length>0&&e.push(r)}else e.push(t)}),e}},{}],169:[function(t,e,r){"use strict";e.exports=function(t,e){for(var r=0;r0&&e[0]&&e[0].starting);l+=1){var c=a(t,l,e,r);c&&c.length>0&&(u.push(c),l+=c.length-1)}return o(u)}},{"./captureGroup":168,"./fastPass":169,"./startHere":174,"./syntax":175}],171:[function(t,e,r){"use strict";var n=t("./applyCaptureGroup");e.exports=function(t,e,r){if(!t||!e)return!1;var a=function(t,e){if(!t||!e)return!1;if(!0===e.anyOne)return!0;if(void 0!==e.tag)return t.tags[e.tag];if(void 0!==e.id)return e.id===t.uid;if(void 0!==e.normal)return e.normal===t.normal||e.normal===t.silent_term;if(!0===e.suffix&&void 0!==e.partial){var r=t.normal.length;return t.normal.substr(r-e.partial.length,r)===e.partial}if(!0===e.prefix&&void 0!==e.partial)return t.normal.substr(0,e.partial.length)===e.partial;if(!0===e.infix&&e.partial)return-1!==t.normal.indexOf(e.partial);if(void 0!==e.regex)return e.regex.test(t.normal)||e.regex.test(t.text);if(void 0!==e.oneOf){for(var n=0;n0)return null;if(!0===m.ending&&l!==t.length-1&&!m.minMax)return null;if(!0!==m.astrix)if(void 0===r[c].minMax)if(!0!==m.optional)if(a(h,m,u)){if(l+=1,!0===m.consecutive){var d=r[c+1];l=s(t,l,m,d)}}else if(!h.silent_term||h.normal){var p=n(h,r,c,u);if(null===p){if(!0!==m.optional)return null}else c=p,l+=1}else{if(0===c)return null;l+=1,c-=1}else{var g=r[c+1];l=s(t,l,m,g)}else for(var v=r[c].minMax.min||0,y=r[c].minMax.max,b=r[c+1],D=0;D=v&&a(w,b))break;var x=t.terms[l+D+1];if(x&&a(x,b)){l+=D+2,c+=1;break}if(D===y-1)return null}}else{if(!f){for(var C=t.terms.slice(e,t.length),k=l-e;k0?(l.length>0&&(s.push(l),l=[]),c+=h.length-1):l.push(e.terms[c])}return l.length>0&&s.push(l),s=s.map(function(r){return new t(r,e.world,e.refText,e.refTerms)}),new o(s,e.world,e.parent)},notArray:function(t,r){var n=r.reduce(function(t,e){return t[e]=!0,t},{});return e.notObj(t,n)},notText:function(t,r){var n=r.out("array");return e.notArray(t,n)}};return t.prototype.not=function(t,r){if("object"===n(t)){var a=Object.prototype.toString.call(t);if("[object Array]"===a)return e.notArray(this,t,r);if("[object Object]"===a)return"Text"===t.isA?e.notText(this,t,r):e.notObj(this,t,r)}return"string"==typeof t?e.notString(this,t,r):this},t}},{"../../text":192,"./lib/startHere":174,"./lib/syntax":175}],177:[function(t,e,r){"use strict";var n=t("../mutate");e.exports=function(t){return t.prototype.delete=function(t){if(!this.found)return this;if(!t)return this.parentTerms=n.deleteThese(this.parentTerms,this),this;var e=this.match(t);return e.found?n.deleteThese(this,e):this.parentTerms},t}},{"../mutate":188}],178:[function(t,e,r){"use strict";var n=t("../mutate"),a=function(t,e){return t.terms.length&&t.terms[e]?(t.terms[e].whitespace.before=" ",t):t};e.exports=function(t){var e=function(e,r){if("Terms"===e.isA)return e;if("Term"===e.isA)return new t([e],r);var n=t.fromString(e,r);return n.tagger(),n},r={insertBefore:function(t,r){var i=this.terms.length,o=e(t,this.world);r&&o.tag(r);var s=this.index();return a(this.parentTerms,s),s>0&&a(o,0),this.parentTerms.terms=n.insertAt(this.parentTerms.terms,s,o),this.terms.length===i&&(this.terms=o.terms.concat(this.terms)),this},insertAfter:function(t,r){var i=this.terms.length,o=e(t,this.world);r&&o.tag(r);var s=this.terms[this.terms.length-1].index();return a(o,0),this.parentTerms.terms=n.insertAt(this.parentTerms.terms,s+1,o),this.terms.length===i&&(this.terms=this.terms.concat(o.terms)),this},insertAt:function(t,r,i){t<0&&(t=0);var o=this.terms.length,s=e(r,this.world);return i&&s.tag(i),t>0&&a(s,0),this.parentTerms.terms=n.insertAt(this.parentTerms.terms,t,s),this.terms.length===o&&Array.prototype.splice.apply(this.terms,[t,0].concat(s.terms)),0===t&&(this.terms[0].whitespace.before="",s.terms[s.terms.length-1].whitespace.after=" "),this}};return Object.keys(r).forEach(function(e){t.prototype[e]=r[e]}),t}},{"../mutate":188}],179:[function(t,e,r){"use strict";e.exports=function(t){return[["toUpperCase","UpperCase"],["toLowerCase"],["toTitleCase","TitleCase"]].forEach(function(e){var r=e[0],n=e[1];t.prototype[r]=function(){var t=arguments;return this.terms.forEach(function(e){e[r].apply(e,t)}),n&&this.tag(n,r),this}}),t}},{}],180:[function(t,e,r){"use strict";var n=t("../../../term");e.exports=function(t,e){var r=t.terms[e],a=t.terms[e+1];if(a){var i=function(t,e){return t.whitespace.before+t.text+t.whitespace.after+(e.whitespace.before+e.text+e.whitespace.after)}(r,a);t.terms[e]=new n(i,r.context),t.terms[e].normal=r.normal+" "+a.normal,t.terms[e].lumped=!0,t.terms[e].parentTerms=t.terms[e+1].parentTerms,t.terms[e+1]=null,t.terms=t.terms.filter(function(t){return null!==t})}}},{"../../../term":143}],181:[function(t,e,r){"use strict";var n=t("./combine"),a=t("../../mutate"),i=function(t,e){for(var r=t.terms.length,a=0;a0&&(e+=t.terms[n].whitespace.before),e+=t.terms[n].text.replace(/[,.?!]$/,""),n0&&(this.terms[this.terms.length-1].whitespace.after+=i),this}};return Object.keys(e).forEach(function(r){t.prototype[r]=e[r]}),t}},{"../mutate":188}],185:[function(t,e,r){"use strict";var n=function(t,e){for(var r=e.terms[0],n=e.terms.length,a=0;a1?(this.terms.forEach(function(t,n){t.tag(r[n],e)}),this):(this.terms.forEach(function(r){r.tag(t,e)}),this)},unTag:function(t,e){var r=[];return"string"==typeof t&&(r=t.split(" ")),r.length>1?(this.terms.forEach(function(t,n){t.unTag(r[n],e)}),this):(this.terms.forEach(function(r){r.unTag(t,e)}),this)},canBe:function(e){var r=this.terms.filter(function(t){return t.canBe(e)});return new t(r,this.world,this.refText,this.refTerms)}};return Object.keys(e).forEach(function(r){t.prototype[r]=e[r]}),t}},{}],187:[function(t,e,r){"use strict";e.exports=function(t){var e={clone:function(){var e=this.terms.map(function(t){return t.clone()});return new t(e,this.world,this.refText,null)},hyphenate:function(){var t=this;return this.terms.forEach(function(e,r){r!==t.terms.length-1&&(e.whitespace.after="-"),0!==r&&(e.whitespace.before="")}),this},dehyphenate:function(){return this.terms.forEach(function(t){"-"===t.whitespace.after&&(t.whitespace.after=" ")}),this},trim:function(){return this.length<=0?this:(this.terms[0].whitespace.before="",this.terms[this.terms.length-1].whitespace.after="",this)}};return Object.keys(e).forEach(function(r){t.prototype[r]=e[r]}),t}},{}],188:[function(t,e,r){"use strict";var n=function(t){var e=[];return"Terms"===t.isA?e=t.terms:"Text"===t.isA?e=t.flatten().list[0].terms:"Term"===t.isA&&(e=[t]),e};r.deleteThese=function(t,e){var r=n(e);return t.terms=t.terms.filter(function(t){for(var e=0;e0&&a[0]&&!a[0].whitespace.before&&(a[0].whitespace.before=" "),Array.prototype.splice.apply(t,[e,0].concat(a)),t}},{}],189:[function(t,e,r){"use strict";e.exports={fns:t("../fns"),Term:t("../term")}},{"../fns":3,"../term":143}],190:[function(t,e,r){"use strict";var n=t("./index"),a=t("./tokenize"),i=t("./paths"),o=i.Terms,s=i.fns;e.exports=function(t,e){var r=[];s.isArray(t)?r=t:(t=s.ensureString(t),r=a(t));var i=r.map(function(t){return o.fromString(t,e)}),u=new n(i,e);return u.list.forEach(function(t){t.refText=u}),u}},{"./index":192,"./paths":205,"./tokenize":207}],191:[function(t,e,r){"use strict";e.exports={found:function(){return this.list.length>0},parent:function(){return this.original||this},length:function(){return this.list.length},isA:function(){return"Text"},whitespace:function(){var t=this;return{before:function(e){return t.list.forEach(function(t){t.whitespace.before(e)}),t},after:function(e){return t.list.forEach(function(t){t.whitespace.after(e)}),t}}}}},{}],192:[function(t,e,r){"use strict";var n=t("./getters");function a(t,e,r){this.list=t||[],"function"==typeof e&&(e=e()),this.world=function(){return e},this.original=r;for(var a=Object.keys(n),i=0;i0&&r.push(o)}}var s=this.parent||this;return new t(r,this.world(),s)},after:function(e){for(var r=[],n=0;n0&&r.push(o)}}var s=this.parent||this;return new t(r,this.world(),s)}};return i.and=i.match,i.notIf=i.ifNo,i.only=i.if,i.onlyIf=i.if,t.addMethods(t,i),t}},{"../../../terms":165,"../../../terms/match/lib/syntax":175}],195:[function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var a=t("../../terms");e.exports=function(t){var e={all:function(){return this.parent},index:function(){return this.list.map(function(t){return t.index()})},wordCount:function(){return this.terms().length},data:function(){return this.list.map(function(t){return t.data()})},map:function(e){var r=this;return this.list.map(function(n,a){var i=new t([n],r.world);return e(i,a)})},forEach:function(e){var r=this;return this.list.forEach(function(n,a){var i=new t([n],r.world);e(i,a)}),this},filter:function(e){var r=this,n=this.list.filter(function(n,a){var i=new t([n],r.world);return e(i,a)});return new t(n,this.world)},reduce:function(e,r){var n=this;return this.list.reduce(function(r,a){var i=new t([a],n.world);return e(r,i)},r)},find:function(e){for(var r=0;rr&&(a=r),n=n.concat(this.list.slice(0,a))}return new t(n,this.world,this.parent)},setPunctuation:function(t){return this.list.forEach(function(e){return e.setPunctuation(t)}),this},getPunctuation:function(t){return t||0===t?this.list[t]?this.list[t].getPunctuation():"":this.list.map(function(t){return t.getPunctuation()})},offset:function(){return this.out("offset")},text:function(){return this.out("text")}};e.eq=e.get,e.join=e.flatten,t.addMethods(t,e)}},{"../../terms":165}],196:[function(t,e,r){"use strict";var n=t("../../term/methods/normalize/unicode"),a={whitespace:!0,case:!0,numbers:!0,punctuation:!0,unicode:!0,contractions:!0,acronyms:!0,parentheses:!1,possessives:!1,plurals:!1,verbs:!1,honorifics:!1},i={whitespace:function(t){return t.terms().list.forEach(function(t,e){var r=t.terms[0];e>0&&!r.silent_term?r.whitespace.before=" ":0===e&&(r.whitespace.before=""),r.whitespace.after="",!0===r.tags.StartQuotation&&(r.whitespace.before+='"'),!0===r.tags.EndQuotation&&(r.whitespace.after='"'+r.whitespace.after)}),t},case:function(t){return t.list.forEach(function(t){t.terms.forEach(function(e,r){0===r||e.tags.Person||e.tags.Place||e.tags.Organization||t.toLowerCase()})}),t},numbers:function(t){return t.values().toNumber(),t},punctuation:function(t){return t.list.forEach(function(t){if(t.terms.length){t.terms[0]._text=t.terms[0]._text.replace(/^¿/,"");for(var e=0;e "+t.list.reduce(function(t,e){return t+"\n "+e.terms.reduce(function(t,e){return t+"\n "+e.out("html")},"")+"\n "},"")+"\n"},terms:function(t){var e=[];return t.list.forEach(function(t){t.terms.forEach(function(t){e.push({text:t.text,normal:t.normal,tags:Object.keys(t.tags)})})}),e},debug:function(t){return console.log("===="),t.list.forEach(function(t){console.log(" --"),t.debug()}),t},topk:function(t){return n(t)},custom:function(t,e){return t.list.map(function(t){return t.out(e)})}};s.plaintext=s.text,s.normalized=s.normal,s.colors=s.color,s.tags=s.terms,s.offset=s.offsets,s.idexes=s.index,s.frequency=s.topk,s.freq=s.topk,s.arr=s.array,e.exports=function(t){return t.prototype.out=function(t){if("string"==typeof t){if(s[t])return s[t](this)}else if(!0===o.isObject(t))return s.custom(this,t);return s.text(this)},t.prototype.debug=function(){return s.debug(this)},t}},{"../paths":201,"./indexes":198,"./offset":199,"./topk":200}],198:[function(t,e,r){"use strict";e.exports=function(t){var e=[],r={};t.terms().list.forEach(function(t){r[t.terms[0].uid]=!0});var n=0;return t.all().list.forEach(function(t,a){t.terms.forEach(function(t,i){void 0!==r[t.uid]&&e.push({text:t.text,normal:t.normal,term:n,sentence:a,sentenceTerm:i}),n+=1})}),e}},{}],199:[function(t,e,r){"use strict";e.exports=function(t){var e=t.all();return t.list.map(function(t){for(var r=[],n=0;ne.count?-1:1}),e&&(n=n.splice(0,e)),n}},{}],201:[function(t,e,r){"use strict";e.exports=t("../paths")},{"../paths":205}],202:[function(t,e,r){"use strict";var n=t("./methods");e.exports=function(t){var e={sort:function(e){return(e=(e=e||"alphabetical").toLowerCase())&&"alpha"!==e&&"alphabetical"!==e?"chron"===e||"chronological"===e?n.chron(this,t):"length"===e?n.lengthFn(this,t):"freq"===e||"frequency"===e?n.freq(this,t):"wordcount"===e?n.wordCount(this,t):this:n.alpha(this,t)},reverse:function(){return this.list=this.list.reverse(),this},unique:function(){var t={};return this.list=this.list.filter(function(e){var r=e.out("root");return!t.hasOwnProperty(r)&&(t[r]=!0,!0)}),this}};return t.addMethods(t,e),t}},{"./methods":203}],203:[function(t,e,r){"use strict";var n=function(t){return(t=t.sort(function(t,e){return t.index>e.index?1:t.index===e.index?0:-1})).map(function(t){return t.ts})};r.alpha=function(t){return t.list.sort(function(t,e){if(t===e)return 0;if(t.terms[0]&&e.terms[0]){if(t.terms[0].root>e.terms[0].root)return 1;if(t.terms[0].roote.out("root")?1:-1}),t},r.chron=function(t){var e=t.list.map(function(t){return{ts:t,index:t.termIndex()}});return t.list=n(e),t},r.lengthFn=function(t){var e=t.list.map(function(t){return{ts:t,index:t.chars()}});return t.list=n(e).reverse(),t},r.wordCount=function(t){var e=t.list.map(function(t){return{ts:t,index:t.length}});return t.list=n(e),t},r.freq=function(t){var e={};t.list.forEach(function(t){var r=t.out("root");e[r]=e[r]||0,e[r]+=1});var r=t.list.map(function(t){var r=e[t.out("root")]||0;return{ts:t,index:-1*r}});return t.list=n(r),t}},{}],204:[function(t,e,r){"use strict";e.exports=function(t){return t.addMethods(t,{splitAfter:function(t,e){var r=[];return this.list.forEach(function(n){n.splitAfter(t,e).forEach(function(t){r.push(t)})}),this.list=r,this},splitBefore:function(t,e){var r=[];return this.list.forEach(function(n){n.splitBefore(t,e).forEach(function(t){r.push(t)})}),this.list=r,this},splitOn:function(t,e){var r=[];return this.list.forEach(function(n){n.splitOn(t,e).forEach(function(t){r.push(t)})}),this.list=r,this}}),t}},{}],205:[function(t,e,r){arguments[4][201][0].apply(r,arguments)},{"../paths":8,dup:201}],206:[function(t,e,r){"use strict";var n=t("../subset/sentences/isQuestion");e.exports=function(t){var e={clauses:function(t){var e=this.splitAfter("#ClauseEnd");return"number"==typeof t&&(e=e.get(t)),e},hashTags:function(t){var e=this.match("#HashTag").terms();return"number"==typeof t&&(e=e.get(t)),e},organizations:function(t){var e=this.splitAfter("#Comma");return e=e.match("#Organization+"),"number"==typeof t&&(e=e.get(t)),e},phoneNumbers:function(t){var e=this.splitAfter("#Comma");return e=e.match("#PhoneNumber+"),"number"==typeof t&&(e=e.get(t)),e},places:function(t){var e=this.splitAfter("#Comma");return e=e.match("#Place+"),"number"==typeof t&&(e=e.get(t)),e},quotations:function(t){var e=this.match("#Quotation+"),r=[];return e.list.forEach(function(t){var e=0,n=null;t.terms.forEach(function(a,i){!0===a.tags.StartQuotation&&(0===e&&(n=i),e+=1),e>0&&!0===a.tags.EndQuotation&&(e-=1),0===e&&null!==n&&(r.push(t.slice(n,i+1)),n=null)}),null!==n&&r.push(t.slice(n,t.terms.length))}),e.list=r,"number"==typeof t&&(e=e.get(t)),e},topics:function(t){var e=this.clauses(),r=e.people();return r.concat(e.places()),r.concat(e.organizations()),(r=r.not(["someone","man","woman","mother","brother","sister","father"])).sort("chronological"),"number"==typeof t&&(r=r.get(t)),r},urls:function(t){var e=this.match("#Url");return"number"==typeof t&&(e=e.get(t)),e},questions:function(e){var r=this.all();"number"==typeof e&&(r=r.get(e));var a=r.list.filter(function(t){return n(t)});return new t(a,this.world,this.parent)},statements:function(e){var r=this.all();"number"==typeof e&&(r=r.get(e));var a=r.list.filter(function(t){return!1===n(t)});return new t(a,this.world,this.parent)},parentheses:function(t){var e=this.match("#Parentheses+");return e=e.splitAfter("#EndBracket"),"number"==typeof t&&(e=e.get(t)),e}};return Object.keys(e).forEach(function(r){t.prototype[r]=e[r]}),t}},{"../subset/sentences/isQuestion":53}],207:[function(t,e,r){"use strict";var n=Object.keys(t("../world/more-data/abbreviations")),a=new RegExp("\\b("+n.join("|")+")[.!?‽⸘‼⁇-⁉] *$","i"),i=/[ .][A-Z]\.? *$/i,o=/(?:\u2026|\.{2,}) *$/,s=/((?:\r?\n|\r)+)/,u=/(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g,l=/[a-z0-9\u0000-\u007F]/i,c=/\S/;e.exports=function(t){t=t||"";var e=[],r=[];if(!(t=String(t))||"string"!=typeof t||!1===c.test(t))return e;for(var n=function(t){for(var e=[],r=t.split(s),n=0;n0&&l.test(d)&&(e.push(d),r[f]="")}return 0===e.length?[t]:e}},{"../world/more-data/abbreviations":216}],208:[function(t,e,r){"use strict";e.exports='{"words":"Comparative¦better|Superlative¦earlier|PresentTense¦sounds|Value¦a few|Noun¦autumn,daylight9eom,here,no doubt,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Copula¦a1is,w0;as,ere;m,re|Condition¦if,unless|PastTense¦be2came,d1had,mea0sa1taken,we0;nt;id;en,gan|Gerund¦accord0be0develop0go0result0stain0;ing|Negative¦n0;ever,o0;!n,t|QuestionWord¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,\'s|Singular¦a06bZcUdQeOfLgKhGici0Ajel07kitty,lFmDnCoBp8question mark,r7s4t1us 0;dollVstW; rex,a1h0ic,ragedy,v show;ere,i07;l03x return;ky,t0uper bowl,yst06;ri04u0;dIff;alZi02oom;a1robl02u0;dCrpo8;rt,tE;cean,thers;othiXumbG;ayfTeeNo0;del,nopoS;iRunch;ead start,o0;lPme1u0;se;! run;adfMirlIlaci8od,rand slam,ulM;amiLly,olLr1un0;diN;iGosD;conomy,gg,ner3v0xampG;ent;eath,inn2o0ragonfG;cument6g0iFlFor;gy;er;an3eiliFhocol2i0ottage,redit card;ty,vil w0;ar;ate;ary;ankiAel7les9o2reakfast,u0;n0tterf6;ti8;dy,tt2y0;fri0;end;le;d1l0noma0;ly; homin2verti0;si0;ng;em|Infinitive¦0:6Y;1:7C;2:7A;3:79;4:5F;5:74;6:6D;7:6L;8:78;9:6W;A:73;B:76;C:6R;D:68;E:7D;F:60;a6Qb69c5Bd4Je43f3Qg3Jh3Ci2Zj2Xk2Tl2Km2Bn28o24p1Pques3Rr0Xs05tWuRvOwHyG;awn,ield;aJe24hist7iIoGre6H;nd0rG;k,ry;n,pe,sh,th0;lk,nHrGsh,tCve;n,raE;d0t;aHiGo8;ew,sA;l6Rry;nHpGr3se;gra4Wli49;dGi8lo65;erGo;go,mi5H;aNeMhKie,oJrHuGwi5;ne,rn;aGe0Ui60u5y;de,in,nsf0p,v5O;r37uC;ank,rG;eat2Vi2;nd,st;ke,lk,rg5Os8;a06c03eZhWi4Jkip,lVmUneTo56pQtJuGwitC;bmAck,ff0gge5ppHrGspe6;ge,pri1rou53vi2;ly,o3D;aLeKoJrHuG;dy,mb7;aDeGi2;ngth2Lss,tC;p,re;m,p;in,ke,r0Yy;iHlaFoil,rinG;g,k7;n,t;ak,e3E;aFe22i7o5B;am,e1Qip;aHiv0oG;ck,ut;re,ve;arCeIle6nHr2tG;!t7;d,se;k,m;aHo4rG;atCew;le,re;il,ve;a05eIisk,oHuG;b,in,le,n,sh;am,ll;a01cZdu9fYgXje6lUmTnt,pQquPsKtJvGwa5V;eGiew,o4U;al,l,rG;se,t;aDi4u42;eJi5oItG;!o4rG;i6uc20;l2rt;mb7nt,r2;e5i4;air,eHlGo40reseE;a9y;at;aDemb0i3Wo2;aHeGi2y;a1nt;te,x;a5Dr4A;act1Yer,le6u1;a12ei2k5PoGyc7;gni2Cnci7rd;ch,li2Bs5N;i1nG;ge,k;aTerSiRlPoNrIuG;b21ll,mp,rGsh,t;cha1s4Q;ai1eJiEoG;cHdu9greBhibAmi1te5vG;e,i2U;eBlaim;di6pa4ss,veE;iEp,rtr43sGur;e,t;a3RuG;g,n3;ck,le;fo32mAsi5;ck,iErt4Mss,u1y;bIccur,ff0pera8utweHverGwe;co47lap,ta3Qu1whelm;igh;ser2taD;eHotG;e,i9;ed,gle6;aLeKiIoHuG;ltip3Frd0;nit14ve;nGrr13;d,g7us;asu4lt,n0Qr3ssa3;intaDke d40na3rHtG;ch,t0;ch,k39ry;aMeLiIoGu1F;aGck,ok,ve;d,n;ft,ke,mAnHstGve;!en;e,k;a2Gc0Ht;b0Qck,uG;gh,nC;eIiHnoG;ck,w;ck,ll,ss;ep;am,oDuG;d3mp;gno4mQnGss3I;cOdica8flu0NhNsKtIvG;eGol2;nt,st;erGrodu9;a6fe4;i5tG;aGru6;ll;abAibA;lu1Fr1D;agi22pG;lemeEo20ro2;aKeIi4oHuG;nt,rry;ld fa5n03pe,st;aGlp;d,t;nd7ppGrm,te;en;aLet,loBoKrIuG;arGeBi14;ant39d;aGip,ow,umb7;b,sp;es,ve1I;in,th0ze;aQeaPiNlLoIracHuncG;ti3I;tu4;cus,lHrG;ce,eca5m,s30;d,l22;aFoG;at,od,w;gu4lGniFx;e,l;r,tu4;il,ll,vG;or;a13cho,dAle6mSnPstNvalua8xG;a0AcLerKi5pGte16;a15eHlaDoGreB;rt,se;ct,riG;en9;ci1t;el,han3;abGima8;liF;ab7couXdHfor9ga3han9j03riCsu4t0vG;isi2Vy;!u4;body,er3pG;hasiGow0;ze;a06eUiMoLrHuG;mp;aIeHiGop;ft;am,ss;g,in;!d3ubt;e,ff0p,re6sHvG;e,iXor9;aJcGli13miBpl18tinguiF;oGuB;uGv0;ra3;gr1YppG;ear,ro2;al,cNem,fLliv0ma0Cny,pKsHterG;mi0D;cribe,er2iHtrG;oy;gn,re;a08e07i6osA;eGi08y;at,ct;iIlHrG;ea1;a4i04;de;ma3n9re,te;a0Ae09h06i8l03oJrGut;aHeGoBuFy;a8dA;ck,ve;llYmSnHok,py,uGv0;gh,nt;cePdu6fMsKtIvG;eGin9;rt,y;aDin0XrG;a5ibu8ol;iGtitu8;d0st;iHoGroE;rm;gu4rm;rn;biKe,foJmaIpG;a4laD;re;nd;rt;ne;ap1e6;aHiGo1;ng,p;im,w;aHeG;at,ck,w;llen3n3r3se;a1nt0;ll,ncHrGt0u1;e,ry;el;aUeQloPoNrKuG;dgIlHrG;n,y;ly;et;aHuF;sh;ke;a5mb,o5rrGth0un9;ow;ck;ar,coSgDlHnefAtrG;ay;ie2ong;in;nGse;!g;band0Jc0Bd06ffo05gr04id,l01mu1nYppTrQsKttGvoid,waA;acIeHra6;ct;m0Fnd;h,k;k,sG;eIiHocia8uG;me;gn,st;mb7rt;le;chHgGri2;ue;!i2;eaJlIroG;aCve;ch;aud,y;l,r;noun9sw0tG;icipa8;ce;lHt0;er;e3ow;ee;rd;aRdIju5mAoR;it;st;!reB;ss;cJhie2knowled3tiva8;te;ge;ve;eIouEu1;se;nt;pt;on|Actor¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt|Honorific¦aObrigadiNcHdGexcellency,fiBking,liDmaAofficNp6queen,r3s0taoiseach,vice5;e0ultJ;c0rgeaC;ond liAretary;abbi,e0;ar0verend; adJ;astFr0;eside6i0ofessE;me ministEnce0;!ss;gistrate,r4yB;eld mar3rst l0;ady,i0;eutena0;nt;shA;oct5utchess;aptain,hance3o0;lonel,mmand4ngress0unci2;m0wom0;an;ll0;or;er;d0yatullah;mir0;al|SportsTeam¦0:1M;1:1T;2:1U;a1Rb1Dc0Zd0Qfc dallas,g0Nhouston 0Mindiana0Ljacksonville jagua0k0Il0Fm02newVoRpKqueens parkJrIsAt5utah jazz,vancouver whitecaps,w3yY;ashington 3est ham0Xh16;natio21redski1wizar12;ampa bay 6e5o3;ronto 3ttenham hotspur;blu1Hrapto0;nnessee tita1xasD;buccanee0ra1G;a7eattle 5heffield0Qporting kansas13t3;. louis 3oke12;c1Srams;mari02s3;eah1IounI;cramento Sn 3;antonio spu0diego 3francisco gi0Bjose earthquak2;char0EpaB;eal salt lake,o04; ran0C;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat2steele0;il3oenix su1;adelphia 3li2;eagl2philNunE;dr2;akland 4klahoma city thunder,r3;i10lando magic;athle0Trai3;de0; 3castle05;england 6orleans 5york 3;city fc,giUje0Lkn02me0Lred bul19y3;anke2;pelica1sain0J;patrio0Irevolut3;ion;aBe9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Rvi3;kings;imberwolv2wi1;re0Cuc0W;dolphi1heat,marli1;mphis grizz3ts;li2;nchester 5r3vN;i3li1;ne0;c00u0H;a4eicesterYos angeles 3;clippe0dodFlaA; galaxy,ke0;ansas city 3nH;chiefs,ro3;ya0M; pace0polis colX;astr0Edynamo,rockeWtexa1;i4olden state warrio0reen bay pac3;ke0;anT;.c.Aallas 7e3i0Cod5;nver 5troit 3;lio1pisto1ti3;ge0;bronc06nuggeO;cowboUmav3;er3;ic06; uX;arCelNh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki2;brow1cavalie0india1;benga03re3;ds;arlotte horCicago 3;b4cubs,fire,wh3;iteE;ea0ulY;di3olina panthe0;ff3naW; c3;ity;altimore ElAoston 7r3uffalo bilT;av2e5ooklyn 3;ne3;ts;we0;cel4red3; sox;tics;ackburn rove0u3;e ja3;ys;rs;ori3rave1;ol2;rizona Ast8tlanta 3;brav2falco1h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls|Uncountable¦0:1C;a1Hb1Bc12e0Wf0Qg0Mh0Gi0Dj0Cknowled1Gl07mYnXoWpRrOsCt8vi7w1;a5ea0Ai4o1;o2rld1;! seI;d,l;ldlife,ne;rmth,t0;neg0Xol08;e3hund0ime,oothpaste,r1una;affRou1;ble,sers,t;a,nnis;aAcene07e9h8il7now,o6p3te2u1;g0Rnshi0L;am,el;ace2e1;ciOed;!c12;ap,cc0ft0B;k,v0;eep,opp0O;riJ;d07fe0Wl1nd;m0Qt;ain,e1i0W;c1laxa0Csearch;ogni0Brea0B;a4e2hys0Elast9o1ress00;rk,w0;a1pp0trol;ce,nR;p0tiK;il,xygen;ews,oi0C;a7ea5i4o3u1;mps,s1;ic;nHo08;lk,st;sl1t;es;chine1il,themat00; learn02ry;aught0e3i2u1;ck,g07;ghtnZqu0CteratI;a1isH;th0;ewel7usti08;ce,mp1nformaOtself;ati1ortan06;en05;a4isto3o1;ck1mework,n1spitali01;ey;ry;ir,lib1ppi9;ut;o2r1um,ymnastJ;a7ound;l1ssip;d,f;i5lour,o2ruit,urnit1;ure;od,rgive1wl;ne1;ss;c6sh;conom9duca5lectriciMn3quip4th9very1;body,o1thB;ne;joy1tertain1;ment;tiC;a8elcius,h4iv3loth6o1urrency;al,ffee,ld w1nfusiAttA;ar;ics;aos,e1;e2w1;ing;se;ke,sh;a3eef,is2lood,read,utt0;er;on;g1ss;ga1;ge;c4dvi3irc2mnes1rt;ty;raft;ce;id|Unit¦0:17;a12b10c0Md0Le0Jf0Fg0Bh08in07joule0k01lZmOnNoMpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Lb,d0Rears old,o1;tt0F;att0b;able4b3e2on1sp;!ne0;a2r0B;!l,sp;spo03; ft,uare 1;c0Gd0Ff3i0Dkilo0Hm1ya0C;e0Kil1;e0li0F;eet0o0B;t,uart0;a3e2i1ou0Nt;c0Knt0;rcent,t00;!scals;hms,uVz;an0GewtR;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;²,³;e1g,z;ct1rtz0;aWogP;al2b,ig9ra1;in0m0;!l1;on0;a3emtOl1tG; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,l,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s|Pronoun¦\'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!\'s|Organization¦0:44;a39b2Qc2Ad22e1Yf1Ug1Mh1Hi1Ej1Ak18l14m0Tn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0You1w0Y;gov,tu2R;a3e1orld trade organizati3Z;lls fargo,st1;fie23inghou17;l1rner br3B;-m12gree30l street journ25m12;an halNeriz3Uisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Qps;es33i1;lev2Wted natio2T; mobi2Jaco bePd bMeAgi frida9h3im horto2Smz,o1witt2V;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen31daily ma2Vguess w2holli0rolling st1Ns1w2;mashing pumpki2Nuprem0;ho;ea1lack eyed pe3Dyrds;ch bo1tl0;ys;l2s1;co,la m13;efoni08us;a6e4ieme2Fnp,o2pice gir5ta1ubaru;rbucks,to2L;ny,undgard1;en;a2Px pisto1;ls;few24insbu25msu1W;.e.m.,adiohead,b6e3oyal 1yan2V;b1dutch she4;ank;/max,aders dige1Ed 1vl30;bu1c1Thot chili peppe2Ilobst27;ll;c,s;ant2Tizno2D;an5bs,e3fiz23hilip morrBi2r1;emier25octer & gamb1Qudenti14;nk floyd,zza hut;psi26tro1uge09;br2Ochina,n2O; 2ason1Wda2E;ld navy,pec,range juli2xf1;am;us;aAb9e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0L;l,s;c,stl3tflix,w1; 1sweek;kids on the block,york09;e,é;a,c;nd1Rs2t1;ional aca2Co,we0P;a,cYd0N;aAcdonald9e5i3lb,o1tv,yspace;b1Knsanto,ody blu0t1;ley crue,or0N;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;\'s,s;c\'s milk,tt11z1V;\'ore08a3e1g,ittle caesa1H;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1H;art;iffy lu0Jo3pmorgan1sa;! cha1;se;hnson & johns1Py d1O;bm,hop,n1tv;g,te1;l,rpol; & m,asbro,ewlett-packaSi3o1sbc,yundai;me dep1n1G;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Gu1;cci,ns n ros0;ldman sachs,o1;dye1g09;ar;axo smith kliYencore;electr0Gm1;oto0S;a3bi,da,edex,i1leetwood mac,oFrito-l08;at,nancial1restoU; tim0;cebook,nnie mae;b04sa,u3xxon1; m1m1;ob0E;!rosceptics;aiml08e5isney,o3u1;nkin donuts,po0Tran dur1;an;j,w j1;on0;a,f leppa2ll,peche mode,r spiegXstiny\'s chi1;ld;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra03;al;ca c5l4m1o08st03;ca2p1;aq;st;dplLgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Fy;dbury,pital o1rl\'s jr;ne;aFbc,eBf9l5mw,ni,o1p,rexiteeV;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roW;ckbuster video,omingda1;le; g1g1;oodriM;cht3e ge0n & jer2rkshire hathaw1;ay;ryG;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bWcRdidQerosmith,ig,lKmEnheuser-busDol,pple9r6s3t&t,v2y1;er;is,on;hland1sociated F; o1;il;by4g2m1;co;os; compu2bee1;\'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c|Demonym¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an|Region¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma|Possessive¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne|Currency¦$,aud,bRcPdKeurJfIgbp,hkd,inr,jpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotyRł;en,uanQ;af,of;h0t5;e0il5;k0q0;elL;iel,oubleKp,upeeK;e2ound st0;er0;lingH;n0soG;ceFn0;ies,y;e0i7;i,mpi6;n,r0wanzaByatB;!onaAw;ori7ranc9t;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s|Country¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d\'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an|City¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg|FemaleName¦0:G0;1:G4;2:FT;3:FF;4:FE;5:ER;6:FU;7:ET;8:GH;9:F1;A:GD;B:E7;C:EI;D:FQ;E:GA;F:FN;G:C8;aE4bD6cB9dAJe9Hf92g8Ih85i7Uj6Wk61l4Pm3An2Vo2Sp2Hqu2Fr1Ps0Rt05ursu7vVwPyMzH;aKeIoH;e,la,ra;lHna;da,ma;da,ra;as7GeIol1UvH;et5onBA;le0sen3;an9endBPhiB5iH;lJnH;if3BniHo0;e,f3A;a,helmi0lHma;a,ow;aNeKiH;cIviH;an9YenG4;kD1tor3;da,l8Wnus,rH;a,nHoniD4;a,iDE;leHnesEF;nDOrH;i1y;aTeQhOiNoKrHu7y4;acG6iHu0F;c3na,sH;h9Nta;nIrH;a,i;i9Kya;a5KffaCIna,s6;al3eHomasi0;a,l8Ho6Zres1;g7Vo6YrIssH;!a,ie;eCi,ri8;bOliNmLnJrIs6tHwa0;ia0um;a,yn;iHya;a,ka,s6;a4e4iHmCCra;!ka;a,t6;at6it6;a06carlet2Ze05hViTkye,oRtNuIyH;bFMlvi1;e,sIzH;an2Uet5ie,y;anHi8;!a,e,nH;aFe;aJeH;fHl3EphH;an2;cFBr73;f3nHphi1;d4ia,ja,ya;er4lv3mon1nHobh76;dy;aLeHirlBNo0y7;ba,e0i7lJrH;iHrBRyl;!d71;ia,lBX;ki4nJrIu0w0yH;la,na;i,leAon,ron;a,da,ia,nHon;a,on;l60re0;bNdMi9lLmJndIrHs6vannaF;aFi0;ra,y;aHi4;nt6ra;lBPome;e,ie;in1ri0;a03eYhWiUoIuH;by,thBM;bRcQlPnOsIwe0xH;an95ie,y;aIeHie,lE;ann8ll1marBHtB;!lHnn1;iHyn;e,nH;a,d7X;da,i,na;an9;hel55io;bin,erByn;a,cHkki,na,ta;helC2ki;ea,iannE0oH;da,n13;an0bJgi0i0nHta,y0;aHee;!e,ta;a,eH;cATkaF;chHe,i0mo0n5FquCGvDy0;aCFelHi9;!e,le;een2iH;a0nn;aNeMhKoJrH;iHudenAX;scil1Uyamva9;lly,rt3;ilome0oebe,ylH;is,lis;arl,ggy,nelope,r7t4;ige,m0Fn4Po7rvaBDtIulH;a,et5in1;ricHsy,tA9;a,e,ia;ctav3deIf86lHph86;a,ga,iv3;l3t5;aReQiKoHy7;eIrH;aFeDma;ll1mi;aLcJkHla,na,s6ta;iHki;!ta;hoB4k8ColH;a,eBJ;!mh;l7Una,risC;dJi5PnIo23taH;li1s6;cy,et5;eAiCQ;a01ckenz2eViLoIrignayani,uriBIyrH;a,na,tAV;i4ll9ZnH;a,iH;ca,ka,qB7;a,chPkaOlKmi,nJrHtzi;aHiam;!n9;a,dy,erva,h,n2;a,dJi9LlH;iHy;cent,e;red;!e7;ae7el3I;ag4LgLi,lIrH;edi62isCyl;an2iHliC;nHsAP;a,da;!an,han;b09c9Gd07e,g05i04l02n00rLtKuIv6TxGyHz2;a,bell,ra;de,rH;a,eD;h77il9t2;a,cTgPiKjor2l6Jn2s6tJyH;!aHbe5RjaAlou;m,n9V;a,ha,i0;!aJbAOeIja,lEna,sHt54;!a,ol,sa;!l07;!h,m,nH;!a,e,n1;arJeIie,oHr3Lueri5;!t;!ry;et3JiB;elHi62y;a,l1;dHon,ue7;akranBy;iHlo97;a,ka,n9;a,re,s2;daHg2;!l2Y;alEd2elHge,isBJon0;eiAin1yn;el,le;a0Je09iXoRuLyH;d3la,nH;!a,dIe9VnHsAT;!a,e9U;a,sAR;aB4cKelJiClIna,pHz;e,iB;a,u;a,la;iHy;a2Ce,l27n9;is,l1IrItt2uH;el7is1;aJeIi8na,rH;aGi8;lei,n1tB;!in1;aRbQd3lMnJsIv3zH;!a,be4Let5z2;a,et5;a,dH;a,sHy;ay,ey,i,y;a,iaJlH;iHy;a8Je;!n4G;b7Verty;!n5T;aOda,e0iMla,nLoJslAUtHx2;iHt2;c3t3;la,nHra;a,ie,o4;a,or1;a,gh,laH;!ni;!h,nH;a,d4e,n4O;cOdon7Ui7kes6na,rNtLurJvIxHy7;mi;ern1in3;a,eHie,yn;l,n;as6is6oH;nya,ya;a,isC;ey,ie,y;a01eWhadija,iOoNrJyH;lHra;a,ee,ie;isHy5D;!tH;a,en,iHy;!e,n48;ri,urtn9C;aNerMl9BmJrHzzy;a,stH;en,in;!berlH;eHi,y;e,y;a,stD;!na,ra;el6QiKlJnIrH;a,i,ri;d4na;ey,i,l9Ss2y;ra,s6;c8Yi5YlPma7nyakumari,rNss5MtKviByH;!e,lH;a,eH;e,i7A;a5FeIhHi3PlEri0y;arGerGie,leDr9Hy;!lyn75;a,en,iHl4Vyn;!ma,n31sC;ei74i,l2;a05eWilUoNuH;anLdKliHstG;aIeHsC;!nAt0W;!n8Z;e,i2Ry;a,iB;!anMcelEd5Wel73han6JlKni,sIva0yH;a,ce;eHie;fi0lEphG;eHie;en,n1;!a,e,n36;!i10lH;!i0Z;anMle0nJrIsH;i5Rsi5R;i,ri;!a,el6Rif1RnH;a,et5iHy;!e,f1P;a,e74iInH;a,e73iH;e,n1;cMd1mi,nIqueliAsmin2Uvie4yAzH;min8;a8eIiH;ce,e,n1s;!lHsCt06;e,le;inIk2lEquelH;in1yn;da,ta;da,lQmOnNo0rMsIvaH;!na;aIiHob6W;do4;!belHdo4;!a,e,l2G;en1i0ma;a,di4es,gr5T;el9ogH;en1;a,eAia0o0se;aNeKilIoHyacin1N;ll2rten1H;a5HdHla5H;a,egard;ath0XiIlHnrietBrmiAst0X;en25ga;di;il78lLnKrHtt2yl78z6G;iHmo4Hri4I;etH;!te;aFnaF;ey,l2;aZeUiPlNold13rJwH;enHyne19;!dolE;acIetHisel9;a,chD;e,ieH;!la;adys,enHor3yn1Z;a,da,na;aKgi,lIna,ov74selH;a,e,le;da,liH;an;!n0;mZnJorgIrH;aldGi,m2Utru76;et5i5W;a,eHna;s1Ovieve;briel3Hil,le,rnet,yle;aSePio0loNrH;anIe9iH;da,e9;!cH;esIiHoi0H;n1s3X;!ca;!rH;a,en45;lIrnH;!an9;ec3ic3;rItiHy8;ma;ah,rah;d0GileDkBl01mVn4DrSsNtMuLvH;aJelIiH;e,ta;in0Byn;!ngelG;geni1la,ni3T;h55ta;meral9peranKtH;eIhHrel7;er;l2Rr;za;iHma,nestGyn;cHka,n;a,ka;eKilJmH;aHie,y;!liA;ee,i1y;lHrald;da,y;aUeSiNlMma,no4oKsJvH;a,iH;na,ra;a,ie;iHuiH;se;a,en,ie,y;a0c3da,nKsHzaI;aHe;!beH;th;!a,or;anor,nH;!a;in1na;en,iHna,wi0;e,th;aXeLiKoHul2W;lor54miniq41n32rHtt2;a,eDis,la,othHthy;ea,y;an0AnaFonAx2;anQbPde,eOiMja,lJmetr3nHsir4X;a,iH;ce,se;a,iIla,orHphiA;es,is;a,l5M;dHrdH;re;!d4Pna;!b2EoraFra;a,d4nH;!a,e;hl3i0mNnLphn1rIvi1YyH;le,na;a,by,cIia,lH;a,en1;ey,ie;a,et5iH;!ca,el1Cka;arHia;is;a0Se0Oh06i04lWoKrIynH;di,th3;istHy06;al,i0;lQnNrIurH;tn1F;aKdJiHnJriA;!nH;a,e,n1;el3;!l1T;n2sH;tanHuelo;ce,za;eHleD;en,t5;aJeoIotH;il4D;!pat4;ir8rJudH;et5iH;a,ne;a,e,iH;ce,sY;a4er4ndH;i,y;aQeNloe,rH;isIyH;stal;sy,tH;aIen,iHy;!an1e,n1;!l;lseIrH;!i8yl;a,y;nMrH;isKlImH;aiA;a,eHot5;n1t5;!sa;d4el1RtH;al,el1Q;cIlH;es5i3H;el3ilH;e,ia,y;iZlYmilXndWrOsMtHy7;aKeJhHri0;erGleDrEy;in1;ri0;li0ri0;a2IsH;a2Hie;a,iNlLmeJolIrH;ie,ol;!e,in1yn;lHn;!a,la;a,eHie,y;ne,y;na,sC;a0Ei0E;a,e,l1;isBl2;tlH;in,yn;arb0DeZianYlWoUrH;andSeQiJoIyH;an0nn;nwEok8;an2PdgLg0KtH;n29tH;!aInH;ey,i,y;ny;etH;!t8;an0e,nH;da,na;i8y;bbi8nH;iBn2;ancHossom,ythe;a,he;ca;aScky,lin9niBrOssNtJulaFvH;!erlH;ey,y;hIsy,tH;e,i11y8;!anH;ie,y;!ie;nHt6yl;adIiH;ce;et5iA;!triH;ce,z;a4ie,ra;aliy2Bb26d1Ng1Ji1Bl0Um0Pn03rYsPthe0uLvJyH;anHes6;a,na;a,eHr27;ry;drJgusIrH;el3o4;ti0;a,ey,i,y;hItrH;id;aLlHt1Q;eIi8yH;!n;e,iHy;gh;!nH;ti;iJleIpiB;ta;en,n1t5;an1AelH;le;aZdXeVgRiPja,nItoHya;inet5n3;!aKeIiHmJ;e,ka;!mHt5;ar2;!belIliCmU;sa;!le;ka,sHta;a,sa;elHie;a,iH;a,ca,n1qH;ue;!t5;te;je7rea;la;!bImHstas3;ar3;el;aJberIel3iHy;e,na;!ly;l3n9;da;aUba,eOiLlJma,ta,yH;a,c3sH;a,on,sa;iHys0K;e,s0J;a,cIna,sHza;a,ha,on,sa;e,ia;c3is6jaJna,ssaJxH;aHia;!nd4;nd4;ra;ia;i0nIyH;ah,na;a,is,naF;c6da,leDmMnslLsH;haFlH;inHyX;g,n;!h;ey;ee;en;at6g2nH;es;ie;ha;aWdiTelMrH;eJiH;anMenH;a,e,ne;an0;na;aLeKiIyH;nn;a,n1;a,e;!ne;!iH;de;e,lEsH;on;yn;!lH;iAyn;ne;agaKbIiH;!gaJ;ey,i8y;!e;il;ah|Place¦aMbKcIdHeFfEgBhAi9jfk,kul,l7m5new eng4ord,p2s1the 0upJyyz;bronx,hamptons;fo,oho,under2yd;acifMek,h0;l,x;land;a0co,idDuc;libu,nhattK;a0gw,hr;s,x;ax,cn,ndianGst;arlem,kg,nd;ay village,re0;at 0enwich;britain,lak2;co,ra;urope,verglad0;es;en,fw,own1xb;dg,gk,hina0lt;town;cn,e0kk,rooklyn;l air,verly hills;frica,m5ntar1r1sia,tl0;!ant1;ct0;ic0; oce0;an;ericas,s|Person¦a01bZcTdQeOfMgJhHinez,jFkEleDmAnettPo9p7r4s3t2uncle,v0womL;a0irgin maH;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussaQcarlett johanssRistZlobodan milosevic,omeone,tepGuC;ay romano,eese witherspoQo1ush limbau0;gh;d stewart,naldinho,sario;a0ipV;lmUris hiltM;prah winfrOra;an,essiaen,itt romnNo0ubarek;m0thR;!my;bron james,e;anye west,iefer sutherland,obe bryaN;aime,effersFk rowli0;ng;alle ber0ulk hog3;ry;astBentlem1irl,rand0uy;fa2mo2;an;a0ella;thF;ff0meril lagasse,zekiel;ie;a0enzel washingt4ick wolf,ude;d0lt3nte;!dy;ar2lint1ous0ruz;in;on;dinal wols1son0;! palm5;ey;arack obama,oy,ro0;!ck,th2;dolf hitl1shton kutch1u0;nt;er|WeekDay¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s|Date¦autumn,daylight9eom,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Time¦a6breakfast 5dinner5e3lunch5m2n0oclock,some5to7;i7o0;on,w;id4or1;od,ve0;ning;time;fternoon,go,ll day,t 0;ni0;ght|Holiday¦0:1Q;1:1P;a1Fb1Bc12d0Ye0Of0Kg0Hh0Di09june07kwanzaa,l04m00nYoVpRrPsFt9v6w4xm03y2;om 2ule;hasho16kippur;hit2int0Xomens equalit8; 0Ss0T;alentines3e2ictor1E;r1Bteran1;! 0;-0ax 0h6isha bav,rinityMu2; b3rke2;y 0;ish2she2;vat;a0Xe prophets birth0;a6eptember14h4imchat tor0Ut 3u2;kk4mmer T;a8p7s6valentines day ;avu2mini atzeret;ot;int 2mhain;a4p3s2valentine1;tephen1;atrick1;ndrew1;amadan,ememberanc0Yos2;a park1h hashana;a3entecost,reside0Zur2;im,ple heart 0;lm2ssovE; s04;rthodox 2stara;christma1easter2goOhoJn0C;! m07;ational 2ew years09;freedom 0nurse1;a2emorial 0lHoOuharram;bMr2undy thurs0;ch0Hdi gr2tin luther k0B;as;a2itRughnassadh;bour 0g baom2ilat al-qadr;er; 2teenth;soliU;d aJmbolc,n2sra and miraj;augurGd2;ependen2igenous people1;c0Bt1;a3o2;ly satur0;lloween,nukkUrvey mil2;k 0;o3r2;ito de dolores,oundhoW;odW;a4east of 2;our lady of guadalupe,the immaculate concepti2;on;ther1;aster8id 3lectYmancip2piphany;atX;al-3u2;l-f3;ad3f2;itr;ha;! 2;m8s2;un0;ay of the dead,ecemb3i2;a de muertos,eciseis de septiembre,wali;er sol2;stice;anad8h4inco de mayo,o3yber m2;on0;lumbu1mmonwealth 0rpus christi;anuk4inese n3ristmas2;! N;ew year;ah;a 0ian tha2;nksgiving;astillCeltaine,lack4ox2;in2;g 0; fri0;dvent,ll 9pril fools,rmistic8s6u2;stral4tum2;nal2; equinox;ia 0;cens2h wednes0sumption of mary;ion 0;e 0;hallows 6s2;ai2oul1t1;nt1;s 0;day;eve|Month¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il|Duration¦centur4d2hour3m0seconds,week3year3;i0onth2;llisecond1nute1;ay0ecade0;!s;ies,y|FirstName¦aEblair,cCdevBj8k6lashawn,m3nelly,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0;ls7nyatta,rry;am0ess1;ie,m0;ie;an,on;as0heyenne;ey,sidy;lexis,ndra,ubr0;ey|LastName¦0:35;1:3A;2:3C;3:2Z;4:2F;a3Bb31c2Od2Ee2Bf25g1Zh1Oi1Jj1Dk16l0Ym0Mn0Io0Fp04rXsLtGvEwBxAy7zh5;a5ou,u;ng,o;a5eun2Uoshi1Jun;ma5ng;da,guc1Zmo27sh21zaQ;iao,u;a6eb0il5o3right,u;li3Bs1;gn0lk0ng,tanabe;a5ivaldi;ssilj37zqu2;a8h7i2Go6r5sui,urn0;an,ynisI;lst0Orr1Uth;at1Uomps1;kah0Unaka,ylor;aDchCeBhimizu,iAmi9o8t6u5zabo;ar2lliv2AzuD;a5ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n6sa5to;ki;ch2dKtos,z;amAeag1Zi8o6u5;bio,iz,sC;b5dri1MgHj0Sme24osevelt,sZux;erts,ins1;c5ve0E;ci,hards1;ir2os;aDe9h7ic5ow20;as5hl0;so;a5illips;m,n1T;ders20et7r6t5;e0Nr4;ez,ry;ers;h21rk0t5vl4;el,te0J;baAg0Alivei00r5;t5w1O;ega,iz;a5eils1guy1Rix1owak,ym1E;gy,ka5var1K;ji5muV;ma;aDeBiAo7u5;ll0n5rr0Bssolini,ñ5;oz;lina,oJr5zart;al0Me5r0U;au,no;hhail4ll0;rci0s5y0;si;eVmmad4r5tsu07;in5tin2;!o;aBe7i5op2uo;!n5u;coln,dholm;fe6n0Qr5w0J;oy;bv5v5;re;mmy,rs14u;aAennedy,imu9le0Lo7u6wo5;k,n;mar,znets4;bay5vacs;asY;ra;hn,rl8to,ur,zl4;a9en8ha3imen2o5u3;h5nYu3;an5ns1;ss1;ki0Es0S;cks1nsse0D;glesi8ke7noue,shik6to,vano5;u,v;awa;da;as;aBe8it7o6u5;!a3b0ghNynh;a3ffmann,rvat;chcock,l0;mingw6nde5rM;rs1;ay;ns0ErrPs6y5;asCes;an4hi5;moI;a8il,o7r6u5;o,tierr2;ayli3ub0;m2nzal2;nd5o,rcia;hi;er9is8lor7o6uj5;ita;st0urni0;es;ch0;nand2;d6insteGsposi5vaK;to;is1wards;aBeAi8omin7u5;bo5rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw6vi5;es,s;in;aEhAlark9o5;hKl5op0rbyn,x;em6li5;ns;an;!e;an7e6iu,o5ristensFu3we;i,ng,u3w,y;!n,on5u3;!g;mpb6rt0st5;ro;ell;aAe7ha3lanco,oyko,r5yrne;ooks,yant;ng;ck6ethov5nnett;en;er,ham;ch,h7iley,rn5;es,i0;er;k,ng;dCl8nd5;ers5r9;en,on,s1;on;eks6iy7var2;ez;ej5;ev;ams|MaleName¦0:CE;1:BK;2:C2;3:BS;4:B4;5:BZ;6:AT;7:9V;8:BC;9:AW;A:AO;B:8W;aB5bA9c98d88e7Hf6Zg6Hh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt07u06v01wOxavi3yHzC;aCor0;cCh8Jne;hDkC;!a5Z;ar51e5Y;ass2i,oDuC;sEu25;nFsEusC;oCsD;uf;ef;at0g;aKeIiDoCyaAQ;lfgang,odrow;lCn1O;bEey,frBJlC;aA6iC;am,e,s;e8Aur;i,nde7sC;!l6t1;de,lDrr5yC;l1ne;lCt3;a94y;aFern1iC;cDha0nceCrg9Cva0;!nt;ente,t5B;lentin49n8Zughn;lyss4Msm0;aTeOhLiJoFrDyC;!l3ro8s1;av9ReCist0oy,um0;nt9Jv55y;bEd7YmCny;!as,mCoharu;aAYie,y;iBy;mCt9;!my,othy;adDeoCia7EomB;!do7O;!de9;dFrC;en8JrC;an8IeCy;ll,n8H;!dy;dgh,ic9Unn3req,ts46;aScotQeOhKiIoGpenc3tCur1Pylve8Jzym1;anEeCua7D;f0phAGvCwa7C;e59ie;!islaw,l6;lom1nA4uC;leyma8ta;dClBm1;!n6;aEeC;lCrm0;d1t1;h6Une,qu0Vun,wn,y8;aCbasti0k1Yl42rg41th,ymo9J;m9n;!tC;!ie,y;lDmCnti22q4Kul;!mAu4;ik,vato6X;aXeThe94iPoGuDyC;an,ou;b6NdDf9pe6SssC;!elAK;ol2Vy;an,bJcIdHel,geGh0landA4mFnEry,sDyC;!ce;coe,s;!a96nA;an,eo;l3Kr;e4Sg3n6oA5ri6A;co,ky;bAe9V;cCl6;ar5Qc5PhDkCo;!ey,ie,y;a87ie;gDid,ub5x,yCza;ansh,nT;g8XiC;na8Ts;ch60fa4lEmDndCpha4sh6Wul,ymo72;alA0ol2Cy;i9Jon;f,ph;ent2inC;cy,t1;aGeEhilDier64ol,reC;st1;!ip,lip;d9Crcy,tC;ar,e2W;b3Udra6Ht46ul;ctav2Wliv3m97rGsDtCum8Vw5;is,to;aDc8TvC;al54;ma;i,l4BvK;athKeIiEoC;aCel,l0ma0r2Y;h,m;cDg4i3KkC;h6Wola;holBkColB;!olB;al,d,il,ls1vC;il52;anCy;!a4i4;aXeUiLoGuDyC;l22r1;hamDr61staC;fa,p4I;ed,mG;dibo,e,hamEis1YntDsCussa;es,he;e,y;ad,ed,mC;ad,ed;cHgu4kFlEnDtchC;!e7;a7Aik;o04t1;e,olC;aj;ah,hCk6;a4eC;al,l;hDlv2rC;le,ri7v2;di,met;ck,hOlMmPnu4rIs1tEuricDxC;!imilian87we7;e,io;eo,hDiBtC;!eo,hew,ia;eCis;us,w;cEio,k81lDqu6Isha7tCv2;i2Jy;in,on;!el,oLus;achCcolm,ik;ai,y;amCdi,moud;adC;ou;aSeOiNlo2ToJuDyC;le,nd1;cFiEkCth3;aCe;!s;gi,s;as,iaC;no;g0nn6SrenEuCwe7;!iC;e,s;!zo;am,on4;a7Cevi,la4UnEoCst3vi;!nC;!a62el;!ny;mDnCr16ur4Vwr4V;ce,d1;ar,o4P;aJeEhaled,iCrist4Xu4Ay3D;er0p,rC;by,k,ollos;en0iFnCrmit,v2;!dDnCt5E;e10y;a7ri4P;r,th;na69rCthem;im,l;aZeRiPoEuC;an,liCst2;an,o,us;aqu2eKhnJnHrFsC;eDhCi7Due;!ua;!ph;dCge;an,i,on;!aCny;h,s,th4Z;!ath4Yie,nA;!l,sCy;ph;an,e,mC;!mA;d,ffHrEsC;sCus;!e;a5KemDmai8oCry;me,ni0Q;i6Wy;!e07rC;ey,y;cId5kHmGrEsDvi3yC;!d5s1;on,p3;ed,od,rCv4O;e51od;al,es,is1;e,ob,ub;k,ob,quC;es;aObrahNchika,gLkeKlija,nuJrHsEtCv0;ai,sC;uki;aCha0i6Hma4sac;ac,iaC;h,s;a,vinCw2;!g;k,nngu53;!r;nacCor;io;im;in,n;aLeGina4WoEuCyd57;be27gCmber4EsE;h,o;m3ra35sCwa3Z;se2;aFctEitEnDrC;be22m0;ry;or;th;bLlKmza,nJo,rEsDyC;a44d5;an,s0;lFo4FrEuCv6;hi41ki,tC;a,o;is1y;an,ey;k,s;!im;ib;aReNiMlenLoJrFuC;illerDsC;!tavo;mo;aEegCov3;!g,orC;io,y;dy,h58nt;nzaCrd1;lo;!n;lbe4Qno,ovan4S;ne,oErC;aCry;ld,rd4O;ffr6rge;bri4l5rCv2;la20r3Fth,y;aSeOiMlKorr0JrC;anEedCitz;!dAeCri25;ri24;cEkC;!ie,lC;in,yn;esKisC;!co,zek;etch3oC;yd;d4lConn;ip;deriEliDng,rnC;an02;pe,x;co;bi0di;ar00dVfrUit0lOmHnGo2rDsteb0th0uge8vCym5zra;an,ere2W;gi,iDnCrol,v2w2;est3Zie;c08k;och,rique,zo;aHerGiDmC;aGe2Q;lDrC;!h0;!io;s1y;nu4;be0Ad1iFliEmDt1viCwood;n,s;er,o;ot1Us;!as,j44sC;ha;a2en;!dAg32mFuDwC;a26in;arC;do;o0Tu0T;l,nC;est;aZePiMoFrEuDwCyl0;ay8ight;a8dl6nc0st2;ag0ew;minGnEri0ugDyC;le;!lB;!a29nCov0;e7ie,y;go,icC;!k;armuDeCll1on,rk;go;id;anJj0lbeImetri9nGon,rFsEvDwCxt3;ay8ey;en,in;hawn,mo09;ek,ri0G;is,nCv3;is,y;rt;!dC;re;lLmJnIrEvC;e,iC;!d;en,iEne7rCyl;eCin,yl;l2Wn;n,o,us;!e,i4ny;iCon;an,en,on;e,lB;as;a07e05hXiar0lMoHrFuDyrC;il,us;rtC;!is;aCistobal;ig;dy,lFnDrC;ey,neli9y;or,rC;ad;by,e,in,l2t1;aHeEiCyJ;fCnt;fo0Dt1;meDt9velaC;nd;nt;rEuDyC;!t1;de;enC;ce;aGeFrisDuC;ck;!tC;i0oph3;st3;d,rlCs;eCie;s,y;cCdric,s11;il;lFmer1rC;ey,lDro7y;ll;!os,t1;eb,v2;ar03eVilUlaToQrDuCyr1;ddy,rtJ;aKeFiEuDyC;an,ce,on;ce,no;an,ce;nDtC;!t;dDtC;!on;an,on;dDndC;en,on;!foCl6y;rd;bDrCyd;is;!by;i8ke;al,lA;nGrCshoi;at,nDtC;!r11;aCie;rd0M;!edict,iDjam2nA;ie,y;to;n6rCt;eCy;tt;ey;ar0Yb0Od0Kgust2hm0Hid5ja0FlZmXnPputsiOrFsaEuCya0ziz;gust9st2;us;hi;aJchIi4jun,maGnEon,tCy0;hCu07;ur;av,oC;ld;an,nd05;el;ie;ta;aq;dHgel00tC;hoFoC;i8nC;!iXy;ne;ny;reCy;!as,s,w;ir,mCos;ar;an,bePd5eJfGi,lFonEphonIt1vC;aNin;on;so,zo;an,en;onDrC;edK;so;c,jaFksandEssaFxC;!and3;er;ar,er;ndC;ro;rtC;!o;ni;en;ad,eC;d,t;in;aDoCri0vik;lfo;mCn;!a;dGeFraDuC;!bakr,lfazl;hCm;am;!l;allFel,oulaye,ulC;!lDrahm0;an;ah,o;ah;av,on|Verb¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en|PhrasalVerb¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut|Modal¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld|Adjective¦0:73;1:7I;2:7O;3:7H;4:7A;5:5A;6:47;7:48;8:4Q;9:5Z;A:7F;B:6X;C:5V;D:6Y;E:71;a6Hb63c5Pd55e4Rf48g40h3Pi34j32k31l2Qm2Fn26o1Qp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6A;d6Czy;despr73s5E;!sa7;eGlFste25;co1Hl o4J;!k5;aGiFola4A;b7Rce versa,ol53;ca2gabo61nilla;ltWnJpGrb58su4tterF;!moB; f33b1NpGsFti1G;ca7et,ide dMtairs;er,i3M;aPbeco6Pconvin26deMeLfair,ivers4knKprecedYrIsGwF;iel1Zritt5X;i1UuF;pervis0specti3;eFu5;cognLgul6Fl6F;own;ndi3v5Rxpect0;cid0rF;!grou5MsF;iz0tood;b7ppeaLssu6EuthorF;iz0;i23ra;aJeHhough4NoGrF;i1oubl0;geth8p,rpD;en5OlFm4Yrr2Tst0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3DoPpOqueami3DtJuFymb62;bHi gener53pFrprisi3;erFre0K;! dup8b,i28;du0seq4S;anda6SeIi0OrFy37;aightFip0; fFfF;or59;adfaBreotyp0;aCec2Fir1IlendDot on; call0le,mb8phist1WrFu0Wvi40;dDry;gnifica2nF;ceCg7;am2Oe8ocki3ut;cFda1em5lfi2Xni1Vpa67re6;o1Fr3U;at56ient27reec56;cr0me,ns serif;aMeIiGoF;buBtt4SuSy4;ghtFv4;!-28f9;ar,bel,condi1du61fres50lHpublic3UsFtard0;is46oF;lu1na2;e1Duc44;bDciF;al,st;aPeNicayu6lacDopuliBrGuF;bl58mp0;eJiGoF;!b09fuEmi30p8;mGor,sFva1;ti6;a4Ue;ciEmF;a0Hi5I;ac20rFti1;feAma2Tplexi3v33;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Lsi45;en,posi1; boa5Fg2Jli6;!ay; gua5DbFli6;eat;eHsF;cFer0Hole1;e6uC;d2Sse;ak0eMiLoFua4O;nJrGtF;ab7;thF;!eF;rn;chala2descri4Zstop;ght5;arby,cessa3Wighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuC;di4EnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abCho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3C;!-0C;nguDst,tt8;ap1Sind5no0A;agg0uF;niOstifi0veni7;de4gno4Blleg4mSnHpso 1VrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenEoxF;ic36;a6i2R;a1er,oce2;iGoF;or;reA;deq3Jppr2Y;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0Q;d2QnE;aKelJiHoFumdr3B;neBok0rrFs07ur5;if2S;ghfalut1OspF;an2Q;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Jiga22lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Dob4;aUeOinNlMoHrF;a1TeFoz1K;e2Dq12tf9;oHrF; keeps,eFm8tuna1;g04ign;liF;sh;ag2Zue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lEr Fux,vori1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiC;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erE;creHeas0gruntl0honeBordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarClJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraDg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainBgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerE;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt|Comparable¦0:41;1:4I;2:45;3:4B;4:2Y;5:3X;a4Ob44c3Od3De35f2Rg2Fh24i1Vj1Uk1Rl1Im1Cn16o14p0Tqu0Rr0IsRtKuIvFw7y6za12;ell27ou3;aBe9hi1Yi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Mt;k,ry;n1Tr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Mse5;like0ti1;aAen9hi8i7ough,r6;anqu2Qen1ue;dy,g3Ume0ny,r09;ck,n,rs2R;d42se;ll,me,rt,s6wd47;te5;aVcarUeThRiQkin0GlMmKoHpGqua1HtAu7w6;eet,ift;b7dd15per0Hr6;e,re2J;sta2Ht4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Hn0W;a1ep,rn;le,rk;e24i3Hright0;ci2Aft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g37m6;!y;ek,nd3F;ck,l0mp4;a6iUort,rill,y;dy,ll0Zrp;cu0Tve0Txy;ce,ed,y;d,fe,int0l1Xv16;aBe9i8o6ude;mantic,o1Ksy,u6;gh,nd;ch,pe,tzy;a6d,mo0J;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aFhoEi1SlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fou00ud;ey,k0;li06or,te1D;a6easa2;in,nt;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd|Adverb¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori|Expression¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;\'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la|Preposition¦\'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;\',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;\',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut|Conjunction¦aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh|Determiner¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er","conjugations":"t:ake,ook,,,aken|:can,could,can,_|free:_,,,ing|puk:e,,,ing|ar:ise,ose,,,isen|babys:it,at|:be,was,is,am,been|:is,was,is,being|beat:_,,,ing,en|beg:in,an,,inning,un|ban:_,ned,,ning|bet:_,,,,_|bit:e,_,,ing,ten|ble:ed,d,,,d|bre:ed,d|br:ing,ought,,,ought|broadcast:_,_|buil:d,t,,,t|b:uy,ought,,,ought|cho:ose,se,,osing,sen|cost:_,_|deal:_,t,,,t|d:ie,ied,,ying|d:ig,ug,,igging,ug|dr:aw,ew,,,awn|dr:ink,ank,,,unk|dr:ive,ove,,iving,iven|:eat,ate,,eating,eaten|f:all,ell,,,allen|fe:ed,d,,,d|fe:el,lt|f:ight,ought,,,ought|f:ind,ound|fl:y,ew,,,own|bl:ow,ew,,,own|forb:id,ade|edit:_,,,ing|forg:et,ot,,eting,otten|forg:ive,ave,,iving,iven|fr:eeze,oze,,eezing,ozen|g:et,ot|g:ive,ave,,iving,iven|:go,went,goes,,gone|h:ang,ung,,,ung|ha:ve,d,s,ving,d|hear:_,d,,,d|hid:e,_,,,den|h:old,eld,,,eld|hurt:_,_,,,_|la:y,id,,,id|le:ad,d,,,d|le:ave,ft,,,ft|l:ie,ay,,ying|li:ght,t,,,t|los:e,t,,ing|ma:ke,de,,,de|mean:_,t,,,t|me:et,t,,eting,t|pa:y,id,,,id|read:_,_,,,_|r:ing,ang,,,ung|r:ise,ose,,ising,isen|r:un,an,,unning,un|sa:y,id,ys,,id|s:ee,aw,,eeing,een|s:ell,old,,,old|sh:ine,one,,,one|sho:ot,t,,,t|show:_,ed|s:ing,ang,,,ung|s:ink,ank|s:it,at|slid:e,_,,,_|sp:eak,oke,,,oken|sp:in,un,,inning,un|st:and,ood|st:eal,ole|st:ick,uck|st:ing,ung|:stream,,,,|str:ike,uck,,iking|sw:ear,ore|sw:im,am,,imming|sw:ing,ung|t:each,aught,eaches|t:ear,ore|t:ell,old|th:ink,ought|underst:and,ood|w:ake,oke|w:ear,ore|w:in,on,,inning|withdr:aw,ew|wr:ite,ote,,iting,itten|t:ie,ied,,ying|ski:_,ied|:boil,,,,|miss:_,,_|:act,,,,|compet:e,ed,,ing|:being,were,are,are|impl:y,ied,ies|ic:e,ed,,ing|develop:_,ed,,ing|wait:_,ed,,ing|aim:_,ed,,ing|spil:l,t,,,led|drop:_,ped,,ping|log:_,ged,,ging|rub:_,bed,,bing|smash:_,,es|egg:_,ed|suit:_,ed,,ing|age:_,d,s,ing|shed:_,_,s,ding|br:eak,oke|ca:tch,ught|d:o,id,oes|b:ind,ound|spread:_,_|become:_,,,,_|ben:d,,,,t|br:ake,,,,oken|burn:_,,,,ed|burst:_,,,,_|cl:ing,,,,ung|c:ome,ame,,,ome|cre:ep,,,,pt|cut:_,,,,_|dive:_,,,,d|dream:_,,,,t|fle:e,,,eing,d|fl:ing,,,,ung|got:_,,,,ten|grow:_,,,,n|hit:_,,,,_|ke:ep,,,,pt|kne:el,,,,lt|know:_,,,,n|leap:_,,,,t|len:d,,,,t|lo:ose,,,,st|prove:_,,,,n|put:_,,,,_|quit:_,,,,_|rid:e,,,,den|s:eek,,,,ought|sen:d,,,,t|set:_,,,,_|sew:_,,,,n|shake:_,,,,n|shave:_,,,,d|shut:_,,,,_|s:eat,,,,at|sla:y,,,,in|sle:ep,,,,pt|sn:eak,,,,uck|spe:ed,,,,d|spen:d,,,,t|sp:it,,,,at|split:_,,,,_|spr:ing,,,,ung|st:ink,unk,,,unk|strew:_,,,,n|sw:are,,,,orn|swe:ep,,,,pt|thrive:_,,,,d|undergo:_,,,,ne|upset:_,,,,_|w:eave,,,,oven|we:ep,,,,pt|w:ind,,,,ound|wr:ing,,,,ung","plurals":"addend|um|a,alga|e,alumna|e,alumn|us|i,appendi|x|ces,avocado|s,bacill|us|i,barracks|,beau|x,bus|es,cact|us|i,chateau|x,analys|is|es,diagnos|is|es,parenthes|is|es,prognos|is|es,synops|is|es,thes|is|es,child|ren,circus|es,clothes|,corp|us|ora,criteri|on|a,curricul|um|a,database|s,deer|,echo|es,embargo|es,epoch|s,f|oot|eet,gen|us|era,g|oose|eese,halo|s,hippopotam|us|i,ind|ex|ices,larva|e,lea|f|ves,librett|o|i,loa|f|ves,m|an|en,matri|x|ces,memorand|um|a,modul|us|i,mosquito|es,move|s,op|us|era,ov|um|a,ox|en,pe|rson|ople,phenomen|on|a,quiz|zes,radi|us|i,referend|um|a,rodeo|s,sex|es,shoe|s,sombrero|s,stomach|s,syllab|us|i,tableau|x,thie|f|ves,t|ooth|eeth,tornado|s,tuxedo|s,zero|s","patterns":{"Person":["master of #Noun","captain of the #Noun"]},"regex":{"HashTag":["^#[a-z]+"],"Gerund":["^[a-z]+n[\'’]$"],"PhoneNumber":["^[0-9]{3}-[0-9]{4}$","^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$"],"Time":["^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$","^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$","^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$","^[PMCE]ST$","^utc ?[+-]?[0-9]+?$","^[a-z0-9]*? o\'?clock$"],"Date":["^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$","^[0-9]{1,4}/[0-9]{1,2}/[0-9]{1,4}$"],"Money":["^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?$","^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$"],"Value":["^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?$","^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$","^[0-9.]{1,2}[-–][0-9]{1,2}$"],"NumberRange":["^[0-9.]{1,4}(st|nd|rd|th)?[-–][0-9.]{1,4}(st|nd|rd|th)?$","^[0-9.]{1,2}[-–][0-9]{1,2}$"],"NiceNumber":["^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$"],"NumericValue":["^[-+]?[0-9]+(.[0-9]+)?$","^.?[0-9]+([0-9,.]+)?%$"],"Percent":["^.?[0-9]+([0-9,.]+)?%$"],"Cardinal":["^.?[0-9]+([0-9,.]+)?%$"],"Fraction":["^[0-9]{1,4}/[0-9]{1,4}$"],"LastName":["^ma?c\'.*","^o\'[drlkn].*"]}}'},{}],209:[function(t,e,r){"use strict";var n=t("../subset/verbs/methods/conjugate/faster.js");e.exports=function(t){var e=this;return Object.keys(t).forEach(function(r){e.conjugations[r]=e.conjugations[r]||{},e.words[r]=e.words[r]||"Infinitive",Object.keys(t[r]).forEach(function(n){var a=t[r][n];e.conjugations[r][n]=a,e.words[a]=e.words[a]||n,e.cache.toInfinitive[t[r][n]]=r});var a=n(r,e);Object.keys(a).forEach(function(t){var r=a[t];!1===e.words.hasOwnProperty(r)&&(e.words[r]=t)})}),t}},{"../subset/verbs/methods/conjugate/faster.js":79}],210:[function(t,e,r){"use strict";e.exports=function(t){var e=this;return Object.keys(t).forEach(function(r){e.patterns[r]=t[r]}),t}},{}],211:[function(t,e,r){"use strict";e.exports=function(t){var e=this;return Object.keys(t).forEach(function(r){var n=t[r];e.plurals[r]=n,e.words[n]=e.words[n]||"Plural",e.words[r]=e.words[r]||"Singular",e.cache.toSingular[n]=r}),t}},{}],212:[function(t,e,r){"use strict";e.exports=function(t){var e=this;Object.keys(t).forEach(function(r){e.regex.push({reg:new RegExp(r,"i"),tag:t[r]})})}},{}],213:[function(t,e,r){"use strict";var n=t("../tags/addDownward");e.exports=function(t){var e=this;return Object.keys(t).forEach(function(r){var n=t[r];n.notA=n.notA||[],n.downward=n.downward||[],e.tags[r]=n}),n(this.tags),t}},{"../tags/addDownward":135}],214:[function(t,e,r){"use strict";var n=t("../term/methods/normalize/normalize").normalize,a=t("../subset/nouns/methods/pluralize"),i=t("../subset/verbs/methods/conjugate/faster.js"),o=t("../subset/adjectives/methods"),s=/ /;e.exports=function(t){var e=this;return Object.keys(t).forEach(function(r){var u=t[r];if(r=n(r).replace(/\s+/," ").replace(/[.\?,;\!]/g,""),e.words[r]=u,!0===s.test(r)){var l=r.split(s);e.cache.firstWords[l[0]]=!0}if("Singular"!==u)if("Infinitive"!==u)if("PhrasalVerb"!==u){if("Comparable"===u){var c=o.toComparative(r);c&&r!==c&&(e.words[c]="Comparative");var h=o.toSuperlative(r);h&&r!==h&&(e.words[h]="Superlative")}}else{var m=r.split(/ /),f=i(m[0],e);Object.keys(f).forEach(function(t){var r=f[t]+" "+m[1];e.words[r]="PhrasalVerb",e.cache.firstWords[f[t]]=!0})}else{var d=i(r,e);Object.keys(d).forEach(function(t){e.words[d[t]]=t})}else{var p=a(r,{});p&&p!==r&&(e.words[p]="Plural")}}),t}},{"../subset/adjectives/methods":11,"../subset/nouns/methods/pluralize":44,"../subset/verbs/methods/conjugate/faster.js":79,"../term/methods/normalize/normalize":149}],215:[function(t,e,r){"use strict";var n=t("../fns"),a=t("./_data"),i=t("./more-data"),o=t("../tags"),s=t("./unpack"),u=t("./addTags"),l=t("./addWords"),c=t("./addRegex"),h=t("./addConjugations"),m=t("./addPatterns"),f=t("./addPlurals"),d=t("./more-data/misc"),p=function(t,e){for(var r=Object.keys(e),n=0;nr[t].lineage.length?1:r[e].isA.length>r[t].isA.length?-1:0:0:1}))},M={text:!0,tags:!0,implicit:!0,clean:!1,id:!1,index:!1,offset:!1,whitespace:!1,bestTag:!1},S={json:function(e,t){e=e||{};var n={};return(e=Object.assign({},M,e)).text&&(n.text=this.text),e.normal&&(n.normal=this.normal),e.tags&&(n.tags=Object.keys(this.tags)),e.clean&&(n.clean=this.clean),(e.id||e.offset)&&(n.id=this.id),e.implicit&&null!==this.implicit&&(n.implicit=this.implicit),e.whitespace&&(n.pre=this.pre,n.post=this.post),e.bestTag&&(n.bestTag=I(this,t)[0]),n}},L=Object.assign({},F,N,O,z,S),J=function(e,t){for(e=e.toString();e.length0&&void 0!==arguments[0]?arguments[0]:"";t(this,e),n=String(n);var r=E(n);this.text=r.text||"",this.clean=r.clean,this.reduced=r.reduced,this.root=null,this.implicit=null,this.pre=r.pre||"",this.post=r.post||"",this.tags={},this.prev=null,this.next=null,this.id=l(r.clean),this.isA="Term",r.alias&&(this.alias=r.alias)}return r(e,[{key:"set",value:function(e){var t=E(e);return this.text=t.text,this.clean=t.clean,this}}]),e}();ee.prototype.clone=function(){var e=new ee(this.text);return e.pre=this.pre,e.post=this.post,e.tags=Object.assign({},this.tags),e},Object.assign(ee.prototype,L),Object.assign(ee.prototype,Y);var te=ee,ne={terms:function(e){var t=[this.pool.get(this.start)];if(0===this.length)return[];for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1?arguments[1]:void 0,n=arguments.length>2?arguments[2]:void 0;"string"==typeof e&&(e="normal"===e?{whitespace:!0,unicode:!0,lowercase:!0,punctuation:!0,acronyms:!0,abbreviations:!0,implicit:!0,normal:!0}:"clean"===e?{titlecase:!1,lowercase:!0,punctuation:!0,whitespace:!0,unicode:!0,implicit:!0}:"reduced"===e?{titlecase:!1,lowercase:!0,punctuation:!1,whitespace:!0,unicode:!0,implicit:!0,reduced:!0}:"root"===e?{titlecase:!1,lowercase:!0,punctuation:!0,whitespace:!0,unicode:!0,implicit:!0,root:!0}:{});var r=this.terms(),a=!1;r[0]&&null===r[0].prev&&null===r[r.length-1].next&&(a=!0);var i=r.reduce((function(i,o,s){e.last=n&&s===r.length-1;var u=!0,l=!0;return!1===a&&(0===s&&t&&(u=!1),s===r.length-1&&n&&(l=!1)),i+o.textOut(e,u,l)}),"");return!0===a&&n&&(i=re(i)),e.trim&&(i=i.trim()),i}},ie={trim:function(){var e=this.terms();if(e.length>0){e[0].pre=e[0].pre.replace(/^\s+/,"");var t=e[e.length-1];t.post=t.post.replace(/\s+$/,"")}return this}},oe=/[.?!]\s*$/,se=function(e,t){t[0].pre=e[0].pre;var n,r,a=e[e.length-1],i=t[t.length-1];i.post=(n=a.post,r=i.post,oe.test(r)?r+n.match(/\s*$/):n),a.post="",""===a.post&&(a.post+=" ")},ue=function(e,t,n){var r=e.terms();se(r,t.terms()),function(e,t){var n=e.lastTerm().next;(e.lastTerm().next=t.start,t.lastTerm().next=n,n)&&(e.pool.get(n).prev=t.lastTerm().id);var r=e.terms(0).id;r&&(t.terms(0).prev=r)}(e,t);var a,i=[e],o=e.start,s=[n];return(s=s.concat(n.parents())).forEach((function(e){var t=e.list.filter((function(e){return e.hasId(o)}));i=i.concat(t)})),(i=(a=i).filter((function(e,t){return a.indexOf(e)===t}))).forEach((function(e){e.length+=t.length})),e},le=/ /,ce=function(e,t,n){var r=e.start,a=t.terms();!function(e){var t=e[e.length-1];!1===le.test(t.post)&&(t.post+=" ")}(a),function(e,t,n){var r=n[n.length-1];r.next=e.start;var a=e.pool,i=a.get(e.start);i.prev&&(a.get(i.prev).next=t.start);n[0].prev=e.terms(0).prev,e.terms(0).prev=r.id}(e,t,a);var i,o=[e],s=[n];return(s=s.concat(n.parents())).forEach((function(e){var n=e.list.filter((function(e){return e.hasId(r)||e.hasId(t.start)}));o=o.concat(n)})),(o=(i=o).filter((function(e,t){return i.indexOf(e)===t}))).forEach((function(e){e.length+=t.length,e.start===r&&(e.start=t.start)})),e},he=function(e,t){var n=t.pool(),r=e.terms(),a=n.get(r[0].prev)||{},i=n.get(r[r.length-1].next)||{};r[0].implicit&&a.implicit&&(a.set(a.implicit),a.post+=" "),function(e,t,n,r){var a=e.parents();a.push(e),a.forEach((function(e){var a=e.list.find((function(e){return e.hasId(t)}));a&&(a.length-=n,a.start===t&&(a.start=r.id))})),e.list=e.list.filter((function(e){return!(!e.start||!e.length)}))}(t,e.start,e.length,i),a&&(a.next=i.id),i&&(i.prev=a.id)},de={append:function(e,t){return ue(this,e,t),this},prepend:function(e,t){return ce(this,e,t),this},delete:function(e){return he(this,e),this},replace:function(e,t){var n=this.length;ue(this,e,t);var r=this.buildFrom(this.start,this.length);r.length=n,he(r,t)},splitOn:function(e){var t=this.terms(),n={before:null,match:null,after:null},r=t.findIndex((function(t){return t.id===e.start}));if(-1===r)return n;var a=t.slice(0,r);a.length>0&&(n.before=this.buildFrom(a[0].id,a.length));var i=t.slice(r,r+e.length);i.length>0&&(n.match=this.buildFrom(i[0].id,i.length));var o=t.slice(r+e.length,t.length);return o.length>0&&(n.after=this.buildFrom(o[0].id,o.length,this.pool)),n}},fe={json:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1?arguments[1]:void 0,n={};return e.text&&(n.text=this.text()),e.normal&&(n.normal=this.text("normal")),e.clean&&(n.clean=this.text("clean")),e.reduced&&(n.reduced=this.text("reduced")),e.root&&(n.root=this.text("root")),e.trim&&(n.text&&(n.text=n.text.trim()),n.normal&&(n.normal=n.normal.trim()),n.reduced&&(n.reduced=n.reduced.trim())),e.terms&&(!0===e.terms&&(e.terms={}),n.terms=this.terms().map((function(n){return n.json(e.terms,t)}))),n}},me={lookAhead:function(e){e||(e=".*");var t=this.pool,n=[],r=this.terms();return function e(r){var a=t.get(r);a&&(n.push(a),a.prev&&e(a.next))}(r[r.length-1].next),0===n.length?[]:this.buildFrom(n[0].id,n.length).match(e)},lookBehind:function(e){e||(e=".*");var t=this.pool,n=[];return function e(r){var a=t.get(r);a&&(n.push(a),a.prev&&e(a.prev))}(t.get(this.start).prev),0===n.length?[]:this.buildFrom(n[n.length-1].id,n.length).match(e)}},pe=Object.assign({},ne,ae,ie,de,fe,me),ge=function(e,t){if(0===t.length)return!0;for(var n=0;n0)return!0;if(void 0!==e.cache.words&&void 0!==r.word&&!0!==e.cache.words.hasOwnProperty(r.word))return!0}if(!0===r.anything&&!0===r.negative)return!0}return!1},ve=function(e,t,n,r,a,i){for(var o=t;t1&&s.greedy&&a.push(i-1))}else{var l=be(e,i,t[o+1],s,n);if(void 0!==s.min&&l-is.max){i+=s.max;continue}if(null===l)return!1;i=l}}if(a.length>0){for(var c=e.slice(a[0],a[a.length-1]+1),h=0;h1)for(var t=e.map((function(e){return e.capture})),n=t.indexOf(!0),r=t.length-1-t.reverse().indexOf(!0),a=n;a2&&void 0!==arguments[2]&&arguments[2];if("string"==typeof t&&(t=Fe(t)),!0===ge(e,t))return[];var r=t.filter((function(e){return!0!==e.optional})).length,a=e.cache.terms||e.terms(),i=[];if(!0===t[0].start){var o=ye(a,t,0,a.length);return!1!==o&&o.length>0&&i.push(o),i=i.map((function(e){return e.filter((function(e){return e}))}))}for(var s=0;sa.length);s+=1){var u=ye(a.slice(s),t,s,a.length);if(!1!==u&&u.length>0&&(s+=u.length-1,u=u.filter((function(e){return e})),i.push(u),!0===n))return i}return i},je=function(e,t){var n={};Ne(e,t).forEach((function(e){e.forEach((function(e){n[e.id]=!0}))}));var r=e.terms(),a=[],i=[];return r.forEach((function(e){!0!==n[e.id]?i.push(e):i.length>0&&(a.push(i),i=[])})),i.length>0&&a.push(i),a},Be={match:function(e){var t=this,n=Ne(this,e);return n=n.map((function(e){return t.buildFrom(e[0].id,e.length)}))},has:function(e){return Ne(this,e,!0).length>0},not:function(e){var t=this,n=je(this,e);return n=n.map((function(e){return t.buildFrom(e[0].id,e.length)}))},canBe:function(e,t){for(var n=this,r=[],a=this.terms(),i=!1,o=0;o0})).map((function(e){return n.buildFrom(e[0].id,e.length)}))}},xe=function e(n,r,a){t(this,e),this.start=n,this.length=r,this.isA="Phrase",Object.defineProperty(this,"pool",{enumerable:!1,writable:!0,value:a}),Object.defineProperty(this,"cache",{enumerable:!1,writable:!0,value:{}})};xe.prototype.buildFrom=function(e,t){var n=new xe(e,t,this.pool);return this.cache&&(n.cache=this.cache,n.cache.terms=null),n},Object.assign(xe.prototype,Be),Object.assign(xe.prototype,pe);var De={term:"terms"};Object.keys(De).forEach((function(e){return xe.prototype[e]=xe.prototype[De[e]]}));var Oe=xe,Te=function(){function e(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};t(this,e),Object.defineProperty(this,"words",{enumerable:!1,value:n})}return r(e,[{key:"add",value:function(e){return this.words[e.id]=e,this}},{key:"get",value:function(e){return this.words[e]}},{key:"remove",value:function(e){delete this.words[e]}},{key:"merge",value:function(e){return Object.assign(this.words,e.words),this}},{key:"stats",value:function(){return{words:Object.keys(this.words).length}}}]),e}();Te.prototype.clone=function(){var e=this,t=Object.keys(this.words).reduce((function(t,n){var r=e.words[n].clone();return t[r.id]=r,t}),{});return new Te(t)};for(var Ve=Te,ze=/(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g,He=/\S/,Ie=/[ .][A-Z]\.? *$/i,Me=/(?:\u2026|\.{2,}) *$/,Se=/((?:\r?\n|\r)+)/,Le=/[a-z0-9\u00C0-\u00FF\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]/i,Je=/^\s+/,We=function(e,t){if(!0===Ie.test(e))return!1;if(!0===Me.test(e))return!1;if(!1===Le.test(e))return!1;var n=e.replace(/[.!?\u203D\u2E18\u203C\u2047-\u2049] *$/,"").split(" "),r=n[n.length-1].toLowerCase();return!t.hasOwnProperty(r)},_e=function(e,t){var n=t.cache.abbreviations;e=e||"";var r=[],a=[];if(!(e=String(e))||"string"!=typeof e||!1===He.test(e))return r;for(var i=function(e){for(var t=[],n=e.split(Se),r=0;r0&&(r.push(l),a[u]="")}if(0===r.length)return[e];for(var c=1;c0?(t[t.length-1]+=i,t.push(s)):t.push(i+s),i=""):i+=s}return i&&t.length>0&&(t[t.length-1]+=i),t=(t=function(e){for(var t=1;t0&&(t.prev=e[n-1].id),e[n+1]&&(t.next=e[n+1].id)}))},tt=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0,n=arguments.length>2?arguments[2]:void 0;"string"!=typeof e&&"number"==typeof e&&(e=String(e));var r=_e(e,t);r=r.map((function(e){return Ye(e)})),n=n||new Ve;var a=r.map((function(e){return e=e.map((function(e){var t=new te(e);return n.add(t),t})),et(e),new Oe(e[0].id,e.length,n)}));return a},nt=function(e,t){"string"==typeof e&&(e=JSON.parse(e));var n=new Ve;return e.list.map((function(r){var a=Ye(r[0]),i=function(e,t){return e.split("|").map((function(e){var n=e.split(",");return(n=n.map((function(e){return parseInt(e,10)}))).map((function(e){return t[e]||console.warn("Compromise import: missing tag at index "+e),t[e]}))}))}(r[1],e.tags);return a=a.map((function(e,r){var a=new te(e);return i[r].forEach((function(e){return a.tag(e,"",t)})),n.add(a),a})),et(a),new Oe(a[0].id,a.length,n)}))},rt={Comparative:"true¦better",Superlative:"true¦earlier",PresentTense:"true¦is,sounds",Value:"true¦a few",Noun:"true¦a8b7c5e3f2here,ie,lit,m1no doubt,p0tce,vs;d,l;a,d;t,y;g,sp,tc,x0;!p;a,ca,o0;l,rp;a,c,l;d,l,rc",Copula:"true¦a1is,w0;as,ere;m,re",PastTense:"true¦be3came,d2had,meant,sa2taken,w0;as,e0;nt,re;id;en,gan",Condition:"true¦if,unless",Gerund:"true¦accord0be0develop0go0result0stain0;ing",Negative:"true¦n0;ever,o0;!n,t",QuestionWord:"true¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s",Plural:"true¦records",Conjunction:"true¦&,aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh",Pronoun:"true¦'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s",Singular:"true¦0:0X;1:10;a0Wb0Kc0Bd04e02fXgShOici1jel0kitty,lNmJnIoHpDquestion mark,rBs7t4u2womW;nc0Rs 2;doll0Dst0F; rex,a3h2ic,ragedy,v show;ere,i1;l0x return;ist0Pky,omeone,t2uper bowl,yst0W;ep3ri1u2;de0Pff;faMmoM;al0i1o2;om,se;a4i0Jr3u2;dLrpoD;erogaVobl0O;rt,te0I;bjSceGthers;othi1umb0E;a4ee04o2;del,m2nopo0th0C;!my;n,yf0;i0unch;ead start,o2;l0me3u2;se;! run;adf0entlem5irlZlaci04od,rand3u2;l0y; slam,fa2mo2;th01;an;a5ella,ly,ol0r3un2;di1;iTo2;ntiWsN;mi0thV;conomy,gg,ner5veWx2;ampQecu7;ad7e4innSo2ragonf0ude;cumentFg2i0l0or;gy;ath,t2;ec2;tive;!dy;a8eili1h6i4o2redit card;ttage,u2;riJsin;ty,vil w2;ar;andeliGocol2;ate;n2rD;ary;aAel0lesHo6r4u2;n2tterf0;ti1;eakfast,o2;!th8;dy,tt4y2;!fri2;end;le;nki1r2;ri2;er;d4l0noma0u2;nt;ly; homin4verti2;si1;ng;em",Actor:"true¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt",Honorific:"true¦a03b00cSdReQfiLgKhon,jr,king,lJmEoDp8queen,r4s0taoiseach,vice7;e1fc,gt,ir,r,u0;ltTpt,rg;c0nDrgeaL;ond liJretary;abbi,e0;ar1pAs,v0;!erend; admirY;astPhd,r0vt;esideEi1of0;!essN;me mini5nce0;!ss;fficOp,rd;a3essrs,i2lle,me,r1s0;!tr;!s;stK;gistrate,j,r6yF;i3lb,t;en,ov;eld mar3rst l0;ady,i0;eutena0;nt;shG;sq,xcellency;et,oct6r,utchess;apt6hance4mdr,o0pl;lonel,m2ngress0unci3;m0wom0;an;dr,mand5;ll0;or;!ain;ldg,rig0;!adi0;er;d0sst,tty,yatullah;j,m0v;!ir0;al",SportsTeam:"true¦0:1A;1:1H;2:1G;a1Eb16c0Td0Kfc dallas,g0Ihouston 0Hindiana0Gjacksonville jagua0k0El0Bm01newToQpJqueens parkIreal salt lake,sAt5utah jazz,vancouver whitecaps,w3yW;ashington 3est ham0Rh10;natio1Oredski2wizar0W;ampa bay 6e5o3;ronto 3ttenham hotspur;blue ja0Mrapto0;nnessee tita2xasC;buccanee0ra0K;a7eattle 5heffield0Kporting kansas0Wt3;. louis 3oke0V;c1Frams;marine0s3;eah15ounG;cramento Rn 3;antonio spu0diego 3francisco gJjose earthquak1;char08paA; ran07;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat1steele0;il3oenix su2;adelphia 3li1;eagl1philNunE;dr1;akland 3klahoma city thunder,rlando magic;athle0Mrai3;de0; 3castle01;england 7orleans 6york 3;city fc,g4je0FknXme0Fred bul0Yy3;anke1;ian0D;pelica2sain0C;patrio0Brevolut3;ion;anchester Be9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Fvi3;kings;imberwolv1wi2;rewe0uc0K;dolphi2heat,marli2;mphis grizz3ts;li1;cXu08;a4eicesterVos angeles 3;clippe0dodDla9; galaxy,ke0;ansas city 3nE;chiefs,roya0E; pace0polis colU;astr06dynamo,rockeTtexa2;olden state warrio0reen bay pac3;ke0;.c.Aallas 7e3i05od5;nver 5troit 3;lio2pisto2ti3;ge0;broncZnuggeM;cowbo4maver3;ic00;ys; uQ;arCelKh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki1;brow2cavalie0india2;bengaWre3;ds;arlotte horAicago 3;b4cubs,fire,wh3;iteB;ea0ulR;diff3olina panthe0; c3;ity;altimore 9lackburn rove0oston 5rooklyn 3uffalo bilN;ne3;ts;cel4red3; sox;tics;rs;oriol1rave2;rizona Ast8tlanta 3;brav1falco2h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls",Uncountable:"true¦a1Ib1Ac11d0Ye0Rf0Lg0Hh0Ci08j07knowled1Hl02mUnews,oTpQrLsAt5vi4w0;a2ea05i1oo0;d,l;ldlife,ne;rmth,t17;neg0Yol06tae;e3h2oothpaste,r0una;affPou0;ble,sers,t;ermod1Eund12;a,nnis;a8cene04eri0Oh7il6kittl0Onow,o5p3t1u0;g0Rnshi0H;ati1De0;am,el;ace16e0;ci0Jed;ap,cc0U;k,v0T;eep,ingl0G;d04fe10l0nd;m0St;a3e1ic0;e,ke0D;c0laxa09search;ogni08rea08;bi09in;aJe1hys10last5o0ressV;lit0Zrk,w0J;a0Vtrol;bstetr0Xil,xygen;a5e3ilk,o2u0;mps,s0;ic;nGo0A;a0chan0S;slZt;chine0il,themat0Q; learn05ry;aught08e2i1ogi0Nu0;ck,g0C;ce,ghtn02ngui0LteratH;a0isG;th04;ewel7usti0G;ce,mp0nformaOtself;a0ortan0E;ti0;en0C;a3isto2o0;ck0mework,n0spitali06;ey;ry;ir,libut,ppi7;en01o1r0um,ymna08;a6ound;l0ssip;d,f;i4lour,o1urnit0;ure;od,rgive0uriNwl;ne0;ss;c6sh;conomZduca5lectr4n2quip3thZvery0;body,o0thE;ne;joy0tertain0;ment;iciNonU;tiF;ar1iabet0raugh1;es;ts;a7elcius,h3ivPl2o0urrency;al,ld w0nfusiAttA;ar;assMoth2;aos,e0;e1w0;ing;se;r4sh;a4eef,i1lood,owls,read,utt0;er;lliar1s0;on;ds;g0ss;ga0;ge;c6dvi5ero3ir2mnes1rt,thl0;et7;ty;craft;b4d0naut4;ynam3;ce;id,ou0;st0;ics",Infinitive:"true¦0:6H;1:6V;2:55;3:6S;4:6T;5:5W;6:64;7:6R;8:6N;9:6F;A:6P;B:6M;C:6A;D:6W;a67b5Wc4Yd46e3Qf3Dg37h30i2Nj2Lk2Jl2Am20n1Xo1Tp1Eques3Er0Ms01tTuPvMwFyE;awn,ield;aHe1Thist6iGoEre60;nd0rE;k,ry;pe,sh,th0;lk,nFrEsh,tCve;n,raD;d0t;aFiEo7;ew,sB;l68ry;nFpEr3se;gra4Jli3W;dEi7lo5O;er47o;aKeJhIoHrFuEwi8;ne,rn;aEe0Ki5Ku8y;de,in,nsf0p,v5C;r2VuC;ank,reat2L;nd,st;lk,rg1Ms7;aXcUeThRi48kip,lQmPnee3Ho4WpOtHuEwitC;bmBck,ff0gge8ppFrEspe5;ge,pri1rou4Tvi4;ly,o32;aJeIoHrFuE;dy,mb6;a4NeEi4;ngth2Bss,tC;p,re;m,p;in,ke,r0Oy;la50oil,rink6;e1Vi6o3F;am,ip;a2iv0oE;ck,ut;arCem,le5n1r4tt6;aFo2rE;atCew;le,re;il,ve;a03eGisk,oFuE;in,le,sh;am,ll;aZcXdu9fWgVje5lSmRnt,pOquNsItHvEwa5L;eEiew,o32;al,l,rE;se,t;a41i2u3Y;eHi8oGtE;!o2rE;i5uc1W;l4rt;mb6nt,r4;e8i2;air,eFlEo3XreseD;a9y;at;a3Remb0i3To4;aFeEi4y;a1nt;te,x;a53r0F;act1Uer,le5u1;a0Zei4k5FoEyc6;gni28nci6rd;ch,li27s5D;i1nE;ge,k;aRerQiPlMoKrGuE;b1Xll,mp,rEsh;cha1s4G;ai1eGiDoE;cEdu9greAhibBmi1te8vi2R;eAlaim;di5pa2ss,veD;iDp,rtr3WsEur;e,t;aFuE;g,n3;n,y;ck,le;fo2YmBsi8;ck,iDrt4Css,u1;bGccur,ff0pera7utweFverEwe;co3Xlap,ta1Yu1whelm;igh;ser4ta2Y;eFotE;e,i9;ed,gle5;aJeIiGoFuE;ltip3Ard0;nit10ve;nErr0Z;d,g6us;asu2lt,n0Mr3ssa3;inta2Ona3rFtE;ch,t0;ch,kEry;et;aKeJiGoEu1A;aEck,ok,ve;d,n;ft,ke,mBnFstEve;!en;e,k;a2Bc0Ct;b0Lck,uE;gh,nC;iEno2W;ck,ll,ss;am,o29uE;d3mp;gno2mOnEss39;cMdica7flu0KhLsItGvE;eEol4;nt,st;erErodu9;a5fe2;i8tE;aEru5;ll;abBibB;lu1Cr1A;agi20pE;lemeDo1Yro4;aIeGi2oFuE;nt,rry;n00pe,st;aElp;d,t;nd6ppErm,te;en;aIloAove1KrGuE;arEeAi11;ant30d;aEip,umb6;b,sp;in,th0ze;aOeaNiLlJoGracFuncE;ti3A;tu2;cus,lFrE;ce,eca8m,s2S;d,l1W;a1ToE;at,od,w;gu2lEni1Rx;e,l;r,tu2;il,vE;or;a11cho,le5mQnNstLvalua7xE;a08cJerIi8pEte15;a14eFla12oEreA;rt,se;ct,riE;en9;ci1t;el,han3;abEima7;li1D;ab6couVdFfor9ga3han9j01riCsu2t0vE;isi2Ny;!u2;body,er3pE;hasiEow0;ze;a04eSiJoIrFuE;mp;aFeAiE;ft;g,in;d3ubt;ff0p,re5sFvE;iWor9;aIcFliEmiApl13tingui0Y;ke;oEuA;uEv0;ra3;gr1QppE;ear,ro4;cLem,fJliv0ma0Bny,pIsFterE;mi0C;cribe,er4iFtrE;oy;gn,re;a07e06i5osB;eEi07y;at,ct;iGlFrE;ea1;a2i03;de;ma3n9re,te;a08e07h04i7l02oHrE;aFeEoAu0Dy;a7dB;ck,ve;llXmQnFok,py,uEv0;gh,nt;ceNdu5fKsItGvE;eEin9;rt,y;aNin0PrE;a8ibu7ol;iEtitu7;d0st;iFoEroD;rm;gu2rm;rn;biJfoImaHpE;a2laE;in;re;nd;rt;ne;ap1e5;aEip,o1;im,w;aFeE;at,ck,w;llen3n3r3se;a1nt0;ll,ncFrEt0u1;e,ry;el;aNeKloJoHruGuE;lEry;ly;sh;a8mb,o8rrEth0un9;ow;ck;ar,lFnefBtrE;ay;ie4ong;ng,se;band0Hc09d04ffo03gr02id,lZmu1nWppRrOsIttEvoid,waB;acGeFra5;ct;m0Dnd;h,k;k,sE;eGiFocia7uE;me;gn,st;mb6rt;le;chFgEri4;ue;!i4;eaHlGroE;aCve;ch;aud,y;l,r;noun9sw0tE;icipa7;ce;lFt0;er;e3ow;ee;rd;aPdGju8mBoP;it;st;!reA;ss;cHhie4knowled3tiva7;te;ge;ve;eGouDu1;se;nt;pt;on",Unit:"true¦0:16;a11b0Zc0Ld0Ke0If0Dg09h06in0Ejoule0k00lYmNnMoLpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Kb,d0Qears old,o1;tt0E;att0b;able4b3e2on1sp;!ne0;a2r0A;!l,sp;spo01; ft,uare 1;c0Fd0Ef3i0Ckilo0Gm1ya0B;e0Jil1;e0li0E;eet0o0A;t,uart0;ascals,e2i1ou0Mt;c0Jnt0;rcent,tZ;hms,uVz;an0GewtQ;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;e1g,z;ct1rtz0;aXogQ;al2b,igAra1;in0m0;!l1;on0;a4emtPl2t1;²,³; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s",Organization:"true¦0:46;a3Ab2Qc2Ad21e1Xf1Tg1Lh1Gi1Dj19k17l13m0Sn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0Xou1w0X;gov,tu2S;a3e1orld trade organizati41;lls fargo,st1;fie22inghou16;l1rner br3D;-m11gree31l street journ25m11;an halNeriz3Wisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Rps;es35i1;lev2Xted natio2Uv; mobi2Kaco bePd bMeAgi frida9h3im horto2Tmz,o1witt2W;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen33daily ma2Xguess w2holli0rolling st1Ms1w2;mashing pumpki2Ouprem0;ho;ea1lack eyed pe3Fyrds;ch bo1tl0;ys;l2s1;co,la m12;efoni07us;a6e4ieme2Gnp,o2pice gir5ta1ubaru;rbucks,to2N;ny,undgard1;en;a2Rx pisto1;ls;few25insbu26msu1X;.e.m.,adiohead,b6e3oyal 1yan2X;b1dutch she4;ank;/max,aders dige1Ed 1vl32;bu1c1Uhot chili peppe2Klobst28;ll;c,s;ant2Vizno2F;an5bs,e3fiz24hilip morrBi2r1;emier27octer & gamb1Rudenti14;nk floyd,zza hut;psi28tro1uge08;br2Qchina,n2Q; 2ason1Xda2G;ld navy,pec,range juli2xf1;am;us;a9b8e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0K;l,s;c,st1Etflix,w1; 1sweek;kids on the block,york08;a,c;nd1Us2t1;ional aca2Fo,we0Q;a,cYd0O;aAcdonald9e5i3lb,o1tv,yspace;b1Nnsanto,ody blu0t1;ley crue,or0O;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt13z1Y;'ore09a3e1g,ittle caesa1Ktd;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1K;art;iffy lu0Lo3pmorgan1sa;! cha1;se;hnson & johns1Sy d1R;bm,hop,n1tv;c,g,te1;l,rpol; & m,asbro,ewlett-packaTi3o1sbc,yundai;me dep1n1J;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Iu1;cci,ns n ros0;ldman sachs,o1;dye1g0B;ar;axo smith kliZencore;electr0Im1;oto0V;a3bi,da,edex,i1leetwood mac,oGrito-l0A;at,nancial1restoV; tim0;cebook,nnie mae;b06sa,u3xxon1; m1m1;ob0H;!rosceptics;aiml0Ae5isney,o3u1;nkin donuts,po0Wran dur1;an;j,w j1;on0;a,f leppa3ll,p2r spiegZstiny's chi1;ld;eche mode,t;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra05;al;!ca c5l4m1o0Ast05;ca2p1;aq;st;dplMgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Hy;dbury,pital o1rl's jr;ne;aGbc,eCfAl6mw,ni,o2p,r1;exiteeWos;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roX;ckbuster video,omingda1;le; g1g1;oodriN;cht3e ge0n & jer2rkshire hathaw1;ay;ryH;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bXcSdidRerosmith,ig,lLmFnheuser-busEol,ppleAr7s3t&t,v2y1;er;is,on;hland2s1;n,ociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c",Demonym:"true¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an",Possessive:"true¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne",Currency:"true¦$,aud,bScQdLeurKfJgbp,hkd,iIjpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotySł;en,uanR;af,of;h0t5;e0il5;k0q0;elM;iel,oubleLp,upeeL;e2ound st0;er0;lingI;n0soH;ceGn0;ies,y;e0i8;i,mpi7;n,r0wanzaCyatC;!onaBw;ls,nr;ori7ranc9;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s",City:"true¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,sario,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg",Abbreviation:"true¦a08b05cZdXeUfSgRhQiPjNkanMlKmGnEoDpCque,rAs6t4u3v2w0;is0y00;!c;a,s,t;niv,safa,t;ce,e0;nn,x;ask,e1fc,gt,ir,r,t,u0;pt,rg;nDp0;!t;d,e0;pAs,v;a,d,ennGhd,l,rof,vt;ct,kla,nt,p,rd;eb0ov;!r;a2d,essrs,i1lle,me,r5s0t;!tr;nn,ster;!j,r;it,lb,t0;!d;!s;an,r,u0;l,n;a,da,e,nc;on,wy;a,en,ov;eb,l0t,y;!a;g,s1tc,x0;!p;p,q;ak,e0ist,r;c,pt,t;a3ca,l,m2o0pl,res,t;!l0m1nn,rp;!o;dr;!l0pt;!if;a,c,l1r0;ig,os;!dg,vd;d3l2pr,r1ss0tty,ug,ve;n,t;c,iz;!ta;!j,m,v",Place:"true¦a07b05cZdYeXfVgRhQiOjfk,kMlKmHneEoDp9que,rd,s8t5u4v3w0yyz;is1y0;!o;!c;a,t;pYsafa,t;e1he 0;bronx,hamptons;nn,x;ask,fo,oho,t,under6yd;a2e1h0;l,x;k,nnK;!cifX;kla,nt;b1w eng0;land;!r;a1co,i0t,uc;dKnn;libu,nhattS;a0gw,hr;s,x;an0ul;!s;a0cn,da,ndianMst;!x;arlem,kg,nd,wy;a2re0;at 0enwich;britain,lak6;!y village;co,l0ra;!a;urope,verglad2;ak,en,fw,ist,own4xb;al4dg,gk,hina3l2o1r0t;es;lo,nn;!t;town;!if;cn,e0kk,lvd,rooklyn;l air,verly hills;frica,lta,m5ntarct2r1sia,tl0ve;!ant1;ct0iz;ic0; oce0;an;ericas,s",Country:"true¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an",Region:"true¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma",FemaleName:"true¦0:FY;1:G2;2:FR;3:FD;4:FC;5:EP;6:ER;7:FS;8:GF;9:EZ;A:GB;B:E5;C:FO;D:FL;E:G8;F:EG;aE2bD4cB8dAIe9Gf91g8Hh83i7Sj6Uk60l4Om38n2To2Qp2Fqu2Er1Os0Qt04ursu6vUwOyLzG;aJeHoG;e,la,ra;lGna;da,ma;da,ra;as7EeHol1TvG;et5onB9;le0sen3;an9endBNhiB4iG;lInG;if3AniGo0;e,f39;a,helmi0lGma;a,ow;aMeJiG;cHviG;an9XenG1;kCZtor3;da,l8Vnus,rG;a,nGoniD2;a,iDC;leGnesEC;nDLrG;i1y;aSePhNiMoJrGu6y4;acG3iGu0E;c3na,sG;h9Mta;nHrG;a,i;i9Jya;a5IffaCGna,s7;al3eGomasi0;a,l8Go6Xres1;g7Uo6WrHssG;!a,ie;eFi,ri8;bNliMmKnIrHs7tGwa0;ia0um;a,yn;iGya;a,ka,s7;a4e4iGmCAra;!ka;a,t7;at7it7;a05carlet2Ye04hUiSkye,oQtMuHyG;bFJlvi1;e,sHzG;an2Tet5ie,y;anGi8;!a,e,nG;aDe;aIeG;fGl3DphG;an2;cF8r6;f3nGphi1;d4ia,ja,ya;er4lv3mon1nGobh75;dy;aKeGirlBLo0y6;ba,e0i6lIrG;iGrBPyl;!d70;ia,lBV;ki4nIrHu0w0yG;la,na;i,leAon,ron;a,da,ia,nGon;a,on;l5Yre0;bMdLi9lKmIndHrGs7vannaD;aDi0;ra,y;aGi4;nt7ra;lBNome;e,ie;in1ri0;a02eXhViToHuG;by,thBK;bQcPlOnNsHwe0xG;an94ie,y;aHeGie,lE;ann8ll1marBFtB;!lGnn1;iGyn;e,nG;a,d7W;da,i,na;an9;hel53io;bin,erByn;a,cGkki,na,ta;helBZki;ea,iannDXoG;da,n12;an0bIgi0i0nGta,y0;aGee;!e,ta;a,eG;cARkaD;chGe,i0mo0n5EquCDvCy0;aCCelGi9;!e,le;een2ia0;aMeLhJoIrG;iGudenAW;scil1Uyamva9;lly,rt3;ilome0oebe,ylG;is,lis;arl,ggy,nelope,r6t4;ige,m0Fn4Oo6rvaBBtHulG;a,et5in1;ricGsy,tA8;a,e,ia;ctav3deHfAWlGphAW;a,ga,iv3;l3t5;aQePiJoGy6;eHrG;aDeCma;ll1mi;aKcIkGla,na,s7ta;iGki;!ta;hoB2k8BolG;a,eBH;!mh;l7Tna,risF;dIi5PnHo23taG;li1s7;cy,et5;eAiCO;a01ckenz2eViLoIrignayani,uriBGyG;a,rG;a,na,tAS;i4ll9XnG;a,iG;ca,ka,qB4;a,chOkaNlJmi,nIrGtzi;aGiam;!n9;a,dy,erva,h,n2;a,dIi9JlG;iGy;cent,e;red;!e6;ae6el3G;ag4KgKi,lHrG;edi61isFyl;an2iGliF;nGsAM;a,da;!an,han;b08c9Ed06e,g04i03l01nZrKtJuHv6Sx87yGz2;a,bell,ra;de,rG;a,eC;h75il9t2;a,cSgOiJjor2l6In2s7tIyG;!aGbe5QjaAlou;m,n9S;a,ha,i0;!aIbALeHja,lEna,sGt53;!a,ol,sa;!l06;!h,m,nG;!a,e,n1;arIeHie,oGr3Kueri5;!t;!ry;et3IiB;elGi61y;a,l1;dGon,ue6;akranBy;iGlo36;a,ka,n9;a,re,s2;daGg2;!l2W;alEd2elGge,isBGon0;eiAin1yn;el,le;a0Ie08iWoQuKyG;d3la,nG;!a,dHe9SnGsAQ;!a,e9R;a,sAO;aB1cJelIiFlHna,pGz;e,iB;a,u;a,la;iGy;a2Ae,l25n9;is,l1GrHtt2uG;el6is1;aIeHi8na,rG;a6Zi8;lei,n1tB;!in1;aQbPd3lLnIsHv3zG;!a,be4Ket5z2;a,et5;a,dG;a,sGy;ay,ey,i,y;a,iaIlG;iGy;a8Ge;!n4F;b7Terty;!n5R;aNda,e0iLla,nKoIslARtGx2;iGt2;c3t3;la,nGra;a,ie,o4;a,or1;a,gh,laG;!ni;!h,nG;a,d4e,n4N;cNdon7Si6kes7na,rMtKurIvHxGy6;mi;ern1in3;a,eGie,yn;l,n;as7is7oG;nya,ya;a,isF;ey,ie,y;aZeUhadija,iMoLrIyG;lGra;a,ee,ie;istGy5B;a,en,iGy;!e,n48;ri,urtn9A;aMerLl99mIrGzzy;a,stG;en,in;!berlG;eGi,y;e,y;a,stC;!na,ra;el6PiJlInHrG;a,i,ri;d4na;ey,i,l9Qs2y;ra,s7;c8Wi5XlOma6nyakumari,rMss5LtJviByG;!e,lG;a,eG;e,i78;a5EeHhGi3PlEri0y;ar5Cer5Cie,leCr9Fy;!lyn73;a,en,iGl4Uyn;!ma,n31sF;ei72i,l2;a04eVilToMuG;anKdJliGst56;aHeGsF;!nAt0W;!n8X;i2Ry;a,iB;!anLcelEd5Vel71han6IlJni,sHva0yG;a,ce;eGie;fi0lEph4X;eGie;en,n1;!a,e,n36;!i10lG;!i0Z;anLle0nIrHsG;i5Qsi5Q;i,ri;!a,el6Pif1RnG;a,et5iGy;!e,f1P;a,e72iHnG;a,e71iG;e,n1;cLd1mi,nHqueliAsmin2Uvie4yAzG;min8;a8eHiG;ce,e,n1s;!lGsFt06;e,le;inHk2lEquelG;in1yn;da,ta;lPmNnMo0rLsHvaG;!na;aHiGob6U;do4;!belGdo4;!a,e,l2G;en1i0ma;a,di4es,gr5R;el9ogG;en1;a,eAia0o0se;aNeKilHoGyacin1N;ll2rten1H;aHdGlaH;a,egard;ry;ath0WiHlGnrietBrmiAst0W;en24ga;di;il75lKnJrGtt2yl75z6D;iGmo4Fri4G;etG;!te;aDnaD;ey,l2;aYeTiOlMold12rIwG;enGyne18;!dolE;acHetGisel9;a,chC;e,ieG;!la;adys,enGor3yn1Y;a,da,na;aJgi,lHna,ov71selG;a,e,le;da,liG;an;!n0;mYnIorgHrG;ald35i,m2Stru73;et5i5T;a,eGna;s1Nvieve;briel3Fil,le,rnet,yle;aReOio0loMrG;anHe9iG;da,e9;!cG;esHiGoi0G;n1s3V;!ca;!rG;a,en43;lHrnG;!an9;ec3ic3;rHtiGy8;ma;ah,rah;d0FileCkBl00mUn4ArRsMtLuKvG;aIelHiG;e,ta;in0Ayn;!ngel2H;geni1la,ni3R;h52ta;meral9peranJtG;eHhGrel6;er;l2Pr;za;iGma,nest29yn;cGka,n;a,ka;eJilImG;aGie,y;!liA;ee,i1y;lGrald;da,y;aTeRiMlLma,no4oJsIvG;a,iG;na,ra;a,ie;iGuiG;se;a,en,ie,y;a0c3da,nJsGzaH;aGe;!beG;th;!a,or;anor,nG;!a;in1na;en,iGna,wi0;e,th;aWeKiJoGul2U;lor51miniq3Yn30rGtt2;a,eCis,la,othGthy;ea,y;an09naDonAx2;anPbOde,eNiLja,lImetr3nGsir4U;a,iG;ce,se;a,iHla,orGphiA;es,is;a,l5J;dGrdG;re;!d4Mna;!b2CoraDra;a,d4nG;!a,e;hl3i0mMnKphn1rHvi1WyG;le,na;a,by,cHia,lG;a,en1;ey,ie;a,et5iG;!ca,el1Aka;arGia;is;a0Qe0Mh04i02lUoJrHynG;di,th3;istGy04;al,i0;lOnLrHurG;tn1D;aId28iGn28riA;!nG;a,e,n1;!l1S;n2sG;tanGuelo;ce,za;eGleC;en,t5;aIeoHotG;il4B;!pat4;ir8rIudG;et5iG;a,ne;a,e,iG;ce,sX;a4er4ndG;i,y;aPeMloe,rG;isHyG;stal;sy,tG;aHen,iGy;!an1e,n1;!l;lseHrG;!i8yl;a,y;nLrG;isJlHmG;aiA;a,eGot5;n1t5;!sa;d4el1PtG;al,el1O;cHlG;es5i3F;el3ilG;e,ia,y;iYlXmilWndVrNsLtGy6;aJeIhGri0;erGleCrEy;in1;ri0;li0ri0;a2GsG;a2Fie;a,iMlKmeIolHrG;ie,ol;!e,in1yn;lGn;!a,la;a,eGie,y;ne,y;na,sF;a0Di0D;a,e,l1;isBl2;tlG;in,yn;arb0CeYianXlVoTrG;andRePiIoHyG;an0nn;nwEok8;an2NdgKg0ItG;n27tG;!aHnG;ey,i,y;ny;etG;!t8;an0e,nG;da,na;i8y;bbi8nG;iBn2;ancGossom,ythe;a,he;ca;aRcky,lin9niBrNssMtIulaDvG;!erlG;ey,y;hHsy,tG;e,i0Zy8;!anG;ie,y;!ie;nGt7yl;adHiG;ce;et5iA;!triG;ce,z;a4ie,ra;aliy29b24d1Lg1Hi19l0Sm0Nn01rWsNthe0uJvIyG;anGes7;a,na;a,r25;drIgusHrG;el3;ti0;a,ey,i,y;hHtrG;id;aKlGt1P;eHi8yG;!n;e,iGy;gh;!nG;ti;iIleHpiB;ta;en,n1t5;an19elG;le;aYdWeUgQiOja,nHtoGya;inet5n3;!aJeHiGmI;e,ka;!mGt5;ar2;!belHliFmT;sa;!le;ka,sGta;a,sa;elGie;a,iG;a,ca,n1qG;ue;!t5;te;je6rea;la;!bHmGstas3;ar3;el;aIberHel3iGy;e,na;!ly;l3n9;da;aTba,eNiKlIma,yG;a,c3sG;a,on,sa;iGys0J;e,s0I;a,cHna,sGza;a,ha,on,sa;e,ia;c3is7jaIna,ssaIxG;aGia;!nd4;nd4;ra;ia;i0nHyG;ah,na;a,is,naD;c7da,leCmLnslKsG;haDlG;inGyW;g,n;!h;ey;ee;en;at7g2nG;es;ie;ha;aVdiSelLrG;eIiG;anLenG;a,e,ne;an0;na;aKeJiHyG;nn;a,n1;a,e;!ne;!iG;de;e,lEsG;on;yn;!lG;iAyn;ne;agaJbHiG;!gaI;ey,i8y;!e;il;ah",WeekDay:"true¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s",Month:"true¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il",FirstName:"true¦aEblair,cCdevBj8k6lashawn,m3nelly,quinn,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0r9;ls7nyatta,rry;am0ess1ude;ie,m0;ie;an,on;as0heyenne;ey,sidy;lex1ndra,ubr0;ey;is",LastName:"true¦0:34;1:39;2:3B;3:2Y;4:2E;5:30;a3Bb31c2Od2Ee2Bf25g1Zh1Pi1Kj1Ek17l0Zm0Nn0Jo0Gp05rYsMtHvFwCxBy8zh6;a6ou,u;ng,o;a6eun2Uoshi1Kun;ma6ng;da,guc1Zmo27sh21zaR;iao,u;a7eb0il6o3right,u;li3Bs1;gn0lk0ng,tanabe;a6ivaldi;ssilj37zqu2;a9h8i2Go7r6sui,urn0;an,ynisJ;lst0Prr1Uth;at1Uomps1;kah0Vnaka,ylor;aEchDeChimizu,iBmiAo9t7u6zabo;ar2lliv2AzuE;a6ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n7sa6to;ki;ch2dLtos,z;amBeag1Zi9o7u6;bio,iz,sD;b6dri1MgIj0Tme24osevelt,ssi,ux;erts,ins1;c6ve0F;ci,hards1;ir2os;aEeAh8ic6ow20;as6hl0;so;a6illips;m,n1T;ders5et8r7t6;e0Nr4;ez,ry;ers;h21rk0t6vl4;el,te0J;baBg0Blivei01r6;t6w1O;ega,iz;a6eils1guy5ix1owak,ym1E;gy,ka6var1K;ji6muW;ma;aEeCiBo8u6;ll0n6rr0Bssolini,ñ6;oz;lina,oKr6zart;al0Me6r0U;au,no;hhail4ll0;rci0ssi6y0;!er;eWmmad4r6tsu07;in6tin2;!o;aCe8i6op2uo;!n6u;coln,dholm;fe7n0Qr6w0J;oy;bv6v6;re;mmy,rs5u;aBennedy,imuAle0Lo8u7wo6;k,n;mar,znets4;bay6vacs;asY;ra;hn,rl9to,ur,zl4;aAen9ha3imen2o6u3;h6nYu3;an6ns1;ss1;ki0Es5;cks1nsse0D;glesi9ke8noue,shik7to,vano6;u,v;awa;da;as;aBe8itchcock,o7u6;!a3b0ghNynh;a3ffmann,rvat;mingw7nde6rN;rs1;ay;ns5rrQs7y6;asDes;an4hi6;moJ;a9il,o8r7u6;o,tierr2;ayli3ub0;m2nzal2;nd6o,rcia;hi;erAis9lor8o7uj6;ita;st0urni0;es;ch0;nand2;d7insteHsposi6vaL;to;is1wards;aCeBi9omin8u6;bo6rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw7vi6;es,s;in;aFhBlarkAo6;h5l6op0rbyn,x;em7li6;ns;an;!e;an8e7iu,o6ristens5u3we;i,ng,u3w,y;!n,on6u3;!g;mpb7rt0st6;ro;ell;aBe8ha3lanco,oyko,r6yrne;ooks,yant;ng;ck7ethov5nnett;en;er,ham;ch,h8iley,rn6;es,i0;er;k,ng;dDl9nd6;ers6rA;en,on,s1;on;eks7iy8var2;ez;ej6;ev;ams",MaleName:"true¦0:CE;1:BL;2:C2;3:BT;4:B5;5:9V;6:BZ;7:AT;8:BD;9:AX;A:AO;aB4bA8c97d87e7Gf6Yg6Gh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt06u05v00wNxavi3yGzB;aBor0;cBh8Ine;hCkB;!aB1;ar51eB0;ass2i,oCuB;sDu25;nEsDusB;oBsC;uf;ef;at0g;aJeHiCoByaAP;lfgang,odrow;lBn1O;bDey,frBJlB;aA5iB;am,e,s;e89ur;i,nde5sB;!l7t1;de,lCrr6yB;l1ne;lBt3;a93y;aEern1iB;cCha0nceBrg9Bva0;!nt;ente,t5A;lentin49n8Yughn;lyss4Msm0;aTeOhKiIoErCyB;!l3ro8s1;av9QeBist0oy,um0;nt9Iv54y;bDd7XmBny;!as,mBoharu;aAYie,y;i83y;mBt9;!my,othy;adDeoCia7DomB;!as;!do7M;!de9;dErB;en8HrB;an8GeBy;ll,n8F;!dy;dgh,ic9Tnn3req,ts45;aRcotPeNhJiHoFpenc3tBur1Oylve8Hzym1;anDeBua7B;f0phAFvBwa7A;e57ie;!islaw,l7;lom1nA3uB;leyma8ta;dBl7Jm1;!n7;aDeB;lBrm0;d1t1;h6Sne,qu0Uun,wn,y8;aBbasti0k1Xl41rg40th,ymo9I;m9n;!tB;!ie,y;lCmBnti21q4Iul;!mAu4;ik,vato6V;aWeShe92iOoFuCyB;an,ou;b6LdCf9pe6QssB;!elAI;ol2Uy;an,bIcHdGel,geFh0landA9mEnDry,sCyB;!ce;coe,s;!a95nA;an,eo;l3Jr;e4Qg3n7olfo,ri68;co,ky;bAe9U;cBl7;ar5Oc5NhCkBo;!ey,ie,y;a85ie;gCid,ub6x,yBza;ansh,nS;g8WiB;na8Ss;ch5Yfa4lDmCndBpha4sh6Uul,ymo70;al9Yol2By;i9Ion;f,ph;ent2inB;cy,t1;aFeDhilCier62ol,reB;st1;!ip,lip;d9Brcy,tB;ar,e2V;b3Sdra6Ft44ul;ctav2Vliv3m96rFsCtBum8Uw6;is,to;aCc8SvB;al52;ma;i,l49vJ;athJeHiDoB;aBel,l0ma0r2X;h,m;cCg4i3IkB;h6Uola;hol5XkBol5X;!ol5W;al,d,il,ls1vB;il50;anBy;!a4i4;aWeTiKoFuCyB;l21r1;hamCr5ZstaB;fa,p4G;ed,mF;dibo,e,hamDis1XntCsBussa;es,he;e,y;ad,ed,mB;ad,ed;cGgu4kElDnCtchB;!e5;a78ik;house,o03t1;e,olB;aj;ah,hBk7;a4eB;al,l;hClv2rB;le,ri5v2;di,met;ck,hNlLmOnu4rHs1tDuricCxB;!imilian8Cwe5;e,io;eo,hCi52tB;!eo,hew,ia;eBis;us,w;cDio,k86lCqu6Gsha5tBv2;i2Hy;in,on;!el,oKus;achBcolm,ik;ai,y;amBdi,moud;adB;ou;aReNiMlo2RoIuCyB;le,nd1;cEiDkBth3;aBe;!s;gi,s;as,iaB;no;g0nn6RrenDuBwe5;!iB;e,s;!zo;am,on4;a7Bevi,la4SnDoBst3vi;!nB;!a60el;!ny;mCnBr67ur4Twr4T;ce,d1;ar,o4N;aIeDhaled,iBrist4Vu48y3B;er0p,rB;by,k,ollos;en0iEnBrmit,v2;!dCnBt5C;e0Yy;a5ri4N;r,th;na68rBthem;im,l;aYeQiOoDuB;an,liBst2;an,o,us;aqu2eJhnInGrEsB;eChBi7Bue;!ua;!ph;dBge;an,i,on;!aBny;h,s,th4X;!ath4Wie,nA;!l,sBy;ph;an,e,mB;!mA;d,ffGrDsB;sBus;!e;a5JemCmai8oBry;me,ni0O;i6Uy;!e58rB;ey,y;cHd6kGmFrDsCvi3yB;!d6s1;on,p3;ed,od,rBv4M;e4Zod;al,es,is1;e,ob,ub;k,ob,quB;es;aNbrahMchika,gKkeJlija,nuIrGsDtBv0;ai,sB;uki;aBha0i6Fma4sac;ac,iaB;h,s;a,vinBw2;!g;k,nngu52;!r;nacBor;io;im;in,n;aJeFina4VoDuByd56;be25gBmber4CsD;h,o;m3ra33sBwa3X;se2;aDctCitCn4ErB;be20m0;or;th;bKlJmza,nIo,rDsCyB;a43d6;an,s0;lEo4FrDuBv7;hi40ki,tB;a,o;is1y;an,ey;k,s;!im;ib;aQeMiLlenKoIrEuB;illerCsB;!tavo;mo;aDegBov3;!g,orB;io,y;dy,h57nt;nzaBrd1;lo;!n;lbe4Qno,ovan4R;ne,oDrB;aBry;ld,rd4U;ffr7rge;bri4l6rBv2;la1Zr3Eth,y;aReNiLlJorr0IrB;anDedBitz;!dAeBri24;ri23;cDkB;!ie,lB;in,yn;esJisB;!co,zek;etch3oB;yd;d4lBonn;ip;deriDliCng,rnB;an01;pe,x;co;bi0di;arZdUfrTit0lNmGnFo2rCsteb0th0uge8vBym6zra;an,ere2V;gi,iCnBrol,v2w2;est45ie;c07k;och,rique,zo;aGerFiCmB;aFe2P;lCrB;!h0;!io;s1y;nu4;be09d1iEliDmCt1viBwood;n,s;er,o;ot1Ts;!as,j43sB;ha;a2en;!dAg32mEuCwB;a25in;arB;do;o0Su0S;l,nB;est;aYeOiLoErDuCwByl0;ay8ight;a8dl7nc0st2;ag0ew;minFnDri0ugCyB;le;!l03;!a29nBov0;e5ie,y;go,icB;!k;armuCeBll1on,rk;go;id;anIj0lbeHmetri9nFon,rEsDvCwBxt3;ay8ey;en,in;hawn,mo08;ek,ri0F;is,nBv3;is,y;rt;!dB;re;lKmInHrDvB;e,iB;!d;en,iDne5rByl;eBin,yl;l2Vn;n,o,us;!e,i4ny;iBon;an,en,on;e,lB;as;a06e04hWiar0lLoGrEuCyrB;il,us;rtB;!is;aBistobal;ig;dy,lEnCrB;ey,neli9y;or,rB;ad;by,e,in,l2t1;aGeDiByI;fBnt;fo0Ct1;meCt9velaB;nd;nt;rDuCyB;!t1;de;enB;ce;aFeErisCuB;ck;!tB;i0oph3;st3;d,rlBs;eBie;s,y;cBdric,s11;il;lEmer1rB;ey,lCro5y;ll;!os,t1;eb,v2;ar02eUilTlaSoPrCuByr1;ddy,rtI;aJeEiDuCyB;an,ce,on;ce,no;an,ce;nCtB;!t;dCtB;!on;an,on;dCndB;en,on;!foBl7y;rd;bCrByd;is;!by;i8ke;al,lA;nFrBshoi;at,nCtB;!r10;aBie;rd0S;!edict,iCjam2nA;ie,y;to;n7rBt;eBy;tt;ey;ar0Xb0Nd0Jgust2hm0Gid6ja0ElZmXnPputsiOrFsaEuCveBya0ziz;ry;gust9st2;us;hi;aIchHi4jun,maFnDon,tBy0;hBu06;ur;av,oB;ld;an,nd0A;el;ie;ta;aq;dGgel05tB;hoEoB;i8nB;!i02y;ne;ny;reBy;!as,s,w;ir,mBos;ar;an,beOd6eIfFi,lEonDphonHt1vB;aMin;on;so,zo;an,en;onCrB;edP;so;c,jaEksandDssaExB;!and3;er;ar,er;ndB;ro;rtH;ni;en;ad,eB;d,t;in;aColfBri0vik;!o;mBn;!a;dFeEraCuB;!bakr,lfazl;hBm;am;!l;allEel,oulaye,ulB;!lCrahm0;an;ah,o;ah;av,on",Person:"true¦ashton kutchSbRcMdKeIgastNhGinez,jEkDleCmBnettJoAp8r4s3t2v0;a0irgin maG;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussain,carlett johanssJlobodan milosevic,uB;ay romano,eese witherspoIo1ush limbau0;gh;d stewart,nald0;inho,o;a0ipJ;lmIris hiltD;prah winfrFra;essiaen,itt romnEubarek;bron james,e;anye west,iefer sutherland,obe bryant;aime,effers8k rowli0;ng;alle ber0itlBulk hogan;ry;ff0meril lagasse,zekiel;ie;a0enzel washingt2ick wolf;lt1nte;ar1lint0ruz;on;dinal wols1son0;! palm2;ey;arack obama,rock;er",Verb:"true¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en",PhrasalVerb:"true¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2fast,oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut",Modal:"true¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld",Adjective:"true¦0:75;1:7K;2:7Q;3:7J;4:7C;5:5C;6:48;7:49;8:4S;9:61;A:7H;B:70;C:6Z;D:73;E:5X;a6Jb65c5Rd57e4Tf49g41h3Qi35j33k32l2Rm2Gn27o1Rp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6C;d6Ezy;despr75s5G;!sa7;eGlFste26;co1Il o4L;!k5;aGiFola4B;b7Tce versa,ol55;ca2gabo63nilla;ltWnJpGrb5Asu4tterF;!moC; f34b1OpGsFti1H;ca7et,ide dMtairs;er,i3N;aPbeco6Rconvin27deMeLfair,ivers4knKprecedYrIsGwF;iel20ritt5Z;i1VuF;pervis0specti3;eFu5;cognLgul6Hl6H;own;ndi3v5Txpect0;cid0rF;!grou5OsF;iz0tood;b7ppeaLssu6GuthorF;iz0;i24ra;aJeHhough4PoGrF;i1oubl0;geth8p,rpB;en5QlFm50rr2Ust0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3EoPpOqueami3EtJuFymb64;bHi gener55pFrprisi3;erFre0L;! dup8b,i29;du0seq4U;anda6UeIi0PrFy38;aightFip0; fFfF;or5B;adfaCreotyp0;aEec2Gir1JlendBot on; call0le,mb8phist1XrFu0Xvi42;dBry;gnifica2nF;ceEg7;am2Pe8ocki3ut;cFda1em5lfi2Yni1Wpa69re6;o1Gr3W;at58ient28reec58;cr0me,ns serif;aMeIiGoF;buCtt4UuSy4;ghtFv4;!-29f9;ar,bel,condi1du63fres52lHpublic3WsFtard0;is48oF;lu1na2;e1Euc46;bBciF;al,st;aQeOicayu6lacBopuliCrGuF;bl5Amp0;eJiGoF;!b0AfuDmi32p8;mGor,sFva1;ti6;a4We;ciDmF;a0IiF;er,um;ac20rFti1;feAma2Uplexi3v34;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Msi46;en,posi1; boa5Gg2Kli6;!ay; gua5EbFli6;eat;eHsF;cFer0Hole1;e6uE;d2Tse;ak0eMiLoFua4P;nJrGtF;ab7;thF;!eF;rn;chala2descri50stop;ght5;arby,cessa3Xighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuE;di4FnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abEho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3D;!-0C;nguBst,tt8;ap1Tind5no0A;agg0uF;niOstifi0veni7;de4gno4Clleg4mSnHpso 1WrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenDoxF;ic37;a6i2S;a1er,oce2;iGoF;or;reA;deq3Kppr2Z;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0R;d2RnD;aKelJiHoFumdr3C;neCok0rrFs07ur5;if2T;ghfalut1PspF;an2R;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Kiga23lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Eob4;aUeOinNlMoHrF;a1UeFoz1L;e2Eq13tf9;oHrF; keeps,eFm8tuna1;g05ign;liF;sh;ag30ue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lDr Gux,voF;ri1uri1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiE;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erD;creHeas0gruntl0honeCordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarElJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraBg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainCgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerD;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt",Comparable:"true¦0:40;1:4H;2:44;3:4A;4:2X;5:3W;a4Nb43c3Nd3Ce34f2Qg2Eh23i1Uj1Tk1Ql1Hm1Bn15o13p0Tqu0Rr0IsRtKuIvFw7y6za11;ell26ou3;aBe9hi1Xi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Lt;k,ry;n1Sr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Lse5;like0ti1;aAen9hi8i7ough,r6;anqu2Pen1ue;dy,g3Tme0ny,r09;ck,n,rs2Q;d41se;ll,me,rt,s6wd46;te5;aVcarUeThRiQkin0FlMmKoHpGqua1GtAu7w6;eet,ift;b7dd14per0Gr6;e,re2I;sta2Gt4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Gn0V;a1ep,rn;le,rk;e23i3Gright0;ci29ft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g36m6;!y;ek,nd3E;ck,l0mp4;a6iTort,rill,y;dy,ll0Yrp;cu0Sve0Sxy;ce,ed,y;d,fe,int0l1Wv15;aBe9i8o6ude;mantic,o1Jsy,u6;gh,nd;ch,pe,tzy;a6d,mo0I;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aEhoDi1RlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fouZud;ey,k0;li05or,te1C;ain,easa2;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd",TextValue:"true¦bMeIfChundredNmMnin9one,qu8s6t0zeroN;enMh3rLw0;e0o;l0ntC;fGve;ir0ousandIree;d,t5;e0ix7;cond,ptEven6xtE;adrDintD;e0th;!t0;e9ie8y;i3o0;rt1ur0;!t2;ie4y;ft0rst,ve;e3h,ie2y;ight0lev2;!e1h,ie0y;th;en1;illion0;!th",Ordinal:"true¦bGeDf9hundredHmGnin7qu6s4t0zeroH;enGh1rFwe0;lfFn9;ir0ousandE;d,t4;e0ixt9;cond,ptAvent8xtA;adr9int9;et0th;e6ie8;i2o0;r0urt3;tie5;ft1rst;ight0lev1;e0h,ie2;en1;illion0;th",Cardinal:"true¦bGeDf7hundred,mGnine9one,qu6s4t0zero;en,h2rFw0;e0o;lve,n7;irt8ousand,ree;e0ix4;ptAven3xtA;adr9int9;i3o0;r1ur0;!t2;ty;ft0ve;e2y;ight0lev1;!e0y;en;illion",Expression:"true¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la",Adverb:"true¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori",Preposition:"true¦'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut",Determiner:"true¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er"},at=["Person","Place","Organization"],it={Noun:{notA:["Verb","Adjective","Adverb"]},Singular:{isA:"Noun",notA:"Plural"},ProperNoun:{isA:"Noun"},Person:{isA:["ProperNoun","Singular"],notA:["Place","Organization"]},FirstName:{isA:"Person"},MaleName:{isA:"FirstName",notA:["FemaleName","LastName"]},FemaleName:{isA:"FirstName",notA:["MaleName","LastName"]},LastName:{isA:"Person",notA:["FirstName"]},Honorific:{isA:"Noun",notA:["FirstName","LastName"]},Place:{isA:"Singular",notA:["Person","Organization"]},Country:{isA:["Place","ProperNoun"],notA:["City"]},City:{isA:["Place","ProperNoun"],notA:["Country"]},Region:{isA:["Place","ProperNoun"]},Address:{isA:"Place"},Organization:{isA:["Singular","ProperNoun"],notA:["Person","Place"]},SportsTeam:{isA:"Organization"},School:{isA:"Organization"},Company:{isA:"Organization"},Plural:{isA:"Noun",notA:["Singular"]},Uncountable:{isA:"Noun"},Pronoun:{isA:"Noun",notA:at},Actor:{isA:"Noun",notA:at},Activity:{isA:"Noun",notA:["Person","Place"]},Unit:{isA:"Noun",notA:at},Demonym:{isA:["Noun","ProperNoun"],notA:at},Possessive:{isA:"Noun"}},ot={Verb:{notA:["Noun","Adjective","Adverb","Value"]},PresentTense:{isA:"Verb",notA:["PastTense","Copula","FutureTense"]},Infinitive:{isA:"PresentTense",notA:["PastTense","Gerund"]},Gerund:{isA:"PresentTense",notA:["PastTense","Copula","FutureTense"]},PastTense:{isA:"Verb",notA:["FutureTense"]},FutureTense:{isA:"Verb"},Copula:{isA:"Verb"},Modal:{isA:"Verb",notA:["Infinitive"]},PerfectTense:{isA:"Verb",notA:"Gerund"},Pluperfect:{isA:"Verb"},Participle:{isA:"Verb"},PhrasalVerb:{isA:"Verb"},Particle:{isA:"PhrasalVerb"}},st={Value:{notA:["Verb","Adjective","Adverb"]},Ordinal:{isA:"Value",notA:["Cardinal"]},Cardinal:{isA:"Value",notA:["Ordinal"]},RomanNumeral:{isA:"Cardinal",notA:["Ordinal","TextValue"]},TextValue:{isA:"Value",notA:["NumericValue"]},NumericValue:{isA:"Value",notA:["TextValue"]},Money:{isA:"Cardinal"},Percent:{isA:"Value"}},ut=["Noun","Verb","Adjective","Adverb","Value"],lt={Adjective:{notA:["Noun","Verb","Adverb","Value"]},Comparable:{isA:["Adjective"]},Comparative:{isA:["Adjective"]},Superlative:{isA:["Adjective"],notA:["Comparative"]},NumberRange:{isA:["Contraction"]},Adverb:{notA:["Noun","Verb","Adjective","Value"]},Date:{notA:["Verb","Conjunction","Adverb","Preposition","Adjective"]},Month:{isA:["Date","Singular"],notA:["Year","WeekDay","Time"]},WeekDay:{isA:["Date","Noun"]},Determiner:{notA:ut},Conjunction:{notA:ut},Preposition:{notA:ut},QuestionWord:{notA:["Determiner"]},Currency:{},Expression:{notA:["Noun","Adjective","Verb","Adverb"]},Abbreviation:{},Url:{notA:["HashTag","PhoneNumber","Verb","Adjective","Value","AtMention","Email"]},PhoneNumber:{notA:["HashTag","Verb","Adjective","Value","AtMention","Email"]},HashTag:{},AtMention:{isA:["Noun"],notA:["HashTag","Verb","Adjective","Value","Email"]},Emoji:{notA:["HashTag","Verb","Adjective","Value","AtMention"]},Emoticon:{notA:["HashTag","Verb","Adjective","Value","AtMention"]},Email:{notA:["HashTag","Verb","Adjective","Value","AtMention"]},Auxiliary:{notA:["Noun","Adjective","Value"]},Acronym:{notA:["Plural","RomanNumeral"]},Negative:{notA:["Noun","Adjective","Value"]},Condition:{notA:["Verb","Adjective","Noun","Value"]}},ct={Noun:"blue",Verb:"green",Negative:"green",Date:"red",Value:"red",Adjective:"magenta",Preposition:"cyan",Conjunction:"cyan",Determiner:"cyan",Adverb:"cyan"},ht=function(e){return Object.keys(e).forEach((function(t){ct[t]?e[t].color=ct[t]:e[t].isA.some((function(n){return!!ct[n]&&(e[t].color=ct[n],!0)}))})),e},dt=function(e){return Object.keys(e).forEach((function(t){for(var n=e[t],r=n.isA.length,a=0;a=0;i--,a*=36){var o=e.charCodeAt(i)-48;o>10&&(o-=7),t+=o*a}return t},wt=function(e,t,n){var r=At(t);return r1&&(n.hasCompound[i[0]]=!0),"Singular"===t){var o=a.toPlural(e,n);r[o]=r[o]||"Plural"}if("Infinitive"===t)for(var s=a.conjugate(e,n),u=Object.keys(s),l=0;l0&&void 0!==arguments[0]?arguments[0]:"",t=e[e.length-1];if(!0===Tt.hasOwnProperty(t))for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0,n={};return t&&t.irregulars&&!0===t.irregulars.verbs.hasOwnProperty(e)&&(n=Object.assign({},t.irregulars.verbs[e])),void 0===(n=Object.assign({},Ht(e),n)).Gerund&&(n.Gerund=Mt.Gerund(e)),void 0===n.PastTense&&(n.PastTense=Mt.PastTense(e)),void 0===n.PresentTense&&(n.PresentTense=Mt.PresentTense(e)),n},Lt=[/ght$/,/nge$/,/ough$/,/ain$/,/uel$/,/[au]ll$/,/ow$/,/oud$/,/...p$/],Jt=[/ary$/],Wt={nice:"nicest",late:"latest",hard:"hardest",inner:"innermost",outer:"outermost",far:"furthest",worse:"worst",bad:"worst",good:"best",big:"biggest",large:"largest"},_t=[{reg:/y$/i,repl:"iest"},{reg:/([aeiou])t$/i,repl:"$1ttest"},{reg:/([aeou])de$/i,repl:"$1dest"},{reg:/nge$/i,repl:"ngest"},{reg:/([aeiou])te$/i,repl:"$1test"}],qt=[/ght$/,/nge$/,/ough$/,/ain$/,/uel$/,/[au]ll$/,/ow$/,/old$/,/oud$/,/e[ae]p$/],Rt=[/ary$/,/ous$/],Kt={grey:"greyer",gray:"grayer",green:"greener",yellow:"yellower",red:"redder",good:"better",well:"better",bad:"worse",sad:"sadder",big:"bigger"},Qt=[{reg:/y$/i,repl:"ier"},{reg:/([aeiou])t$/i,repl:"$1tter"},{reg:/([aeou])de$/i,repl:"$1der"},{reg:/nge$/i,repl:"nger"}],Ut={toSuperlative:function(e){if(Wt.hasOwnProperty(e))return Wt[e];for(var t=0;t<_t.length;t++)if(_t[t].reg.test(e))return e.replace(_t[t].reg,_t[t].repl);for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0,n=t.irregulars.nouns;if(n.hasOwnProperty(e))return n[e];var r=en(e);return null!==r?r:Yt.test(e)?e+"es":e+"s"},nn=[[/([^v])ies$/i,"$1y"],[/ises$/i,"isis"],[/(kn|[^o]l|w)ives$/i,"$1ife"],[/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i,"$1f"],[/^(dwar|handkerchie|hoo|scar|whar)ves$/i,"$1f"],[/(antenn|formul|nebul|vertebr|vit)ae$/i,"$1a"],[/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i,"$1us"],[/(buffal|tomat|tornad)(oes)$/i,"$1o"],[/(..[aeiou]s)es$/i,"$1"],[/(vert|ind|cort)(ices)$/i,"$1ex"],[/(matr|append)(ices)$/i,"$1ix"],[/(x|ch|ss|sh|z|o)es$/i,"$1"],[/men$/i,"man"],[/(n)ews$/i,"$1ews"],[/([ti])a$/i,"$1um"],[/([^aeiouy]|qu)ies$/i,"$1y"],[/(s)eries$/i,"$1eries"],[/(m)ovies$/i,"$1ovie"],[/([m|l])ice$/i,"$1ouse"],[/(cris|ax|test)es$/i,"$1is"],[/(alias|status)es$/i,"$1"],[/(ss)$/i,"$1"],[/(ics)$/i,"$1"],[/s$/i,""]],rn=function(e,t){var n,r=t.irregulars.nouns,a=(n=r,Object.keys(n).reduce((function(e,t){return e[n[t]]=t,e}),{}));if(a.hasOwnProperty(e))return a[e];for(var i=0;i0}));return this.buildFrom(n)},t.ifNo=function(e){var t=Fe(e),n=this.list.filter((function(e){return 0===e.match(t).length}));return this.buildFrom(n)},t.has=function(e){var t=Fe(e);return this.list.some((function(e){return!0===e.has(t)}))},t.lookAhead=function(e){e||(e=".*");var t=Fe(e),n=[];return this.list.forEach((function(e){n=n.concat(e.lookAhead(t))})),n=n.filter((function(e){return e})),this.buildFrom(n)},t.lookAfter=t.lookAhead,t.lookBehind=function(e){e||(e=".*");var t=Fe(e),n=[];return this.list.forEach((function(e){n=n.concat(e.lookBehind(t))})),n=n.filter((function(e){return e})),this.buildFrom(n)},t.lookBefore=t.lookBehind,t.before=function(e){var t=Fe(e),n=this.if(t).list.map((function(e){var n=e.terms().map((function(e){return e.id})),r=e.match(t)[0],a=n.indexOf(r.start);return 0===a||-1===a?null:e.buildFrom(e.start,a)}));return n=n.filter((function(e){return null!==e})),this.buildFrom(n)},t.after=function(e){var t=Fe(e),n=this.if(t).list.map((function(e){var n=e.terms(),r=n.map((function(e){return e.id})),a=e.match(t)[0],i=r.indexOf(a.start);if(-1===i||!n[i+a.length])return null;var o=n[i+a.length].id,s=e.length-i-a.length;return e.buildFrom(o,s)}));return n=n.filter((function(e){return null!==e})),this.buildFrom(n)}}))),vn=(gn.match,gn.not,gn.matchOne,gn.ifNo,gn.has,gn.lookAhead,gn.lookAfter,gn.lookBehind,gn.lookBefore,gn.before,gn.after,function(e,t,n,r){var a=[];"string"==typeof e&&(a=e.split(" ")),t.list.forEach((function(i){var o=i.terms();!0===n&&(o=o.filter((function(n){return n.canBe(e,t.world)}))),o.forEach((function(n,i){a.length>1?a[i]&&"."!==a[i]&&n.tag(a[i],r,t.world):n.tag(e,r,t.world)}))}))}),bn={tag:function(e,t){return e?(vn(e,this,!1,t),this):this},tagSafe:function(e,t){return e?(vn(e,this,!0,t),this):this},unTag:function(e,t){var n=this;return this.list.forEach((function(r){r.terms().forEach((function(r){return r.unTag(e,t,n.world)}))})),this},canBe:function(e){if(!e)return this;var t=this.world,n=this.list.reduce((function(n,r){return n.concat(r.canBe(e,t))}),[]);return this.buildFrom(n)}},yn={map:function(t){var n=this;if(!t)return this;var r=this.list.map((function(e,r){var a=n.buildFrom([e]);a.from=null;var i=t(a,r);return i.list&&i.list[0]?i.list[0]:i}));return 0===r.length?this.buildFrom(r):"object"!==e(r[0])||"Phrase"!==r[0].isA?r:this.buildFrom(r)},forEach:function(e,t){var n=this;return e?(this.list.forEach((function(r,a){var i=n.buildFrom([r]);!0===t&&(i.from=null),e(i,a)})),this):this},filter:function(e){var t=this;if(!e)return this;var n=this.list.filter((function(n,r){var a=t.buildFrom([n]);return a.from=null,e(a,r)}));return this.buildFrom(n)},find:function(e){var t=this;if(!e)return this;var n=this.list.find((function(n,r){var a=t.buildFrom([n]);return a.from=null,e(a,r)}));return n?this.buildFrom([n]):void 0},some:function(e){var t=this;return e?this.list.some((function(n,r){var a=t.buildFrom([n]);return a.from=null,e(a,r)})):this},random:function(e){if(!this.found)return this;var t=Math.floor(Math.random()*this.list.length);if(void 0===e){var n=[this.list[t]];return this.buildFrom(n)}return t+e>this.length&&(t=(t=this.length-e)<0?0:t),this.slice(t,t+e)}},An=function(e,t){return""!==t&&(e.reduced===t||e.implicit===t||e.root===t||e.text.toLowerCase()===t)},wn={lookup:function(t){var n=this;"string"==typeof t&&(t=[t]);var r=t.map((function(e){e=e.toLowerCase();var t=Ye(e);return t=t.map((function(e){return e.trim()}))}));this.cache();var a=[];return r.forEach((function(t){n.list.forEach((function(n){if(!0===n.cache.words[t[0]]){var r=n.terms(),i=function(t,n){for(var r=function(e){if(An(n[e],t[0])&&t.every((function(t,r){return!0===An(n[e+r],t)})))return{v:n[e].id}},a=0;a0&&void 0!==arguments[0]?arguments[0]:{};if("number"==typeof n&&this.list[n])return this.list[n].json(r);("root"===(n=Object.assign({},r,n))||"object"===e(n)&&n.root)&&this.list.forEach((function(e){e.terms().forEach((function(e){null===e.root&&e.setRoot(t.world)}))})),n.unique&&(n.reduced=!0),n.offset&&(n.terms=!0===n.terms?{}:n.terms,n.terms.offset=!0),(n.index||n.terms.index)&&(n.terms=!0===n.terms?{}:n.terms,n.terms.id=!0);var i=this.list.map((function(e){return e.json(n,t.world)}));if(n.terms.offset||n.offset||n.terms.index||n.index){var o=a(this.all());(n.terms.index||n.index)&&i.forEach((function(e){e.terms.forEach((function(e){e.index=o[e.id].index})),e.index=e.terms[0].index})),(n.terms.offset||n.offset)&&i.forEach((function(e){e.terms.forEach((function(e){e.offset=o[e.id]||{}}));var t=e.terms.reduce((function(e,t){return e+=t.offset.length||0}),0);e.offset=e.terms[0].offset,e.offset.length=t}))}if(n.frequency||n.freq||n.count){var s={};this.list.forEach((function(e){var t=e.text("reduced");s[t]=s[t]||0,s[t]+=1})),this.list.forEach((function(e,t){i[t].count=s[e.text("reduced")]}))}if(n.unique){var u={};i=i.filter((function(e){return!0!==u[e.reduced]&&(u[e.reduced]=!0,!0)}))}return i},n.data=n.json})),En=(Gn.json,Gn.data,["Person","Place","Organization"]),Cn={Noun:{notA:["Verb","Adjective","Adverb"]},Singular:{isA:"Noun",notA:"Plural"},ProperNoun:{isA:"Noun"},Person:{isA:["ProperNoun","Singular"],notA:["Place","Organization"]},FirstName:{isA:"Person"},MaleName:{isA:"FirstName",notA:["FemaleName","LastName"]},FemaleName:{isA:"FirstName",notA:["MaleName","LastName"]},LastName:{isA:"Person",notA:["FirstName"]},Honorific:{isA:"Noun",notA:["FirstName","LastName"]},Place:{isA:"Singular",notA:["Person","Organization"]},Country:{isA:["Place","ProperNoun"],notA:["City"]},City:{isA:["Place","ProperNoun"],notA:["Country"]},Region:{isA:["Place","ProperNoun"]},Address:{isA:"Place"},Organization:{isA:["Singular","ProperNoun"],notA:["Person","Place"]},SportsTeam:{isA:"Organization"},School:{isA:"Organization"},Company:{isA:"Organization"},Plural:{isA:"Noun",notA:["Singular"]},Uncountable:{isA:"Noun"},Pronoun:{isA:"Noun",notA:En},Actor:{isA:"Noun",notA:En},Activity:{isA:"Noun",notA:["Person","Place"]},Unit:{isA:"Noun",notA:En},Demonym:{isA:["Noun","ProperNoun"],notA:En},Possessive:{isA:"Noun"}},Fn={Verb:{notA:["Noun","Adjective","Adverb","Value"]},PresentTense:{isA:"Verb",notA:["PastTense","Copula","FutureTense"]},Infinitive:{isA:"PresentTense",notA:["PastTense","Gerund"]},Gerund:{isA:"PresentTense",notA:["PastTense","Copula","FutureTense"]},PastTense:{isA:"Verb",notA:["FutureTense"]},FutureTense:{isA:"Verb"},Copula:{isA:"Verb"},Modal:{isA:"Verb",notA:["Infinitive"]},PerfectTense:{isA:"Verb",notA:"Gerund"},Pluperfect:{isA:"Verb"},Participle:{isA:"Verb"},PhrasalVerb:{isA:"Verb"},Particle:{isA:"PhrasalVerb"}},Nn={Value:{notA:["Verb","Adjective","Adverb"]},Ordinal:{isA:"Value",notA:["Cardinal"]},Cardinal:{isA:"Value",notA:["Ordinal"]},RomanNumeral:{isA:"Cardinal",notA:["Ordinal","TextValue"]},TextValue:{isA:"Value",notA:["NumericValue"]},NumericValue:{isA:"Value",notA:["TextValue"]},Money:{isA:"Cardinal"},Percent:{isA:"Value"}},jn=["Noun","Verb","Adjective","Adverb","Value"],Bn={Adjective:{notA:["Noun","Verb","Adverb","Value"]},Comparable:{isA:["Adjective"]},Comparative:{isA:["Adjective"]},Superlative:{isA:["Adjective"],notA:["Comparative"]},NumberRange:{isA:["Contraction"]},Adverb:{notA:["Noun","Verb","Adjective","Value"]},Date:{notA:["Verb","Conjunction","Adverb","Preposition","Adjective"]},Month:{isA:["Date","Singular"],notA:["Year","WeekDay","Time"]},WeekDay:{isA:["Date","Noun"]},Determiner:{notA:jn},Conjunction:{notA:jn},Preposition:{notA:jn},QuestionWord:{notA:["Determiner"]},Currency:{},Expression:{notA:["Noun","Adjective","Verb","Adverb"]},Abbreviation:{},Url:{notA:["HashTag","PhoneNumber","Verb","Adjective","Value","AtMention","Email"]},PhoneNumber:{notA:["HashTag","Verb","Adjective","Value","AtMention","Email"]},HashTag:{},AtMention:{isA:["Noun"],notA:["HashTag","Verb","Adjective","Value","Email"]},Emoji:{notA:["HashTag","Verb","Adjective","Value","AtMention"]},Emoticon:{notA:["HashTag","Verb","Adjective","Value","AtMention"]},Email:{notA:["HashTag","Verb","Adjective","Value","AtMention"]},Auxiliary:{notA:["Noun","Adjective","Value"]},Acronym:{notA:["Plural","RomanNumeral"]},Negative:{notA:["Noun","Adjective","Value"]},Condition:{notA:["Verb","Adjective","Noun","Value"]}},xn={Noun:"blue",Verb:"green",Negative:"green",Date:"red",Value:"red",Adjective:"magenta",Preposition:"cyan",Conjunction:"cyan",Determiner:"cyan",Adverb:"cyan"},Dn=function(e){return Object.keys(e).forEach((function(t){xn[t]?e[t].color=xn[t]:e[t].isA.some((function(n){return!!xn[n]&&(e[t].color=xn[n],!0)}))})),e},On=function(e){return Object.keys(e).forEach((function(t){for(var n=e[t],r=n.isA.length,a=0;at.count?-1:e.countt[n]?-1:1}))).map((function(e){return[e,t[e]]}))}(n);var r={};return n.forEach((function(e,t){r[e[0]]=t})),t=t.map((function(t){var n=t.terms.map((function(t){var n=t.tags;return n=(n=(n=Jn(n,e.world)).map((function(e){return r[e]}))).join(",")}));return n=n.join("|"),[t.text,n]})),{tags:Object.keys(r),list:t}}},_n={alpha:function(e,t){var n=e.text("clean"),r=t.text("clean");return nr?1:0},length:function(e,t){var n=e.text().trim().length,r=t.text().trim().length;return nr?-1:0},wordCount:function(e,t){var n=e.wordCount(),r=t.wordCount();return nr?-1:0}};_n.alphabetical=_n.alpha,_n.wordcount=_n.wordCount;var qn={index:!0,sequence:!0,seq:!0,sequential:!0,chron:!0,chronological:!0},Rn={sort:function(e){return"freq"===(e=e||"alpha")||"frequency"===e||"topk"===e?(n={},r={case:!0,punctuation:!1,whitespace:!0,unicode:!0},(t=this).list.forEach((function(e){var t=e.text(r);n[t]=n[t]||0,n[t]+=1})),t.list.sort((function(e,t){var a=n[e.text(r)],i=n[t.text(r)];return ai?-1:0})),t):qn.hasOwnProperty(e)?function(e){var t={};return e.json({terms:{offset:!0}}).forEach((function(e){t[e.terms[0].id]=e.terms[0].offset.start})),e.list=e.list.sort((function(e,n){return t[e.start]>t[n.start]?1:t[e.start]0){a+=o;continue}}void 0!==n[i]&&!0===n.hasOwnProperty(i)&&e[a].tag(n[i],"lexicon",t),i!==e[a].reduced&&!0===n.hasOwnProperty(e[a].reduced)&&e[a].tag(n[e[a].reduced],"lexicon",t)}return e},fr=/[\'‘’‛‵′`´]$/,mr=/^[A-Z]('s|,)?$/,pr={I:!0,A:!0},gr=function(e,t,n){var r=e[t];if(fr.test(r.text)&&!fr.test(r.pre)&&!fr.test(r.post)&&r.clean.length>2){var a=r.clean[r.clean.length-2];if("s"===a)return void r.tag(["Possessive","Noun"],"end-tick",n);"n"===a&&r.tag(["Gerund"],"chillin",n)}!function(e,t){var n=e.reduced;return!!e.tags.Acronym||!(n.length>4&&t.words[n])&&e.isAcronym()}(r,n)?!pr.hasOwnProperty(r.text)&&mr.test(r.text)&&(r.tag("Acronym","one-letter-acronym",n),r.tag("Noun","one-letter-infer",n)):(r.tag("Acronym","acronym-step",n),r.tag("Noun","acronym-infer",n))},vr=[[/^[0-9]{3}-[0-9]{4}$/,"PhoneNumber"],[/^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$/,"PhoneNumber"],[/^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?([a-z]{1,4})?$/,["Money","Value"]],[/^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$/,["Money","Value"]],[/^[-+]?[0-9]([0-9,.]+)?(usd|eur|jpy|gbp|cad|aud|chf|cny|hkd|nzd|kr|rub)$/i,["Money","Value"]],[/^\w+@\w+\.[a-z]{2,3}$/,"Email"],[/^#[a-z0-9_\u00C0-\u00FF]{2,}$/,"HashTag"],[/^@\w{2,}$/,"AtMention"],[/^(https?:\/\/|www\.)\w+\.[a-z]{2,3}/,"Url"],[/^[\w\.\/]+\.(com|net|gov|org|ly|edu|info|biz|ru|jp|de|in|uk|br)/,"Url"],[/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$/,"Time"],[/^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$/,"Time"],[/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$/,"Time"],[/^[PMCE]ST$/,"Time"],[/^utc ?[+-]?[0-9]+?$/,"Time"],[/^[a-z0-9]*? o\'?clock$/,"Time"],[/^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$/,"Date"],[/^[0-9]{1,4}\/[0-9]{1,2}\/[0-9]{1,4}$/,"Date"],[/^ma?c\'.*/,"LastName"],[/^o\'[drlkn].*/,"LastName"],[/^ma?cd[aeiou]/,"LastName"],[/^(lol)+[sz]$/,"Expression"],[/^(un|de|re)\\-[a-z\u00C0-\u00FF]{2}/,"Verb"],[/^[\-\+]?[0-9]+(\.[0-9])*$/,["Cardinal","NumericValue"]],[/^(over|under)[a-z]{2,}/,"Adjective"],[/^[0-9]{1,4}\.[0-9]{1,2}\.[0-9]{1,4}$/,"Date"],[/^[\-\+]?[0-9][0-9,]*(\.[0-9])*$/,["Cardinal","NumericValue"]],[/^[-+]?[0-9]+(.[0-9]+)?$/,["Cardinal","NumericValue"]],[/^[0-9\.]{1,4}(st|nd|rd|th)?[-–][0-9\.]{1,4}(st|nd|rd|th)?$/,"NumberRange"],[/^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$/,"NumericValue"],[/^.?[0-9]+([0-9,.]+)?%$/,["Percent","Cardinal","NumericValue"]],[/^[0-9]{1,4}\/[0-9]{1,4}$/,"Fraction"],[/^[0-9\.]{1,2}[-–][0-9]{1,2}$/,["Value","NumberRange"]],[/^[0-9][0-9,\.]*(st|nd|rd|r?th)$/,["NumericValue","Ordinal"]],[/[0-9]\+$/,["Cardinal","NumericValue"]],[/^[0-9]+(st|nd|rd|th)$/,"Ordinal"],[/^[0-9\.]+([a-z]{1,4})$/,"Value"]],br=/^[IVXLCDM]{2,}$/,yr=/^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/,Ar="Adjective",wr="Infinitive",kr="Singular",$r="PastTense",Pr="Expression",Gr="LastName",Er={a:[[/.[aeiou]na$/,"Noun"],[/.[oau][wvl]ska$/,Gr],[/.[^aeiou]ica$/,kr],[/^([hyj]a)+$/,Pr]],c:[[/.[^aeiou]ic$/,Ar]],d:[[/.[ia]sed$/,Ar],[/.[gt]led$/,Ar],[/.[td]ed$/,$r],[/.[aeiou]red$/,$r],[/.[^aeiou]led$/,$r],[/[^aeiou]ard$/,kr],[/[aeiou][^aeiou]id$/,Ar],[/[aeiou]c?ked$/,$r],[/[^aeiou][aeiou][tvx]ed$/,$r],[/.[vrl]id$/,Ar]],e:[[/.[lnr]ize$/,wr],[/.[^aeiou]ise$/,wr],[/.[aeiou]te$/,wr],[/.[^aeiou][ai]ble$/,Ar],[/.[^aeiou]eable$/,Ar],[/.[ts]ive$/,Ar]],h:[[/.[^aeiouf]ish$/,Ar],[/.v[iy]ch$/,Gr],[/^ug?h+$/,Pr],[/^uh[ -]?oh$/,Pr]],i:[[/.[oau][wvl]ski$/,Gr]],k:[[/^(k)+$/,Pr]],l:[[/.[gl]ial$/,Ar],[/.[^aeiou]ful$/,Ar],[/.[nrtumcd]al$/,Ar],[/.[^aeiou][ei]al$/,Ar]],m:[[/.[^aeiou]ium$/,kr],[/[^aeiou]ism$/,kr],[/^h*u*m+$/,Pr],[/^\d+ ?[ap]m$/,"Date"]],n:[[/.[lsrnpb]ian$/,Ar],[/[^aeiou]ician$/,"Actor"]],o:[[/^no+$/,Pr],[/^(yo)+$/,Pr],[/^woo+[pt]?$/,Pr]],r:[[/.[bdfklmst]ler$/,"Noun"],[/.[ilk]er$/,"Comparative"],[/[aeiou][pns]er$/,kr],[/[^i]fer$/,wr],[/.[^aeiou][ao]pher$/,"Actor"]],t:[[/.[di]est$/,"Superlative"],[/.[icldtgrv]ent$/,Ar],[/[aeiou].*ist$/,Ar],[/^[a-z]et$/,"Verb"]],s:[[/.[rln]ates$/,"PresentTense"],[/.[^z]ens$/,"Verb"],[/.[lstrn]us$/,kr],[/[aeiou][^aeiou]is$/,kr],[/[a-z]\'s$/,"Noun"],[/^yes+$/,Pr]],v:[[/.[^aeiou][ai][kln]ov$/,Gr]],y:[[/.[cts]hy$/,Ar],[/.[st]ty$/,Ar],[/.[gk]y$/,Ar],[/.[tnl]ary$/,Ar],[/.[oe]ry$/,kr],[/[rdntkbhs]ly$/,"Adverb"],[/...lly$/,"Adverb"],[/[bszmp]{2}y$/,Ar],[/.(gg|bb|zz)ly$/,Ar],[/.[aeiou]my$/,Ar],[/[ea]{2}zy$/,Ar],[/.[^aeiou]ity$/,kr]]},Cr="Adjective",Fr="Infinitive",Nr="PresentTense",jr="Singular",Br="PastTense",xr="Adverb",Dr="Plural",Or="Verb",Tr="LastName",Vr=[null,null,{ea:jr,ia:"Noun",ic:Cr,ly:xr,"'n":Or,"'t":Or},{que:Cr,lar:Cr,ffy:Cr,nny:Cr,rmy:Cr,azy:Cr,oid:Cr,mum:Cr,ous:Cr,end:Or,sis:jr,rol:jr,ize:Fr,ify:Fr,zes:Nr,nes:Nr,ing:"Gerund"," so":xr,"'ll":"Modal","'re":"Copula"},{teen:"Value",tors:"Noun",amed:Br,ched:Br,ends:Or,oses:Nr,fies:Nr,ects:Nr,nded:Br,cede:Fr,tage:Fr,gate:Fr,vice:jr,tion:jr,cted:Br,ette:jr,some:Cr,llen:Cr,ried:Cr,gone:Cr,made:Cr,fore:xr,less:xr,ices:Dr,ions:Dr,ints:Dr,aped:Br,lked:Br,ould:"Modal",tive:"Actor",sson:Tr,czyk:Tr,chuk:Tr,enko:Tr,akis:Tr,nsen:Tr},{fully:xr,where:xr,wards:xr,urned:Br,tized:Br,eased:Br,ances:Dr,tures:Dr,ports:Dr,ettes:Dr,ities:Dr,rough:Cr,ology:"Noun",bound:Cr,tieth:"Ordinal",ishes:Nr,tches:Nr,nssen:Tr,marek:Tr},{keeper:"Actor",logist:"Actor",auskas:Tr,teenth:"Value"},{sdottir:Tr,opoulos:Tr}],zr={":(":!0,":)":!0,":P":!0,":p":!0,":O":!0,":3":!0,":|":!0,":/":!0,":\\":!0,":$":!0,":*":!0,":@":!0,":-(":!0,":-)":!0,":-P":!0,":-p":!0,":-O":!0,":-3":!0,":-|":!0,":-/":!0,":-\\":!0,":-$":!0,":-*":!0,":-@":!0,":^(":!0,":^)":!0,":^P":!0,":^p":!0,":^O":!0,":^3":!0,":^|":!0,":^/":!0,":^\\":!0,":^$":!0,":^*":!0,":^@":!0,"):":!0,"(:":!0,"$:":!0,"*:":!0,")-:":!0,"(-:":!0,"$-:":!0,"*-:":!0,")^:":!0,"(^:":!0,"$^:":!0,"*^:":!0,"<3":!0,"=2&&br.test(n)&&yr.test(n)&&e.tag("RomanNumeral","xvii",t)},suffix:function(e,t){!function(e,t){var n=e.clean.length,r=7;n<=r&&(r=n-1);for(var a=r;a>1;a-=1){var i=e.clean.substr(n-a,n);if(!0===Vr[i.length].hasOwnProperty(i)){var o=Vr[i.length][i];e.tagSafe(o,"suffix -"+i,t);break}}}(e,t),function(e,t){var n=e.clean,r=n[n.length-1];if(!0===Er.hasOwnProperty(r))for(var a=Er[r],i=0;i35)))}(r=r.trim())&&(e.tag("Emoji","comma-emoji",t),e.text=r,e.pre=e.pre.replace(":",""),e.post=e.post.replace(":","")),e.text.match(Hr)&&(e.tag("Emoji","unicode-emoji",t),e.text=r),!0===(n=(n=r).replace(/^[:;]/,":"),zr.hasOwnProperty(n))&&(e.tag("Emoticon","emoticon-emoji",t),e.text=r)}},Mr=function(e){var t=e.termList(),n=e.world;Ir.lexicon(t,n);for(var r=0;r3&&void 0!==n[r]&&!0===n.hasOwnProperty(r)&&e.tag(n[r],"stem-"+r,t)}}))},Xr={isSingular:[/(ax|test)is$/i,/(octop|vir|radi|nucle|fung|cact|stimul)us$/i,/(octop|vir)i$/i,/(rl)f$/i,/(alias|status)$/i,/(bu)s$/i,/(al|ad|at|er|et|ed|ad)o$/i,/(ti)um$/i,/(ti)a$/i,/sis$/i,/(?:(^f)fe|(lr)f)$/i,/hive$/i,/s[aeiou]+ns$/i,/(^aeiouy|qu)y$/i,/(x|ch|ss|sh|z)$/i,/(matr|vert|ind|cort)(ix|ex)$/i,/(m|l)ouse$/i,/(m|l)ice$/i,/(antenn|formul|nebul|vertebr|vit)a$/i,/.sis$/i,/^(?!talis|.*hu)(.*)man$/i],isPlural:[/(^v)ies$/i,/ises$/i,/ives$/i,/(antenn|formul|nebul|vertebr|vit)ae$/i,/(octop|vir|radi|nucle|fung|cact|stimul)i$/i,/(buffal|tomat|tornad)oes$/i,/(analy|ba|diagno|parenthe|progno|synop|the)ses$/i,/(vert|ind|cort)ices$/i,/(matr|append)ices$/i,/(x|ch|ss|sh|s|z|o)es$/i,/is$/i,/men$/i,/news$/i,/.tia$/i,/(^f)ves$/i,/(lr)ves$/i,/(^aeiouy|qu)ies$/i,/(m|l)ice$/i,/(cris|ax|test)es$/i,/(alias|status)es$/i,/ics$/i]},Zr=["Uncountable","Pronoun","Place","Value","Person","Month","WeekDay","Holiday"],Yr=[/ss$/,/sis$/,/[^aeiou][uo]s$/,/'s$/],ea=[/i$/,/ae$/],ta=function(e,t){if(e.tags.Noun&&!e.tags.Acronym){var n=e.clean;if(e.tags.Singular||e.tags.Plural)return;if(n.length<=3)return void e.tag("Singular","short-singular",t);if(Zr.find((function(t){return e.tags[t]})))return;if(Xr.isPlural.find((function(e){return e.test(n)})))return void e.tag("Plural","plural-rules",t);if(Xr.isSingular.find((function(e){return e.test(n)})))return void e.tag("Singular","singular-rules",t);if(!0===/s$/.test(n)){if(Yr.find((function(e){return e.test(n)})))return;return void e.tag("Plural","plural-fallback",t)}if(ea.find((function(e){return e.test(n)})))return;e.tag("Singular","singular-fallback",t)}},na=["academy","administration","agence","agences","agencies","agency","airlines","airways","army","assoc","associates","association","assurance","authority","autorite","aviation","bank","banque","board","boys","brands","brewery","brotherhood","brothers","building society","bureau","cafe","caisse","capital","care","cathedral","center","central bank","centre","chemicals","choir","chronicle","church","circus","clinic","clinique","club","co","coalition","coffee","collective","college","commission","committee","communications","community","company","comprehensive","computers","confederation","conference","conseil","consulting","containers","corporation","corps","corp","council","crew","daily news","data","departement","department","department store","departments","design","development","directorate","division","drilling","education","eglise","electric","electricity","energy","ensemble","enterprise","enterprises","entertainment","estate","etat","evening news","faculty","federation","financial","fm","foundation","fund","gas","gazette","girls","government","group","guild","health authority","herald","holdings","hospital","hotel","hotels","inc","industries","institut","institute","institute of technology","institutes","insurance","international","interstate","investment","investments","investors","journal","laboratory","labs","liberation army","limited","local authority","local health authority","machines","magazine","management","marine","marketing","markets","media","memorial","mercantile exchange","ministere","ministry","military","mobile","motor","motors","musee","museum","news","news service","observatory","office","oil","optical","orchestra","organization","partners","partnership","people's party","petrol","petroleum","pharmacare","pharmaceutical","pharmaceuticals","pizza","plc","police","polytechnic","post","power","press","productions","quartet","radio","regional authority","regional health authority","reserve","resources","restaurant","restaurants","savings","school","securities","service","services","social club","societe","society","sons","standard","state police","state university","stock exchange","subcommittee","syndicat","systems","telecommunications","telegraph","television","times","tribunal","tv","union","university","utilities","workers"].reduce((function(e,t){return e[t]="Noun",e}),{}),ra=function(e){return!!e.tags.Noun&&(!(e.tags.Pronoun||e.tags.Comma||e.tags.Possessive)&&!!(e.tags.Organization||e.tags.Acronym||e.tags.Place||e.titleCase()))},aa={neighbours:Wr,case:Rr,stem:Ur,plural:ta,organizations:function(e,t){for(var n=0;n5&&e.match("#Verb+").length>=2}));if(u.found){var l=u.splitAfter("#Noun .* #Verb .* #Noun+");r=r.splitOn(l.eq(0))}return"number"==typeof t&&(r=r.get(t)),new e(r.list,this,this.world)},e},Ra=function(e){var n=function(e){function n(e,r,a){var o;return t(this,n),(o=s(this,i(n).call(this,e,r,a))).contracted=null,o}return a(n,e),r(n,[{key:"expand",value:function(){return this.list.forEach((function(e){var t=e.terms(),n=t[0].isTitleCase();t.forEach((function(e,n){e.set(e.implicit||e.text),e.implicit=void 0,n0}}),Object.defineProperty(this,"length",{get:function(){return i.list.length}}),Object.defineProperty(this,"isA",{get:function(){return"Doc"}})}return r(e,[{key:"tagger",value:function(){return Ja(this)}},{key:"pool",value:function(){return this.list.length>0?this.list[0].pool:this.all().list[0].pool}}]),e}();Pi.prototype.buildFrom=function(e){return e=e.map((function(e){return e.clone(!0)})),new Pi(e,this,this.world)},Pi.prototype.fromText=function(e){var t=tt(e,this.world,this.pool());return this.buildFrom(t)},Object.assign(Pi.prototype,$i.misc),Object.assign(Pi.prototype,$i.selections),ki(Pi);var Gi={untag:"unTag",and:"match",notIf:"ifNo",only:"if",onlyIf:"if"};Object.keys(Gi).forEach((function(e){return Pi.prototype[e]=Pi.prototype[Gi[e]]}));var Ei=Pi,Ci=new fn,Fi=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0;t&&Ci.addWords(t);var n=tt(e,Ci),r=new Ei(n,null,Ci);return r.tagger(),r};return Fi.tokenize=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0;t&&Ci.addWords(t);var n=tt(e,Ci),r=new Ei(n,null,Ci);return r},Fi.extend=function(e){return e(Ei,Ci),this},Fi.clone=function(){return Ci=Ci.clone(),this},Fi.load=function(e){var t=nt(e,Ci);return new Ei(t,null,Ci)},Fi.verbose=function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return Ci.verbose(e),this},Fi.version="12.0.0",Fi.import=Fi.load,Fi})); diff --git a/builds/compromise.mjs b/builds/compromise.mjs new file mode 100644 index 000000000..11f5d4c60 --- /dev/null +++ b/builds/compromise.mjs @@ -0,0 +1,12414 @@ +function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); +} + +function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); +} + +//this is a not-well-thought-out way to reduce our dependence on `object===object` stuff +var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split(''); //generates a unique id for this term + +function makeId(str) { + str = str || '_'; + var text = str + '-'; + + for (var i = 0; i < 7; i++) { + text += chars[Math.floor(Math.random() * chars.length)]; + } + + return text; +} + +var _id = makeId; + +//a hugely-ignorant, and widely subjective transliteration of latin, cryllic, greek unicode characters to english ascii. +//approximate visual (not semantic or phonetic) relationship between unicode and ascii characters +//http://en.wikipedia.org/wiki/List_of_Unicode_characters +//https://docs.google.com/spreadsheet/ccc?key=0Ah46z755j7cVdFRDM1A2YVpwa1ZYWlpJM2pQZ003M0E +var compact = { + '!': '¡', + '?': '¿Ɂ', + '"': '“”"❝❞', + "'": '‘‛❛❜', + '-': '—–', + a: 'ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАадѦѧӐӑӒӓƛɅæ', + b: 'ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬвъьѢѣҌҍ', + c: '¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾСсєҀҁҪҫ', + d: 'ÐĎďĐđƉƊȡƋƌǷ', + e: 'ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ', + f: 'ƑƒϜϝӺӻҒғſ', + g: 'ĜĝĞğĠġĢģƓǤǥǦǧǴǵ', + h: 'ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ', + I: 'ÌÍÎÏ', + i: 'ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії', + j: 'ĴĵǰȷɈɉϳЈј', + k: 'ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ', + l: 'ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ', + m: 'ΜϺϻМмӍӎ', + n: 'ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ', + o: 'ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ', + p: 'ƤƿΡρϷϸϼРрҎҏÞ', + q: 'Ɋɋ', + r: 'ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ', + s: 'ŚśŜŝŞşŠšƧƨȘșȿЅѕ', + t: 'ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮТт', + u: 'µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύ', + v: 'νѴѵѶѷ', + w: 'ŴŵƜωώϖϢϣШЩшщѡѿ', + x: '×ΧχϗϰХхҲҳӼӽӾӿ', + y: 'ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ', + z: 'ŹźŻżŽžƩƵƶȤȥɀΖζ' +}; //decompress data into two hashes + +var unicode = {}; +Object.keys(compact).forEach(function (k) { + compact[k].split('').forEach(function (s) { + unicode[s] = k; + }); +}); + +var killUnicode = function killUnicode(str) { + var chars = str.split(''); + chars.forEach(function (s, i) { + if (unicode[s]) { + chars[i] = unicode[s]; + } + }); + return chars.join(''); +}; + +var unicode_1 = killUnicode; // console.log(killUnicode('bjŏȒk—Ɏó')); + +var periodAcronym = /([A-Z]\.)+[A-Z]?,?$/; +var oneLetterAcronym = /^[A-Z]\.,?$/; +var noPeriodAcronym = /[A-Z]{2,}('s|,)?$/; +var lowerCaseAcronym = /([a-z]\.){2,}[a-z]\.?$/; + +var isAcronym = function isAcronym(str) { + //like N.D.A + if (periodAcronym.test(str) === true) { + return true; + } //like c.e.o + + + if (lowerCaseAcronym.test(str) === true) { + return true; + } //like 'F.' + + + if (oneLetterAcronym.test(str) === true) { + return true; + } //like NDA + + + if (noPeriodAcronym.test(str) === true) { + return true; + } + + return false; +}; + +var isAcronym_1 = isAcronym; + +var hasSlash = /[a-z\u00C0-\u00FF] ?\/ ?[a-z\u00C0-\u00FF]/; +/** some basic operations on a string to reduce noise */ + +var clean = function clean(str) { + str = str || ''; + str = str.toLowerCase(); + str = str.trim(); + var original = str; //(very) rough ASCII transliteration - bjŏrk -> bjork + + str = unicode_1(str); //rough handling of slashes - 'see/saw' + + if (hasSlash.test(str) === true) { + str = str.replace(/\/.*/, ''); + } //#tags, @mentions + + + str = str.replace(/^[#@]/, ''); //punctuation + + str = str.replace(/[,;.!?]+$/, ''); // coerce single curly quotes + + str = str.replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g, "'"); // coerce double curly quotes + + str = str.replace(/[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g, '"'); //coerce Unicode ellipses + + str = str.replace(/\u2026/g, '...'); //en-dash + + str = str.replace(/\u2013/g, '-'); //lookin'->looking (make it easier for conjugation) + + if (/[a-z][^aeiou]in['’]$/.test(str) === true) { + str = str.replace(/in['’]$/, 'ing'); + } //turn re-enactment to reenactment + + + if (/^(re|un)-?[^aeiou]./.test(str) === true) { + str = str.replace('-', ''); + } //strip leading & trailing grammatical punctuation + + + if (/^[:;]/.test(str) === false) { + str = str.replace(/\.{3,}$/g, ''); + str = str.replace(/[",\.!:;\?\)]+$/g, ''); + str = str.replace(/^['"\(]+/g, ''); + } //do this again.. + + + str = str.trim(); //oh shucks, + + if (str === '') { + str = original; + } //compact acronyms + + + if (isAcronym_1(str)) { + str = str.replace(/\./g, ''); + } //nice-numbers + + + str = str.replace(/([0-9]),([0-9])/g, '$1$2'); + return str; +}; + +var clean_1 = clean; // console.log(normalize('Dr. V Cooper')); + +/** reduced is one step further than clean */ +var reduced = function reduced(str) { + // remove apostrophes + str = str.replace(/['’]s$/, ''); + str = str.replace(/s['’]$/, 's'); + return str; +}; + +var reduce = reduced; + +//all punctuation marks, from https://en.wikipedia.org/wiki/Punctuation +//we have slightly different rules for start/end - like #hashtags. + +var startings = /^[ \n\t\.’'\[\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\-?‘’;\/⁄·\&*\•^†‡°¡¿※№÷׺ª%‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\u0022|\uFF02|\u0027|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\u00AB|\u2039|\u2035|\u2036|\u2037|\u301D|\u0060|\u301F]+/; +var endings = /[ \n\t\.’'\[\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\-?‘’;\/⁄·\&*@\•^†‡°¡¿※#№÷׺ª‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\u0022|\uFF02|\u0027|\u201D|\u2019|\u201D|\u2019|\u201D|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4|\u301E]+$/; //money = ₵¢₡₢$₫₯֏₠€ƒ₣₲₴₭₺₾ℳ₥₦₧₱₰£៛₽₹₨₪৳₸₮₩¥ + +var hasSlash$1 = /\//; +var hasApostrophe = /['’]/; +var minusNumber = /^[-+\.][0-9]/; +/** turn given text into a parsed-up object + * seperate the 'meat' of the word from the whitespace+punctuation + */ + +var parseTerm = function parseTerm(str) { + var original = str; + var pre = ''; + var post = ''; + str = str.replace(startings, function (found) { + pre = found; // support '-40' + + if ((pre === '-' || pre === '+' || pre === '.') && minusNumber.test(str)) { + pre = ''; + return found; + } + + return ''; + }); + str = str.replace(endings, function (found) { + post = found; // keep s-apostrophe - "flanders'" or "chillin'" + + if (hasApostrophe.test(found) && /[sn]['’]$/.test(original) && hasApostrophe.test(pre) === false) { + post = post.replace(hasApostrophe, ''); + return "'"; + } + + return ''; + }); //we went too far.. + + if (str === '') { + // do a very mild parse, and hope for the best. + original = original.replace(/ *$/, function (after) { + post = after || ''; + return ''; + }); + str = original; + pre = ''; + post = post; + } // create the various forms of our text, + + + var clean = clean_1(str); + var parsed = { + text: str, + clean: clean, + reduced: reduce(clean), + pre: pre, + post: post + }; // support aliases for slashes + + if (hasSlash$1.test(str)) { + str.split(hasSlash$1).forEach(function (word) { + parsed.alias = parsed.alias || {}; + parsed.alias[word.trim()] = true; + }); + } + + return parsed; +}; + +var parse = parseTerm; + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +var _01Case = createCommonjsModule(function (module, exports) { + var titleCase = /^[A-Z][a-z'\u00C0-\u00FF]/; + var upperCase = /^[A-Z]+s?$/; + /** convert all text to uppercase */ + + exports.toUpperCase = function () { + this.text = this.text.toUpperCase(); + return this; + }; + /** convert all text to lowercase */ + + + exports.toLowerCase = function () { + this.text = this.text.toLowerCase(); + return this; + }; + /** only set the first letter to uppercase + * leave any existing uppercase alone + */ + + + exports.toTitleCase = function () { + this.text = this.text.replace(/^ *[a-z\u00C0-\u00FF]/, function (x) { + return x.toUpperCase(); + }); //support unicode? + + return this; + }; + /** if all letters are uppercase */ + + + exports.isUpperCase = function () { + return upperCase.test(this.text); + }; + /** if the first letter is uppercase, and the rest are lowercase */ + + + exports.isTitleCase = function () { + return titleCase.test(this.text); + }; + + exports.titleCase = exports.isTitleCase; +}); +var _01Case_1 = _01Case.toUpperCase; +var _01Case_2 = _01Case.toLowerCase; +var _01Case_3 = _01Case.toTitleCase; +var _01Case_4 = _01Case.isUpperCase; +var _01Case_5 = _01Case.isTitleCase; +var _01Case_6 = _01Case.titleCase; + +// these methods are called with '@hasComma' in the match syntax +// various unicode quotation-mark formats +var startQuote = "(\"|\uFF02|'|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\xAB|\u2039|\u2035|\u2036|\u2037|\u301D|`|\u301F)"; +var endQuote = "(\"|\uFF02|'|\u201D|\u2019|\u201D|\u2019|\u201D|\u201D|\u2019|\xBB|\u203A|\u2032|\u2033|\u2034|\u301E|\xB4|\u301E)"; +/** search the term's 'post' punctuation */ + +var hasPost = function hasPost(punct) { + return this.post.indexOf(punct) !== -1; +}; +/** search the term's 'pre' punctuation */ + + +var hasPre = function hasPre(punct) { + return this.pre.indexOf(punct) !== -1; +}; +/** does it have a quotation symbol? */ + + +var hasQuote = function hasQuote() { + return startQuote.test(this.pre) || endQuote.test(this.post); +}; +/** does it have a comma? */ + + +var hasComma = function hasComma() { + return this.hasPost(','); +}; +/** does it end in a period? */ + + +var hasPeriod = function hasPeriod() { + return this.hasPost('.') === true && this.hasPost('...') === false; +}; +/** does it end in an exclamation */ + + +var hasExclamation = function hasExclamation() { + return this.hasPost('!'); +}; +/** does it end with a question mark? */ + + +var hasQuestionMark = function hasQuestionMark() { + return this.hasPost('?') || this.hasPost('¿'); +}; +/** is there a ... at the end? */ + + +var hasEllipses = function hasEllipses() { + return this.hasPost('..') || this.hasPost('…'); +}; +/** is there a semicolon after this word? */ + + +var hasSemicolon = function hasSemicolon() { + return this.hasPost(';'); +}; +/** is there a slash '/' in this word? */ + + +var hasSlash$2 = function hasSlash() { + return /\//.test(this.text); +}; +/** a hyphen connects two words like-this */ + + +var hasHyphen = function hasHyphen() { + var hyphen = /(-|–|—)/; + return hyphen.test(this.post) || hyphen.test(this.pre); +}; +/** a dash separates words - like that */ + + +var hasDash = function hasDash() { + var hyphen = / (-|–|—) /; + return hyphen.test(this.post) || hyphen.test(this.pre); +}; +/** is it multiple words combinded */ + + +var hasContraction = function hasContraction() { + return Boolean(this.implicit); +}; +/** try to sensibly put this punctuation mark into the term */ + + +var addPunctuation = function addPunctuation(punct) { + // dont add doubles + if (punct === ',' || punct === ';') { + this.post = this.post.replace(punct, ''); + } + + this.post = punct + this.post; + return this; +}; + +var _02Punctuation = { + hasPost: hasPost, + hasPre: hasPre, + hasQuote: hasQuote, + hasComma: hasComma, + hasPeriod: hasPeriod, + hasExclamation: hasExclamation, + hasQuestionMark: hasQuestionMark, + hasEllipses: hasEllipses, + hasSemicolon: hasSemicolon, + hasSlash: hasSlash$2, + hasHyphen: hasHyphen, + hasDash: hasDash, + hasContraction: hasContraction, + addPunctuation: addPunctuation +}; + +//declare it up here +var wrapMatch = function wrapMatch() {}; +/** ignore optional/greedy logic, straight-up term match*/ + + +var doesMatch = function doesMatch(t, reg, index, length) { + // support id matches + if (reg.id === t.id) { + return true; + } // support '.' + + + if (reg.anything === true) { + return true; + } // support '^' (in parentheses) + + + if (reg.start === true && index !== 0) { + return false; + } // support '$' (in parentheses) + + + if (reg.end === true && index !== length - 1) { + return false; + } //support a text match + + + if (reg.word !== undefined) { + //match contractions + if (t.implicit !== null && t.implicit === reg.word) { + return true; + } // term aliases for slashes and things + + + if (t.alias !== undefined && t.alias.hasOwnProperty(reg.word)) { + return true; + } // support ~ match + + + if (reg.soft === true && reg.word === t.root) { + return true; + } //match either .clean or .text + + + return reg.word === t.clean || reg.word === t.text || reg.word === t.reduced; + } //support #Tag + + + if (reg.tag !== undefined) { + return t.tags[reg.tag] === true; + } //support @method + + + if (reg.method !== undefined) { + if (typeof t[reg.method] === 'function' && t[reg.method]() === true) { + return true; + } + + return false; + } //support /reg/ + + + if (reg.regex !== undefined) { + return reg.regex.test(t.clean); + } //support (one|two) + + + if (reg.choices !== undefined) { + // try to support && operator + if (reg.operator === 'and') { + // must match them all + return reg.choices.every(function (r) { + return wrapMatch(t, r, index, length); + }); + } // or must match one + + + return reg.choices.some(function (r) { + return wrapMatch(t, r, index, length); + }); + } + + return false; +}; // wrap result for !negative match logic + + +wrapMatch = function wrapMatch(t, reg, index, length) { + var result = doesMatch(t, reg, index, length); + + if (reg.negative === true) { + return !result; + } + + return result; +}; + +var _doesMatch = wrapMatch; + +var boring = {}; +/** check a match object against this term */ + +var doesMatch_1 = function doesMatch_1(reg, index, length) { + return _doesMatch(this, reg, index, length); +}; +/** does this term look like an acronym? */ + + +var isAcronym_1$1 = function isAcronym_1$1() { + return isAcronym_1(this.text); +}; +/** is this term implied by a contraction? */ + + +var isImplicit = function isImplicit() { + return this.text === '' && Boolean(this.implicit); +}; +/** does the term have at least one good tag? */ + + +var isKnown = function isKnown() { + return Object.keys(this.tags).some(function (t) { + return boring[t] !== true; + }); +}; +/** cache the root property of the term */ + + +var setRoot = function setRoot(world) { + var transform = world.transforms; + var str = this.implicit || this.clean; + + if (this.tags.Plural) { + str = transform.toSingular(str, world); + } + + if (this.tags.Verb && !this.tags.Negative && !this.tags.Infinitive) { + var tense = null; + + if (this.tags.PastTense) { + tense = 'PastTense'; + } else if (this.tags.Gerund) { + tense = 'Gerund'; + } else if (this.tags.PresentTense) { + tense = 'PresentTense'; + } else if (this.tags.Participle) { + tense = 'Participle'; + } else if (this.tags.Actor) { + tense = 'Actor'; + } + + str = transform.toInfinitive(str, world, tense); + } + + this.root = str; +}; + +var _03Misc = { + doesMatch: doesMatch_1, + isAcronym: isAcronym_1$1, + isImplicit: isImplicit, + isKnown: isKnown, + setRoot: setRoot +}; + +var hasSpace = /[\s-]/; +var isUpperCase = /^[A-Z-]+$/; // const titleCase = str => { +// return str.charAt(0).toUpperCase() + str.substr(1) +// } + +/** return various text formats of this term */ + +var textOut = function textOut(options, showPre, showPost) { + options = options || {}; + var word = this.text; + var before = this.pre; + var after = this.post; // -word- + + if (options.reduced === true) { + word = this.reduced || ''; + } + + if (options.root === true) { + word = this.root || ''; + } + + if (options.implicit === true && this.implicit) { + word = this.implicit || ''; + } + + if (options.normal === true) { + word = this.clean || this.text || ''; + } + + if (options.root === true) { + word = this.root || this.reduced || ''; + } + + if (options.unicode === true) { + word = unicode_1(word); + } // cleanup case + + + if (options.titlecase === true) { + if (this.tags.ProperNoun && !this.titleCase()) ; else if (this.tags.Acronym) { + word = word.toUpperCase(); //uppercase acronyms + } else if (isUpperCase.test(word) && !this.tags.Acronym) { + // lowercase everything else + word = word.toLowerCase(); + } + } + + if (options.lowercase === true) { + word = word.toLowerCase(); + } // remove the '.'s from 'F.B.I.' (safely) + + + if (options.acronyms === true && this.tags.Acronym) { + word = word.replace(/\./g, ''); + } // -before/after- + + + if (options.whitespace === true || options.root) { + before = ''; + after = ' '; + + if ((hasSpace.test(this.post) === false || options.last) && !this.implicit) { + after = ''; + } + } + + if (options.punctuation === true && !options.root) { + //normalized end punctuation + if (this.hasPost('.') === true) { + after = '.' + after; + } else if (this.hasPost('?') === true) { + after = '?' + after; + } else if (this.hasPost('!') === true) { + after = '!' + after; + } else if (this.hasPost(',') === true) { + after = ',' + after; + } else if (this.hasEllipses() === true) { + after = '...' + after; + } + } + + if (showPre !== true) { + before = ''; + } + + if (showPost !== true) { + // let keep = after.match(/\)/) || '' + after = ''; //keep //after.replace(/[ .?!,]+/, '') + } // remove the '.' from 'Mrs.' (safely) + + + if (options.abbreviations === true && this.tags.Abbreviation) { + after = after.replace(/^\./, ''); + } + + return before + word + after; +}; + +var _04Text = { + textOut: textOut +}; + +var boringTags = { + Auxiliary: 1, + Possessive: 1 +}; +/** a subjective ranking of tags kinda tfidf-based */ + +var rankTags = function rankTags(term, world) { + var tags = Object.keys(term.tags); + var tagSet = world.tags; + tags = tags.sort(function (a, b) { + //bury the tags we dont want + if (boringTags[b] || !tagSet[b]) { + return -1; + } // unknown tags are interesting + + + if (!tagSet[b]) { + return 1; + } + + if (!tagSet[a]) { + return 0; + } // then sort by #of parent tags (most-specific tags first) + + + if (tagSet[a].lineage.length > tagSet[b].lineage.length) { + return 1; + } + + if (tagSet[a].isA.length > tagSet[b].isA.length) { + return -1; + } + + return 0; + }); + return tags; +}; + +var _bestTag = rankTags; + +var jsonDefault = { + text: true, + tags: true, + implicit: true, + clean: false, + id: false, + index: false, + offset: false, + whitespace: false, + bestTag: false +}; +/** return various metadata for this term */ + +var json = function json(options, world) { + options = options || {}; + options = Object.assign({}, jsonDefault, options); + var result = {}; // default on + + if (options.text) { + result.text = this.text; + } + + if (options.normal) { + result.normal = this.normal; + } + + if (options.tags) { + result.tags = Object.keys(this.tags); + } // default off + + + if (options.clean) { + result.clean = this.clean; + } + + if (options.id || options.offset) { + result.id = this.id; + } + + if (options.implicit && this.implicit !== null) { + result.implicit = this.implicit; + } + + if (options.whitespace) { + result.pre = this.pre; + result.post = this.post; + } + + if (options.bestTag) { + result.bestTag = _bestTag(this, world)[0]; + } + + return result; +}; + +var _05Json = { + json: json +}; + +var methods = Object.assign({}, _01Case, _02Punctuation, _03Misc, _04Text, _05Json); + +/** add spaces at the end */ +var padEnd = function padEnd(str, width) { + str = str.toString(); + + while (str.length < width) { + str += ' '; + } + + return str; +}; +/** output for verbose-mode */ + + +var logTag = function logTag(t, tag, reason) { + var log = '\x1b[33m' + padEnd(t.clean, 15) + '\x1b[0m + \x1b[32m' + tag + '\x1b[0m '; + + if (reason) { + log = padEnd(log, 35) + ' ' + reason + ''; + } + + console.log(log); +}; +/** output for verbose mode */ + + +var logUntag = function logUntag(t, tag, reason) { + var log = '\x1b[33m' + padEnd(t.clean, 3) + ' \x1b[31m - #' + tag + '\x1b[0m '; + + if (reason) { + log = padEnd(log, 35) + ' ' + reason; + } + + console.log(log); +}; + +var isArray = function isArray(arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; +}; + +var titleCase = function titleCase(str) { + return str.charAt(0).toUpperCase() + str.substr(1); +}; + +var fns = { + logTag: logTag, + logUntag: logUntag, + isArray: isArray, + titleCase: titleCase +}; + +/** add a tag, and its descendents, to a term */ + +var addTag = function addTag(t, tag, reason, world) { + var tagset = world.tags; //support '.' or '-' notation for skipping the tag + + if (tag === '' || tag === '.' || tag === '-') { + return; + } + + if (tag[0] === '#') { + tag = tag.replace(/^#/, ''); + } + + tag = fns.titleCase(tag); //if we already got this one + + if (t.tags[tag] === true) { + return; + } // log it? + + + var isVerbose = world.isVerbose(); + + if (isVerbose === true) { + fns.logTag(t, tag, reason); + } //add tag + + + t.tags[tag] = true; //whee! + //check tagset for any additional things to do... + + if (tagset.hasOwnProperty(tag) === true) { + //add parent Tags + tagset[tag].isA.forEach(function (down) { + t.tags[down] = true; + + if (isVerbose === true) { + fns.logTag(t, '→ ' + down); + } + }); //remove any contrary tags + + t.unTag(tagset[tag].notA, '←', world); + } +}; +/** support an array of tags */ + + +var addTags = function addTags(term, tags, reason, world) { + if (fns.isArray(tags) === true) { + tags.forEach(function (tag) { + return addTag(term, tag, reason, world); + }); + } else { + addTag(term, tags, reason, world); + } +}; + +var add = addTags; + +/** remove this tag, and its descentents from the term */ + +var unTag = function unTag(t, tag, reason, world) { + var isVerbose = world.isVerbose(); //support '*' for removing all tags + + if (tag === '*') { + t.tags = {}; + return t; + } // remove the tag + + + if (t.tags[tag] === true && t.tags.hasOwnProperty(tag) === true) { + delete t.tags[tag]; //log in verbose-mode + + if (isVerbose === true) { + fns.logUntag(t, tag, reason); + } + } //delete downstream tags too + + + var tagset = world.tags; + + if (tagset[tag]) { + var lineage = tagset[tag].lineage; + + for (var i = 0; i < lineage.length; i++) { + // unTag(t, also[i], ' - - - ', world) //recursive + if (t.tags[lineage[i]] === true) { + delete t.tags[lineage[i]]; + + if (isVerbose === true) { + fns.logUntag(t, ' - ' + lineage[i]); + } + } + } + } + + return t; +}; //handle an array of tags + + +var untagAll = function untagAll(term, tags, reason, world) { + if (fns.isArray(tags) === true) { + tags.forEach(function (tag) { + return unTag(term, tag, reason, world); + }); + } else { + unTag(term, tags, reason, world); + } +}; + +var unTag_1 = untagAll; + +var canBe = function canBe(term, tag, world) { + var tagset = world.tags; // cleanup tag + + if (tag[0] === '#') { + tag = tag.replace(/^#/, ''); + } //fail-fast + + + if (tagset[tag] === undefined) { + return true; + } //loop through tag's contradictory tags + + + var enemies = tagset[tag].notA || []; + + for (var i = 0; i < enemies.length; i++) { + if (term.tags[enemies[i]] === true) { + return false; + } + } + + if (tagset[tag].isA !== undefined) { + return canBe(term, tagset[tag].isA, world); //recursive + } + + return true; +}; + +var canBe_1 = canBe; + +/** add a tag or tags, and their descendents to this term + * @param {string | string[]} tags - a tag or tags + * @param {string?} [reason] a clue for debugging + */ + +var tag_1 = function tag_1(tags, reason, world) { + add(this, tags, reason, world); + return this; +}; +/** only tag this term if it's consistent with it's current tags */ + + +var tagSafe = function tagSafe(tags, reason, world) { + if (canBe_1(this, tags, world)) { + add(this, tags, reason, world); + } + + return this; +}; +/** remove a tag or tags, and their descendents from this term + * @param {string | string[]} tags - a tag or tags + * @param {string?} [reason] a clue for debugging + */ + + +var unTag_1$1 = function unTag_1$1(tags, reason, world) { + unTag_1(this, tags, reason, world); + return this; +}; +/** is this tag consistent with the word's current tags? + * @param {string | string[]} tags - a tag or tags + * @returns {boolean} + */ + + +var canBe_1$1 = function canBe_1$1(tags, world) { + return canBe_1(this, tags, world); +}; + +var tag = { + tag: tag_1, + tagSafe: tagSafe, + unTag: unTag_1$1, + canBe: canBe_1$1 +}; + +var Term = +/*#__PURE__*/ +function () { + function Term() { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + + _classCallCheck(this, Term); + + text = String(text); + var obj = parse(text); // the various forms of our text + + this.text = obj.text || ''; + this.clean = obj.clean; + this.reduced = obj.reduced; + this.root = null; + this.implicit = null; + this.pre = obj.pre || ''; + this.post = obj.post || ''; + this.tags = {}; + this.prev = null; + this.next = null; + this.id = _id(obj.clean); + this.isA = 'Term'; // easier than .constructor... + // support alternative matches + + if (obj.alias) { + this.alias = obj.alias; + } + } + /** set the text of the Term to something else*/ + + + _createClass(Term, [{ + key: "set", + value: function set(str) { + var obj = parse(str); + this.text = obj.text; + this.clean = obj.clean; + return this; + } + }]); + + return Term; +}(); +/** create a deep-copy of this term */ + + +Term.prototype.clone = function () { + var term = new Term(this.text); + term.pre = this.pre; + term.post = this.post; + term.tags = Object.assign({}, this.tags); //use the old id, so it can be matched with .match(doc) + // term.id = this.id + + return term; +}; + +Object.assign(Term.prototype, methods); +Object.assign(Term.prototype, tag); +var Term_1 = Term; + +/** return a flat array of Term objects */ +var terms = function terms(n) { + var terms = [this.pool.get(this.start)]; + + if (this.length === 0) { + return []; + } + + for (var i = 0; i < this.length - 1; i += 1) { + var id = terms[terms.length - 1].next; + + if (id === null) { + // throw new Error('linked-list broken') + console.error("Compromise error: Linked list broken in phrase '" + this.start + "'"); + break; + } + + var term = this.pool.get(id); + terms.push(term); //return this one? + + if (n !== undefined && n === i) { + return terms[n]; + } + } + + if (n !== undefined) { + return terms[n]; + } + + return terms; +}; +/** return a shallow or deep copy of this phrase */ + + +var clone = function clone(isShallow) { + var _this = this; + + if (isShallow) { + return this.buildFrom(this.start, this.length); + } //how do we clone part of the pool? + + + var terms = this.terms(); + var newTerms = terms.map(function (t) { + return t.clone(); + }); //connect these new ids up + + newTerms.forEach(function (t, i) { + //add it to the pool.. + _this.pool.add(t); + + if (newTerms[i + 1]) { + t.next = newTerms[i + 1].id; + } + + if (newTerms[i - 1]) { + t.prev = newTerms[i - 1].id; + } + }); + return this.buildFrom(newTerms[0].id, newTerms.length); +}; +/** return last term object */ + + +var lastTerm = function lastTerm() { + var terms = this.terms(); + return terms[terms.length - 1]; +}; +/** quick lookup for a term id */ + + +var hasId = function hasId(wantId) { + if (this.length === 0 || !wantId) { + return false; + } + + if (this.start === wantId) { + return true; + } + + var lastId = this.start; + + for (var i = 0; i < this.length - 1; i += 1) { + var term = this.pool.get(lastId); + + if (term === undefined) { + console.error("Compromise error: Linked list broken. Missing term '".concat(lastId, "' in phrase '").concat(this.start, "'\n")); // throw new Error('linked List error') + + return false; + } + + if (term.next === wantId) { + return true; + } + + lastId = term.next; + } + + return false; +}; +/** how many seperate, non-empty words is it? */ + + +var wordCount = function wordCount() { + return this.terms().filter(function (t) { + return t.text !== ''; + }).length; +}; + +var _01Utils = { + terms: terms, + clone: clone, + lastTerm: lastTerm, + hasId: hasId, + wordCount: wordCount +}; + +var trimEnd = function trimEnd(str) { + return str.replace(/ +$/, ''); +}; +/** produce output in the given format */ + + +var text = function text() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var isFirst = arguments.length > 1 ? arguments[1] : undefined; + var isLast = arguments.length > 2 ? arguments[2] : undefined; + + if (typeof options === 'string') { + if (options === 'normal') { + options = { + whitespace: true, + unicode: true, + lowercase: true, + punctuation: true, + acronyms: true, + abbreviations: true, + implicit: true, + normal: true + }; + } else if (options === 'clean') { + options = { + titlecase: false, + lowercase: true, + punctuation: true, + whitespace: true, + unicode: true, + implicit: true + }; + } else if (options === 'reduced') { + options = { + titlecase: false, + lowercase: true, + punctuation: false, + //FIXME: reversed + whitespace: true, + unicode: true, + implicit: true, + reduced: true + }; + } else if (options === 'root') { + options = { + titlecase: false, + lowercase: true, + punctuation: true, + whitespace: true, + unicode: true, + implicit: true, + root: true + }; + } else { + options = {}; + } + } + + var terms = this.terms(); //this this phrase a complete sentence? + + var isFull = false; + + if (terms[0] && terms[0].prev === null && terms[terms.length - 1].next === null) { + isFull = true; + } + + var text = terms.reduce(function (str, t, i) { + options.last = isLast && i === terms.length - 1; + var showPre = true; + var showPost = true; + + if (isFull === false) { + // dont show beginning whitespace + if (i === 0 && isFirst) { + showPre = false; + } // dont show end-whitespace + + + if (i === terms.length - 1 && isLast) { + showPost = false; + } + } + + var txt = t.textOut(options, showPre, showPost); // if (options.titlecase && i === 0) { + // txt = titleCase(txt) + // } + + return str + txt; + }, ''); //full-phrases show punctuation, but not whitespace + + if (isFull === true && isLast) { + text = trimEnd(text); + } + + if (options.trim) { + text = text.trim(); + } + + return text; +}; + +var _02Text = { + text: text +}; + +/** remove start and end whitespace */ +var trim = function trim() { + var terms = this.terms(); + + if (terms.length > 0) { + //trim starting + terms[0].pre = terms[0].pre.replace(/^\s+/, ''); //trim ending + + var lastTerm = terms[terms.length - 1]; + lastTerm.post = lastTerm.post.replace(/\s+$/, ''); + } + + return this; +}; + +var _03Change = { + trim: trim +}; + +var endOfSentence = /[.?!]\s*$/; // replacing a 'word.' with a 'word!' + +var combinePost = function combinePost(before, after) { + //only transfer the whitespace + if (endOfSentence.test(after)) { + var whitespace = before.match(/\s*$/); + return after + whitespace; + } + + return before; +}; //add whitespace to the start of the second bit + + +var addWhitespace = function addWhitespace(beforeTerms, newTerms) { + // add any existing pre-whitespace to beginning + newTerms[0].pre = beforeTerms[0].pre; + var lastTerm = beforeTerms[beforeTerms.length - 1]; //add any existing punctuation to end of our new terms + + var newTerm = newTerms[newTerms.length - 1]; + newTerm.post = combinePost(lastTerm.post, newTerm.post); // remove existing punctuation + + lastTerm.post = ''; //before ←[space] - after + + if (lastTerm.post === '') { + lastTerm.post += ' '; + } +}; //insert this segment into the linked-list + + +var stitchIn = function stitchIn(main, newPhrase) { + // console.log(main.text(), newPhrase.text()) + var afterId = main.lastTerm().next; //connect ours in (main → newPhrase) + + main.lastTerm().next = newPhrase.start; //stich the end in (newPhrase → after) + + newPhrase.lastTerm().next = afterId; //do it backwards, too + + if (afterId) { + // newPhrase ← after + var afterTerm = main.pool.get(afterId); + afterTerm.prev = newPhrase.lastTerm().id; + } // before ← newPhrase + + + var beforeId = main.terms(0).id; + + if (beforeId) { + var newTerm = newPhrase.terms(0); + newTerm.prev = beforeId; + } +}; // avoid stretching a phrase twice. + + +var unique = function unique(list) { + return list.filter(function (o, i) { + return list.indexOf(o) === i; + }); +}; //append one phrase onto another. + + +var appendPhrase = function appendPhrase(before, newPhrase, doc) { + var beforeTerms = before.terms(); //spruce-up the whitespace issues + + addWhitespace(beforeTerms, newPhrase.terms()); //insert this segment into the linked-list + + stitchIn(before, newPhrase); // stretch! + // make each effected phrase longer + + var toStretch = [before]; + var hasId = before.start; + var docs = [doc]; + docs = docs.concat(doc.parents()); // find them all! + + docs.forEach(function (parent) { + // only the phrases that should change + var shouldChange = parent.list.filter(function (p) { + return p.hasId(hasId); + }); + toStretch = toStretch.concat(shouldChange); + }); // don't double-count a phrase + + toStretch = unique(toStretch); // console.log(toStretch) + + toStretch.forEach(function (p) { + p.length += newPhrase.length; + }); + return before; +}; + +var append = appendPhrase; + +var hasSpace$1 = / /; //a new space needs to be added, either on the new phrase, or the old one +// '[new] [◻old]' -or- '[old] [◻new] [old]' + +var addWhitespace$1 = function addWhitespace(newTerms) { + //add a space before our new text? + // add a space after our text + var lastTerm = newTerms[newTerms.length - 1]; + + if (hasSpace$1.test(lastTerm.post) === false) { + lastTerm.post += ' '; + } // let term = original.pool.get(original.start) + // if (term.prev) { + // //add our space ahead of our new terms + // let firstWord = newTerms[0] + // if (hasSpace.test(firstWord.post) === false) { + // firstWord.post += ' ' + // } + // return + // } + //otherwise, add our space to the start of original + // if (hasSpace.test(term.pre) === false) { + // term.pre = ' ' + term.pre + // } + + + return; +}; //insert this segment into the linked-list + + +var stitchIn$1 = function stitchIn(main, newPhrase, newTerms) { + // [newPhrase] → [main] + var lastTerm = newTerms[newTerms.length - 1]; + lastTerm.next = main.start; // [before] → [main] + + var pool = main.pool; + var start = pool.get(main.start); + + if (start.prev) { + var before = pool.get(start.prev); + before.next = newPhrase.start; + } //do it backwards, too + // before ← newPhrase + + + newTerms[0].prev = main.terms(0).prev; // newPhrase ← main + + main.terms(0).prev = lastTerm.id; +}; //recursively increase the length of all parent phrases +// const stretchAll = function(doc, oldStart, newPhrase) { +// //find our phrase to stretch +// let phrase = doc.list.find(p => p.hasId(oldStart) || p.hasId(newPhrase.start)) +// if (phrase === undefined) { +// console.error('compromise error: Prepend missing start - ' + oldStart) +// return +// } +// //should we update the phrase's starting? +// if (phrase.start === oldStart) { +// phrase.start = newPhrase.start +// } +// // console.log(newPhrase) +// phrase.length += newPhrase.length +// if (doc.from) { +// stretchAll(doc.from, oldStart, newPhrase) +// } +// } + + +var unique$1 = function unique(list) { + return list.filter(function (o, i) { + return list.indexOf(o) === i; + }); +}; //append one phrase onto another + + +var joinPhrase = function joinPhrase(original, newPhrase, doc) { + var starterId = original.start; + var newTerms = newPhrase.terms(); //spruce-up the whitespace issues + + addWhitespace$1(newTerms); //insert this segment into the linked-list + + stitchIn$1(original, newPhrase, newTerms); //increase the length of our phrases + + var toStretch = [original]; + var docs = [doc]; + docs = docs.concat(doc.parents()); + docs.forEach(function (d) { + // only the phrases that should change + var shouldChange = d.list.filter(function (p) { + return p.hasId(starterId) || p.hasId(newPhrase.start); + }); + toStretch = toStretch.concat(shouldChange); + }); // don't double-count + + toStretch = unique$1(toStretch); // stretch these phrases + + toStretch.forEach(function (p) { + p.length += newPhrase.length; // change the start too, if necessary + + if (p.start === starterId) { + p.start = newPhrase.start; + } + }); + return original; +}; + +var prepend = joinPhrase; + +//recursively decrease the length of all the parent phrases +var shrinkAll = function shrinkAll(doc, id, deleteLength, after) { + var arr = doc.parents(); + arr.push(doc); + arr.forEach(function (d) { + //find our phrase to shrink + var phrase = d.list.find(function (p) { + return p.hasId(id); + }); + + if (!phrase) { + return; + } + + phrase.length -= deleteLength; // does it start with this soon-removed word? + + if (phrase.start === id) { + phrase.start = after.id; + } + }); // cleanup empty phrase objects + + doc.list = doc.list.filter(function (p) { + if (!p.start || !p.length) { + return false; + } + + return true; + }); +}; +/** wrap the linked-list around these terms + * so they don't appear any more + */ + + +var deletePhrase = function deletePhrase(phrase, doc) { + var pool = doc.pool(); + var terms = phrase.terms(); //grab both sides of the chain, + + var prev = pool.get(terms[0].prev) || {}; + var after = pool.get(terms[terms.length - 1].next) || {}; + + if (terms[0].implicit && prev.implicit) { + prev.set(prev.implicit); + prev.post += ' '; + } // //first, change phrase lengths + + + shrinkAll(doc, phrase.start, phrase.length, after); // connect [prev]->[after] + + if (prev) { + prev.next = after.id; + } // connect [prev]<-[after] + + + if (after) { + after.prev = prev.id; + } // lastly, actually delete the terms from the pool? + // for (let i = 0; i < terms.length; i++) { + // pool.remove(terms[i].id) + // } + +}; + +var _delete = deletePhrase; + +/** put this text at the end */ + +var append_1 = function append_1(newPhrase, doc) { + append(this, newPhrase, doc); + return this; +}; +/** add this text to the beginning */ + + +var prepend_1 = function prepend_1(newPhrase, doc) { + prepend(this, newPhrase, doc); + return this; +}; + +var delete_1 = function delete_1(doc) { + _delete(this, doc); + return this; +}; // stich-in newPhrase, stretch 'doc' + parents + + +var replace = function replace(newPhrase, doc) { + // doc.debug() + //add it do the end + var firstLength = this.length; + append(this, newPhrase, doc); //delete original terms + + var tmp = this.buildFrom(this.start, this.length); + tmp.length = firstLength; // console.log(tmp) + + _delete(tmp, doc); // return doc +}; +/** + * Turn this phrase object into 3 phrase objects + */ + + +var splitOn = function splitOn(p) { + var terms = this.terms(); + var result = { + before: null, + match: null, + after: null + }; + var index = terms.findIndex(function (t) { + return t.id === p.start; + }); + + if (index === -1) { + return result; + } //make all three sections into phrase-objects + + + var start = terms.slice(0, index); + + if (start.length > 0) { + result.before = this.buildFrom(start[0].id, start.length); + } + + var match = terms.slice(index, index + p.length); + + if (match.length > 0) { + result.match = this.buildFrom(match[0].id, match.length); + } + + var end = terms.slice(index + p.length, terms.length); + + if (end.length > 0) { + result.after = this.buildFrom(end[0].id, end.length, this.pool); + } + + return result; +}; + +var _04Insert = { + append: append_1, + prepend: prepend_1, + "delete": delete_1, + replace: replace, + splitOn: splitOn +}; + +/** return json metadata for this phrase */ +var json$1 = function json() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var world = arguments.length > 1 ? arguments[1] : undefined; + var res = {}; // text data + + if (options.text) { + res.text = this.text(); + } + + if (options.normal) { + res.normal = this.text('normal'); + } + + if (options.clean) { + res.clean = this.text('clean'); + } + + if (options.reduced) { + res.reduced = this.text('reduced'); + } + + if (options.root) { + res.root = this.text('root'); + } + + if (options.trim) { + if (res.text) { + res.text = res.text.trim(); + } + + if (res.normal) { + res.normal = res.normal.trim(); + } + + if (res.reduced) { + res.reduced = res.reduced.trim(); + } + } // terms data + + + if (options.terms) { + if (options.terms === true) { + options.terms = {}; + } + + res.terms = this.terms().map(function (t) { + return t.json(options.terms, world); + }); + } + + return res; +}; + +var _05Json$1 = { + json: json$1 +}; + +/** match any terms after this phrase */ +var lookAhead = function lookAhead(regs) { + // if empty match string, return everything after + if (!regs) { + regs = '.*'; + } + + var pool = this.pool; // get a list of all terms preceding our start + + var terms = []; + + var getAfter = function getAfter(id) { + var term = pool.get(id); + + if (!term) { + return; + } + + terms.push(term); + + if (term.prev) { + getAfter(term.next); //recursion + } + }; + + var all = this.terms(); + var lastTerm = all[all.length - 1]; + getAfter(lastTerm.next); + + if (terms.length === 0) { + return []; + } // got the terms, make a phrase from them + + + var p = this.buildFrom(terms[0].id, terms.length); + return p.match(regs); +}; +/** match any terms before this phrase */ + + +var lookBehind = function lookBehind(regs) { + // if empty match string, return everything before + if (!regs) { + regs = '.*'; + } + + var pool = this.pool; // get a list of all terms preceding our start + + var terms = []; + + var getBefore = function getBefore(id) { + var term = pool.get(id); + + if (!term) { + return; + } + + terms.push(term); + + if (term.prev) { + getBefore(term.prev); //recursion + } + }; + + var term = pool.get(this.start); + getBefore(term.prev); + + if (terms.length === 0) { + return []; + } // got the terms, make a phrase from them + + + var p = this.buildFrom(terms[terms.length - 1].id, terms.length); + return p.match(regs); +}; + +var _06Lookahead = { + lookAhead: lookAhead, + lookBehind: lookBehind +}; + +var methods$1 = Object.assign({}, _01Utils, _02Text, _03Change, _04Insert, _05Json$1, _06Lookahead); + +// try to avoid doing the match +var failFast = function failFast(p, regs) { + if (regs.length === 0) { + return true; + } + + for (var i = 0; i < regs.length; i += 1) { + var reg = regs[i]; // //logical quick-ones + + if (reg.optional !== true && reg.negative !== true) { + //start/end impossibilites + if (reg.start === true && i > 0) { + return true; + } // has almost no effect + + + if (p.cache.words !== undefined && reg.word !== undefined && p.cache.words.hasOwnProperty(reg.word) !== true) { + // console.log('skip') + return true; + } + } //this is not possible + + + if (reg.anything === true && reg.negative === true) { + return true; + } + } + + return false; +}; + +var _02FailFast = failFast; + +// i formally apologize for how complicated this is. +//found a match? it's greedy? keep going! +var getGreedy = function getGreedy(terms, t, reg, until, index, length) { + var start = t; + + for (; t < terms.length; t += 1) { + //stop for next-reg match + if (until && terms[t].doesMatch(until, index + t, length)) { + return t; + } + + var count = t - start + 1; // is it max-length now? + + if (reg.max !== undefined && count === reg.max) { + return t; + } //stop here + + + if (terms[t].doesMatch(reg, index + t, length) === false) { + // is it too short? + if (reg.min !== undefined && count < reg.min) { + return null; + } + + return t; + } + } + + return t; +}; //'unspecific greedy' is a weird situation. + + +var greedyTo = function greedyTo(terms, t, nextReg, index, length) { + //if there's no next one, just go off the end! + if (!nextReg) { + return terms.length; + } //otherwise, we're looking for the next one + + + for (; t < terms.length; t += 1) { + if (terms[t].doesMatch(nextReg, index + t, length) === true) { + return t; + } + } //guess it doesn't exist, then. + + + return null; +}; +/** tries to match a sequence of terms, starting from here */ + + +var tryHere = function tryHere(terms, regs, index, length) { + var captures = []; + var t = 0; // we must satisfy each rule in 'regs' + + for (var r = 0; r < regs.length; r += 1) { + var reg = regs[r]; //should we fail here? + + if (!terms[t]) { + //are all remaining regs optional? + var hasNeeds = regs.slice(r).some(function (remain) { + return !remain.optional; + }); + + if (hasNeeds === false) { + break; + } // have unmet needs + + + return false; + } //support 'unspecific greedy' .* properly + + + if (reg.anything === true && reg.greedy === true) { + var skipto = greedyTo(terms, t, regs[r + 1], reg, index); // ensure it's long enough + + if (reg.min !== undefined && skipto - t < reg.min) { + return false; + } // reduce it back, if it's too long + + + if (reg.max !== undefined && skipto - t > reg.max) { + t = t + reg.max; + continue; + } //TODO: support [*] properly + + + if (skipto === null) { + return false; //couldn't find it + } + + t = skipto; + continue; + } //if it looks like a match, continue + + + if (reg.anything === true || terms[t].doesMatch(reg, index + t, length) === true) { + var startAt = t; // okay, it was a match, but if it optional too, + // we should check the next reg too, to skip it? + + if (reg.optional && regs[r + 1]) { + // does the next reg match it too? + if (terms[t].doesMatch(regs[r + 1], index + t, length) === true) { + // but does the next reg match the next term?? + // only skip if it doesn't + if (!terms[t + 1] || terms[t + 1].doesMatch(regs[r + 1], index + t, length) === false) { + r += 1; + } + } + } //advance to the next term! + + + t += 1; //check any ending '$' flags + + if (reg.end === true) { + //if this isn't the last term, refuse the match + if (t !== terms.length && reg.greedy !== true) { + return false; + } + } //try keep it going! + + + if (reg.greedy === true) { + t = getGreedy(terms, t, reg, regs[r + 1], index, length); + + if (t === null) { + return false; //greedy was too short + } + } + + if (reg.capture) { + captures.push(startAt); //add greedy-end to capture + + if (t > 1 && reg.greedy) { + captures.push(t - 1); + } + } + + continue; + } //bah, who cares, keep going + + + if (reg.optional === true) { + continue; + } // should we skip-over an implicit word? + + + if (terms[t].isImplicit() && regs[r - 1] && terms[t + 1]) { + // does the next one match? + if (terms[t + 1].doesMatch(reg, index + t, length)) { + t += 2; + continue; + } + } // console.log(' ❌\n\n') + + + return false; + } //we got to the end of the regs, and haven't failed! + //try to only return our [captured] segment + + + if (captures.length > 0) { + //make sure the array is the full-length we'd return anyways + var arr = terms.slice(captures[0], captures[captures.length - 1] + 1); //make sure the array is t-length (so we skip ahead full-length) + + for (var tmp = 0; tmp < t; tmp++) { + arr[tmp] = arr[tmp] || null; //these get cleaned-up after + } + + return arr; + } //return our result + + + return terms.slice(0, t); +}; + +var _03TryMatch = tryHere; + +/* break-down a match expression into this: +{ + word:'', + tag:'', + regex:'', + + start:false, + end:false, + negative:false, + anything:false, + greedy:false, + optional:false, + + capture:false, + choices:[], +} +*/ +var hasMinMax = /\{([0-9]+,?[0-9]*)\}/; +var andSign = /&&/; + +var titleCase$1 = function titleCase(str) { + return str.charAt(0).toUpperCase() + str.substr(1); +}; + +var end = function end(str) { + return str[str.length - 1]; +}; + +var start = function start(str) { + return str[0]; +}; + +var stripStart = function stripStart(str) { + return str.substr(1); +}; + +var stripEnd = function stripEnd(str) { + return str.substr(0, str.length - 1); +}; + +var stripBoth = function stripBoth(str) { + str = stripStart(str); + str = stripEnd(str); + return str; +}; // + + +var parseToken = function parseToken(w) { + var obj = {}; //collect any flags (do it twice) + + for (var i = 0; i < 2; i += 1) { + //back-flags + if (end(w) === '+') { + obj.greedy = true; + w = stripEnd(w); + } + + if (w !== '*' && end(w) === '*' && w !== '\\*') { + obj.greedy = true; + w = stripEnd(w); + } + + if (end(w) === '?') { + obj.optional = true; + w = stripEnd(w); + } + + if (end(w) === '$') { + obj.end = true; + w = stripEnd(w); + } //front-flags + + + if (start(w) === '^') { + obj.start = true; + w = stripStart(w); + } + + if (start(w) === '!') { + obj.negative = true; + w = stripStart(w); + } //wrapped-flags + + + if (start(w) === '(' && end(w) === ')') { + // support (one && two) + if (andSign.test(w)) { + obj.choices = w.split(andSign); + obj.operator = 'and'; + } else { + obj.choices = w.split('|'); + obj.operator = 'or'; + } //remove '(' and ')' + + + obj.choices[0] = stripStart(obj.choices[0]); + var last = obj.choices.length - 1; + obj.choices[last] = stripEnd(obj.choices[last]); // clean up the results + + obj.choices = obj.choices.map(function (s) { + return s.trim(); + }); + obj.choices = obj.choices.filter(function (s) { + return s; + }); //recursion alert! + + obj.choices = obj.choices.map(parseToken); + w = ''; + } //capture group (this one can span multiple-terms) + + + if (start(w) === '[' || end(w) === ']') { + obj.capture = true; + w = w.replace(/^\[/, ''); + w = w.replace(/\]$/, ''); + } //regex + + + if (start(w) === '/' && end(w) === '/') { + w = stripBoth(w); + obj.regex = new RegExp(w); + return obj; + } //soft-match + + + if (start(w) === '~' && end(w) === '~') { + w = stripBoth(w); + obj.soft = true; + obj.word = w; + return obj; + } + } // support #Tag{0,9} + + + if (hasMinMax.test(w) === true) { + w = w.replace(hasMinMax, function (a, b) { + var arr = b.split(/,/g); + + if (arr.length === 1) { + // '{3}' Exactly three times + obj.min = Number(arr[0]); + obj.max = Number(arr[0]); + } else { + // '{2,4}' Two to four times + // '{3,}' Three or more times + obj.min = Number(arr[0]); + obj.max = Number(arr[1] || 999); + } + + obj.greedy = true; + return ''; + }); + } //do the actual token content + + + if (start(w) === '#') { + obj.tag = stripStart(w); + obj.tag = titleCase$1(obj.tag); + return obj; + } //dynamic function on a term object + + + if (start(w) === '@') { + obj.method = stripStart(w); + return obj; + } + + if (w === '.') { + obj.anything = true; + return obj; + } //support alone-astrix + + + if (w === '*') { + obj.anything = true; + obj.greedy = true; + obj.optional = true; + return obj; + } + + if (w) { + //somehow handle encoded-chars? + w = w.replace('\\*', '*'); + w = w.replace('\\.', '.'); + obj.word = w.toLowerCase(); + } + + return obj; +}; + +var parseToken_1 = parseToken; + +var isArray$1 = function isArray(arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; +}; //split-up by (these things) + + +var byParentheses = function byParentheses(str) { + var arr = str.split(/([\^\[\!]*\(.*?\)[?+*]*\]?\$?)/); + arr = arr.map(function (s) { + return s.trim(); + }); + return arr; +}; + +var byWords = function byWords(arr) { + var words = []; + arr.forEach(function (a) { + //keep brackets lumped together + if (/^[[^_/]?\(/.test(a[0])) { + words.push(a); + return; + } + + var list = a.split(' '); + list = list.filter(function (w) { + return w; + }); + words = words.concat(list); + }); + return words; +}; //turn an array into a 'choices' list + + +var byArray = function byArray(arr) { + return [{ + choices: arr.map(function (s) { + return { + word: s + }; + }) + }]; +}; + +var postProcess = function postProcess(tokens) { + //ensure there's only one consecutive capture group. + var count = tokens.filter(function (t) { + return t.capture === true; + }).length; + + if (count > 1) { + var captureArr = tokens.map(function (t) { + return t.capture; + }); + var first = captureArr.indexOf(true); + var last = captureArr.length - 1 - captureArr.reverse().indexOf(true); //'fill in' capture groups between start-end + + for (var i = first; i < last; i++) { + tokens[i].capture = true; + } + } + + return tokens; +}; + +var fromDoc = function fromDoc(doc) { + if (!doc || !doc.list || !doc.list[0]) { + return []; + } + + var ids = []; + doc.list.forEach(function (p) { + p.terms().forEach(function (t) { + ids.push({ + id: t.id + }); + }); + }); + return [{ + choices: ids, + greedy: true + }]; +}; +/** parse a match-syntax string into json */ + + +var syntax = function syntax(input) { + // fail-fast + if (input === null || input === undefined || input === '') { + return []; + } //try to support a ton of different formats: + + + if (_typeof(input) === 'object') { + if (isArray$1(input)) { + if (input.length === 0 || !input[0]) { + return []; + } //is it a pre-parsed reg-list? + + + if (_typeof(input[0]) === 'object') { + return input; + } //support a flat array of normalized words + + + if (typeof input[0] === 'string') { + return byArray(input); + } + } //support passing-in a compromise object as a match + + + if (input && input.isA === 'Doc') { + return fromDoc(input); + } + + return []; + } + + if (typeof input === 'number') { + input = String(input); //go for it? + } + + var tokens = byParentheses(input); + tokens = byWords(tokens); + tokens = tokens.map(parseToken_1); //clean up anything weird + + tokens = postProcess(tokens); // console.log(JSON.stringify(tokens, null, 2)) + + return tokens; +}; + +var syntax_1 = syntax; + +/** returns a simple array of arrays */ + +var matchAll = function matchAll(p, regs) { + var matchOne = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + //if we forgot to parse it.. + if (typeof regs === 'string') { + regs = syntax_1(regs); + } //try to dismiss it, at-once + + + if (_02FailFast(p, regs) === true) { + return []; + } //any match needs to be this long, at least + + + var minLength = regs.filter(function (r) { + return r.optional !== true; + }).length; + var terms = p.cache.terms || p.terms(); + var matches = []; //optimisation for '^' start logic + + if (regs[0].start === true) { + var match = _03TryMatch(terms, regs, 0, terms.length); + + if (match !== false && match.length > 0) { + matches.push(match); + } // remove (intentional) null results + + + matches = matches.map(function (arr) { + return arr.filter(function (t) { + return t; + }); + }); + return matches; + } //try starting, from every term + + + for (var i = 0; i < terms.length; i += 1) { + // slice may be too short + if (i + minLength > terms.length) { + break; + } //try it! + + + var _match = _03TryMatch(terms.slice(i), regs, i, terms.length); + + if (_match !== false && _match.length > 0) { + //zoom forward! + i += _match.length - 1; //[capture-groups] return some null responses + + _match = _match.filter(function (m) { + return m; + }); + matches.push(_match); //ok, maybe that's enough? + + if (matchOne === true) { + return matches; + } + } + } + + return matches; +}; + +var _01MatchAll = matchAll; + +/** return anything that doesn't match. + * returns a simple array of arrays + */ + +var notMatch = function notMatch(p, regs) { + var found = {}; + var arr = _01MatchAll(p, regs); + arr.forEach(function (ts) { + ts.forEach(function (t) { + found[t.id] = true; + }); + }); //return anything not found + + var terms = p.terms(); + var result = []; + var current = []; + terms.forEach(function (t) { + if (found[t.id] === true) { + if (current.length > 0) { + result.push(current); + current = []; + } + + return; + } + + current.push(t); + }); + + if (current.length > 0) { + result.push(current); + } + + return result; +}; + +var not = notMatch; + +/** return an array of matching phrases */ + +var match_1 = function match_1(str) { + var _this = this; + + var matches = _01MatchAll(this, str); //make them phrase objects + + matches = matches.map(function (list) { + return _this.buildFrom(list[0].id, list.length); + }); + return matches; +}; +/** return boolean if one match is found */ + + +var has = function has(str) { + var matches = _01MatchAll(this, str, true); + return matches.length > 0; +}; +/** remove all matches from the result */ + + +var not$1 = function not$1(str) { + var _this2 = this; + + var matches = not(this, str); //make them phrase objects + + matches = matches.map(function (list) { + return _this2.buildFrom(list[0].id, list.length); + }); + return matches; +}; +/** return a list of phrases that can have this tag */ + + +var canBe$1 = function canBe(tag, world) { + var _this3 = this; + + var results = []; + var terms = this.terms(); + var previous = false; + + for (var i = 0; i < terms.length; i += 1) { + var can = terms[i].canBe(tag, world); + + if (can === true) { + if (previous === true) { + //add it to the end + results[results.length - 1].push(terms[i]); + } else { + results.push([terms[i]]); //make a new one + } + + previous = can; + } + } //turn them into Phrase objects + + + results = results.filter(function (a) { + return a.length > 0; + }).map(function (arr) { + return _this3.buildFrom(arr[0].id, arr.length); + }); + return results; +}; + +var match = { + match: match_1, + has: has, + not: not$1, + canBe: canBe$1 +}; + +var Phrase = function Phrase(id, length, pool) { + _classCallCheck(this, Phrase); + + this.start = id; + this.length = length; + this.isA = 'Phrase'; // easier than .constructor... + + Object.defineProperty(this, 'pool', { + enumerable: false, + writable: true, + value: pool + }); + Object.defineProperty(this, 'cache', { + enumerable: false, + writable: true, + value: {} + }); +}; +/** create a new Phrase object from an id and length */ + + +Phrase.prototype.buildFrom = function (id, length) { + var p = new Phrase(id, length, this.pool); + + if (this.cache) { + p.cache = this.cache; + p.cache.terms = null; + } + + return p; +}; // Phrase.prototype.fromString = function(str) { +// console.log(tokenize) +// return tokenize.fromText(str) +// } +//apply methods + + +Object.assign(Phrase.prototype, match); +Object.assign(Phrase.prototype, methods$1); //apply aliases + +var aliases = { + term: 'terms' +}; +Object.keys(aliases).forEach(function (k) { + return Phrase.prototype[k] = Phrase.prototype[aliases[k]]; +}); +var Phrase_1 = Phrase; + +/** a key-value store of all terms in our Document */ +var Pool = +/*#__PURE__*/ +function () { + function Pool() { + var words = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, Pool); + + //quiet this property in console.logs + Object.defineProperty(this, 'words', { + enumerable: false, + value: words + }); + } + /** throw a new term object in */ + + + _createClass(Pool, [{ + key: "add", + value: function add(term) { + this.words[term.id] = term; + return this; + } + /** find a term by it's id */ + + }, { + key: "get", + value: function get(id) { + return this.words[id]; + } + /** find a term by it's id */ + + }, { + key: "remove", + value: function remove(id) { + delete this.words[id]; + } + }, { + key: "merge", + value: function merge(pool) { + Object.assign(this.words, pool.words); + return this; + } + /** helper method */ + + }, { + key: "stats", + value: function stats() { + return { + words: Object.keys(this.words).length + }; + } + }]); + + return Pool; +}(); +/** make a deep-copy of all terms */ + + +Pool.prototype.clone = function () { + var _this = this; + + var keys = Object.keys(this.words); + var words = keys.reduce(function (h, k) { + var t = _this.words[k].clone(); + + h[t.id] = t; + return h; + }, {}); + return new Pool(words); +}; + +var Pool_1 = Pool; + +//(Rule-based sentence boundary segmentation) - chop given text into its proper sentences. +// Ignore periods/questions/exclamations used in acronyms/abbreviations/numbers, etc. +// @spencermountain 2017 MIT +//proper nouns with exclamation marks +// const blacklist = { +// yahoo: true, +// joomla: true, +// jeopardy: true, +// } +//regs- +var initSplit = /(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g; +var hasSomething = /\S/; +var isAcronym$1 = /[ .][A-Z]\.? *$/i; +var hasEllipse = /(?:\u2026|\.{2,}) *$/; +var newLine = /((?:\r?\n|\r)+)/; // Match different new-line formats + +var hasLetter = /[a-z0-9\u00C0-\u00FF\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]/i; +var startWhitespace = /^\s+/; // Start with a regex: + +var naiive_split = function naiive_split(text) { + var all = []; //first, split by newline + + var lines = text.split(newLine); + + for (var i = 0; i < lines.length; i++) { + //split by period, question-mark, and exclamation-mark + var arr = lines[i].split(initSplit); + + for (var o = 0; o < arr.length; o++) { + all.push(arr[o]); + } + } + + return all; +}; +/** does this look like a sentence? */ + + +var isSentence = function isSentence(str, abbrevs) { + // check for 'F.B.I.' + if (isAcronym$1.test(str) === true) { + return false; + } //check for '...' + + + if (hasEllipse.test(str) === true) { + return false; + } // must have a letter + + + if (hasLetter.test(str) === false) { + return false; + } + + var txt = str.replace(/[.!?\u203D\u2E18\u203C\u2047-\u2049] *$/, ''); + var words = txt.split(' '); + var lastWord = words[words.length - 1].toLowerCase(); // check for 'Mr.' + + if (abbrevs.hasOwnProperty(lastWord)) { + return false; + } // //check for jeopardy! + // if (blacklist.hasOwnProperty(lastWord)) { + // return false + // } + + + return true; +}; + +var splitSentences = function splitSentences(text, world) { + var abbrevs = world.cache.abbreviations; + text = text || ''; + text = String(text); + var sentences = []; // First do a greedy-split.. + + var chunks = []; // Ensure it 'smells like' a sentence + + if (!text || typeof text !== 'string' || hasSomething.test(text) === false) { + return sentences; + } // Start somewhere: + + + var splits = naiive_split(text); // Filter-out the crap ones + + for (var i = 0; i < splits.length; i++) { + var s = splits[i]; + + if (s === undefined || s === '') { + continue; + } //this is meaningful whitespace + + + if (hasSomething.test(s) === false) { + //add it to the last one + if (chunks[chunks.length - 1]) { + chunks[chunks.length - 1] += s; + continue; + } else if (splits[i + 1]) { + //add it to the next one + splits[i + 1] = s + splits[i + 1]; + continue; + } + } //else, only whitespace, no terms, no sentence + + + chunks.push(s); + } //detection of non-sentence chunks: + //loop through these chunks, and join the non-sentence chunks back together.. + + + for (var _i = 0; _i < chunks.length; _i++) { + var c = chunks[_i]; //should this chunk be combined with the next one? + + if (chunks[_i + 1] && isSentence(c, abbrevs) === false) { + chunks[_i + 1] = c + (chunks[_i + 1] || ''); + } else if (c && c.length > 0) { + //&& hasLetter.test(c) + //this chunk is a proper sentence.. + sentences.push(c); + chunks[_i] = ''; + } + } //if we never got a sentence, return the given text + + + if (sentences.length === 0) { + return [text]; + } //move whitespace to the ends of sentences, when possible + //['hello',' world'] -> ['hello ','world'] + + + for (var _i2 = 1; _i2 < sentences.length; _i2 += 1) { + var ws = sentences[_i2].match(startWhitespace); + + if (ws !== null) { + sentences[_i2 - 1] += ws[0]; + sentences[_i2] = sentences[_i2].replace(startWhitespace, ''); + } + } + + return sentences; +}; + +var _01Sentences = splitSentences; // console.log(sentence_parser('john f. kennedy')); + +var wordlike = /\S/; +var isBoundary = /^[!?.]+$/; +var naiiveSplit = /(\S+)/; +var isSlash = /\/\W*$/; +var notWord = { + '.': true, + '-': true, + //dash + '–': true, + //en-dash + '—': true, + //em-dash + '--': true, + '...': true // '/': true, // 'one / two' + +}; + +var hasHyphen$1 = function hasHyphen(str) { + //dont split 're-do' + if (/^(re|un)-?[^aeiou]./.test(str) === true) { + return false; + } //letter-number + + + var reg = /^([a-z\u00C0-\u00FF`"'/]+)(-|–|—)([a-z0-9\u00C0-\u00FF].*)/i; + + if (reg.test(str) === true) { + return true; + } //support weird number-emdash combo '2010–2011' + // let reg2 = /^([0-9]+)(–|—)([0-9].*)/i + // if (reg2.test(str)) { + // return true + // } + + + return false; +}; // 'he / she' should be one word + + +var combineSlashes = function combineSlashes(arr) { + for (var i = 1; i < arr.length - 1; i++) { + if (isSlash.test(arr[i])) { + arr[i - 1] += arr[i] + arr[i + 1]; + arr[i] = null; + arr[i + 1] = null; + } + } + + return arr; +}; + +var splitHyphens = function splitHyphens(word) { + var arr = []; //support multiple-hyphenated-terms + + var hyphens = word.split(/[-–—]/); + + for (var o = 0; o < hyphens.length; o++) { + if (o === hyphens.length - 1) { + arr.push(hyphens[o]); + } else { + arr.push(hyphens[o] + '-'); + } + } + + return arr; +}; //turn a string into an array of terms (naiive for now, lumped later) + + +var splitWords = function splitWords(str) { + var result = []; + var arr = []; //start with a naiive split + + str = str || ''; + + if (typeof str === 'number') { + str = String(str); + } + + var words = str.split(naiiveSplit); + + for (var i = 0; i < words.length; i++) { + //split 'one-two' + if (hasHyphen$1(words[i]) === true) { + arr = arr.concat(splitHyphens(words[i])); + continue; + } + + arr.push(words[i]); + } //greedy merge whitespace+arr to the right + + + var carry = ''; + + for (var _i = 0; _i < arr.length; _i++) { + var word = arr[_i]; //if it's more than a whitespace + + if (wordlike.test(word) === true && notWord.hasOwnProperty(word) === false && isBoundary.test(word) === false) { + //put whitespace on end of previous term, if possible + if (result.length > 0) { + result[result.length - 1] += carry; + result.push(word); + } else { + //otherwise, but whitespace before + result.push(carry + word); + } + + carry = ''; + } else { + carry += word; + } + } //handle last one + + + if (carry && result.length > 0) { + result[result.length - 1] += carry; //put it on the end + } // combine 'one / two' + + + result = combineSlashes(result); // remove empty results + + result = result.filter(function (s) { + return s; + }); + return result; +}; + +var _02Words = splitWords; + +var addLinks = function addLinks(terms) { + terms.forEach(function (term, i) { + if (i > 0) { + term.prev = terms[i - 1].id; + } + + if (terms[i + 1]) { + term.next = terms[i + 1].id; + } + }); +}; +/** turn a string into an array of Phrase objects */ + + +var fromText = function fromText() { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var world = arguments.length > 1 ? arguments[1] : undefined; + var pool = arguments.length > 2 ? arguments[2] : undefined; + + //a bit of validation, first + if (typeof text !== 'string') { + if (typeof text === 'number') { + text = String(text); + } + } //tokenize into words + + + var sentences = _01Sentences(text, world); + sentences = sentences.map(function (str) { + return _02Words(str); + }); //turn them into proper objects + + pool = pool || new Pool_1(); + var phrases = sentences.map(function (terms) { + terms = terms.map(function (str) { + var term = new Term_1(str); + pool.add(term); + return term; + }); //add next/previous ids + + addLinks(terms); //return phrase objects + + return new Phrase_1(terms[0].id, terms.length, pool); + }); //return them ready for a Document object + + return phrases; +}; // parse the compressed format '3,2|2,4' + + +var parseTags = function parseTags(text, tagList) { + return text.split('|').map(function (str) { + var numList = str.split(','); + numList = numList.map(function (n) { + return parseInt(n, 10); + }); // convert a list pf numbers into an array of tag names + + return numList.map(function (num) { + if (!tagList[num]) { + console.warn('Compromise import: missing tag at index ' + num); + } + + return tagList[num]; + }); + }); +}; +/** create a word-pool and Phrase objects from .export() json*/ + + +var fromJSON = function fromJSON(json, world) { + if (typeof json === 'string') { + json = JSON.parse(json); + } + + var pool = new Pool_1(); //create Phrase objects + + var phrases = json.list.map(function (o) { + // tokenize words from sentence text + var terms = _02Words(o[0]); // unpack the tag data for each term + + var tagArr = parseTags(o[1], json.tags); //create Term objects + + terms = terms.map(function (str, i) { + var term = new Term_1(str); + tagArr[i].forEach(function (tag) { + return term.tag(tag, '', world); + }); + pool.add(term); + return term; + }); //add prev/next links + + addLinks(terms); // return a proper Phrase object + + return new Phrase_1(terms[0].id, terms.length, pool); + }); + return phrases; +}; + +var _01Tokenizer = { + fromText: fromText, + fromJSON: fromJSON +}; + +var _version = '12.0.0'; + +var _data = { + "Comparative": "true¦better", + "Superlative": "true¦earlier", + "PresentTense": "true¦is,sounds", + "Value": "true¦a few", + "Noun": "true¦a8b7c5e3f2here,ie,lit,m1no doubt,p0tce,vs;d,l;a,d;t,y;g,sp,tc,x0;!p;a,ca,o0;l,rp;a,c,l;d,l,rc", + "Copula": "true¦a1is,w0;as,ere;m,re", + "PastTense": "true¦be3came,d2had,meant,sa2taken,w0;as,e0;nt,re;id;en,gan", + "Condition": "true¦if,unless", + "Gerund": "true¦accord0be0develop0go0result0stain0;ing", + "Negative": "true¦n0;ever,o0;!n,t", + "QuestionWord": "true¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s", + "Plural": "true¦records", + "Conjunction": "true¦&,aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh", + "Pronoun": "true¦'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s", + "Singular": "true¦0:0X;1:10;a0Wb0Kc0Bd04e02fXgShOici1jel0kitty,lNmJnIoHpDquestion mark,rBs7t4u2womW;nc0Rs 2;doll0Dst0F; rex,a3h2ic,ragedy,v show;ere,i1;l0x return;ist0Pky,omeone,t2uper bowl,yst0W;ep3ri1u2;de0Pff;faMmoM;al0i1o2;om,se;a4i0Jr3u2;dLrpoD;erogaVobl0O;rt,te0I;bjSceGthers;othi1umb0E;a4ee04o2;del,m2nopo0th0C;!my;n,yf0;i0unch;ead start,o2;l0me3u2;se;! run;adf0entlem5irlZlaci04od,rand3u2;l0y; slam,fa2mo2;th01;an;a5ella,ly,ol0r3un2;di1;iTo2;ntiWsN;mi0thV;conomy,gg,ner5veWx2;ampQecu7;ad7e4innSo2ragonf0ude;cumentFg2i0l0or;gy;ath,t2;ec2;tive;!dy;a8eili1h6i4o2redit card;ttage,u2;riJsin;ty,vil w2;ar;andeliGocol2;ate;n2rD;ary;aAel0lesHo6r4u2;n2tterf0;ti1;eakfast,o2;!th8;dy,tt4y2;!fri2;end;le;nki1r2;ri2;er;d4l0noma0u2;nt;ly; homin4verti2;si1;ng;em", + "Actor": "true¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt", + "Honorific": "true¦a03b00cSdReQfiLgKhon,jr,king,lJmEoDp8queen,r4s0taoiseach,vice7;e1fc,gt,ir,r,u0;ltTpt,rg;c0nDrgeaL;ond liJretary;abbi,e0;ar1pAs,v0;!erend; admirY;astPhd,r0vt;esideEi1of0;!essN;me mini5nce0;!ss;fficOp,rd;a3essrs,i2lle,me,r1s0;!tr;!s;stK;gistrate,j,r6yF;i3lb,t;en,ov;eld mar3rst l0;ady,i0;eutena0;nt;shG;sq,xcellency;et,oct6r,utchess;apt6hance4mdr,o0pl;lonel,m2ngress0unci3;m0wom0;an;dr,mand5;ll0;or;!ain;ldg,rig0;!adi0;er;d0sst,tty,yatullah;j,m0v;!ir0;al", + "SportsTeam": "true¦0:1A;1:1H;2:1G;a1Eb16c0Td0Kfc dallas,g0Ihouston 0Hindiana0Gjacksonville jagua0k0El0Bm01newToQpJqueens parkIreal salt lake,sAt5utah jazz,vancouver whitecaps,w3yW;ashington 3est ham0Rh10;natio1Oredski2wizar0W;ampa bay 6e5o3;ronto 3ttenham hotspur;blue ja0Mrapto0;nnessee tita2xasC;buccanee0ra0K;a7eattle 5heffield0Kporting kansas0Wt3;. louis 3oke0V;c1Frams;marine0s3;eah15ounG;cramento Rn 3;antonio spu0diego 3francisco gJjose earthquak1;char08paA; ran07;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat1steele0;il3oenix su2;adelphia 3li1;eagl1philNunE;dr1;akland 3klahoma city thunder,rlando magic;athle0Mrai3;de0; 3castle01;england 7orleans 6york 3;city fc,g4je0FknXme0Fred bul0Yy3;anke1;ian0D;pelica2sain0C;patrio0Brevolut3;ion;anchester Be9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Fvi3;kings;imberwolv1wi2;rewe0uc0K;dolphi2heat,marli2;mphis grizz3ts;li1;cXu08;a4eicesterVos angeles 3;clippe0dodDla9; galaxy,ke0;ansas city 3nE;chiefs,roya0E; pace0polis colU;astr06dynamo,rockeTtexa2;olden state warrio0reen bay pac3;ke0;.c.Aallas 7e3i05od5;nver 5troit 3;lio2pisto2ti3;ge0;broncZnuggeM;cowbo4maver3;ic00;ys; uQ;arCelKh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki1;brow2cavalie0india2;bengaWre3;ds;arlotte horAicago 3;b4cubs,fire,wh3;iteB;ea0ulR;diff3olina panthe0; c3;ity;altimore 9lackburn rove0oston 5rooklyn 3uffalo bilN;ne3;ts;cel4red3; sox;tics;rs;oriol1rave2;rizona Ast8tlanta 3;brav1falco2h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls", + "Uncountable": "true¦a1Ib1Ac11d0Ye0Rf0Lg0Hh0Ci08j07knowled1Hl02mUnews,oTpQrLsAt5vi4w0;a2ea05i1oo0;d,l;ldlife,ne;rmth,t17;neg0Yol06tae;e3h2oothpaste,r0una;affPou0;ble,sers,t;ermod1Eund12;a,nnis;a8cene04eri0Oh7il6kittl0Onow,o5p3t1u0;g0Rnshi0H;ati1De0;am,el;ace16e0;ci0Jed;ap,cc0U;k,v0T;eep,ingl0G;d04fe10l0nd;m0St;a3e1ic0;e,ke0D;c0laxa09search;ogni08rea08;bi09in;aJe1hys10last5o0ressV;lit0Zrk,w0J;a0Vtrol;bstetr0Xil,xygen;a5e3ilk,o2u0;mps,s0;ic;nGo0A;a0chan0S;slZt;chine0il,themat0Q; learn05ry;aught08e2i1ogi0Nu0;ck,g0C;ce,ghtn02ngui0LteratH;a0isG;th04;ewel7usti0G;ce,mp0nformaOtself;a0ortan0E;ti0;en0C;a3isto2o0;ck0mework,n0spitali06;ey;ry;ir,libut,ppi7;en01o1r0um,ymna08;a6ound;l0ssip;d,f;i4lour,o1urnit0;ure;od,rgive0uriNwl;ne0;ss;c6sh;conomZduca5lectr4n2quip3thZvery0;body,o0thE;ne;joy0tertain0;ment;iciNonU;tiF;ar1iabet0raugh1;es;ts;a7elcius,h3ivPl2o0urrency;al,ld w0nfusiAttA;ar;assMoth2;aos,e0;e1w0;ing;se;r4sh;a4eef,i1lood,owls,read,utt0;er;lliar1s0;on;ds;g0ss;ga0;ge;c6dvi5ero3ir2mnes1rt,thl0;et7;ty;craft;b4d0naut4;ynam3;ce;id,ou0;st0;ics", + "Infinitive": "true¦0:6H;1:6V;2:55;3:6S;4:6T;5:5W;6:64;7:6R;8:6N;9:6F;A:6P;B:6M;C:6A;D:6W;a67b5Wc4Yd46e3Qf3Dg37h30i2Nj2Lk2Jl2Am20n1Xo1Tp1Eques3Er0Ms01tTuPvMwFyE;awn,ield;aHe1Thist6iGoEre60;nd0rE;k,ry;pe,sh,th0;lk,nFrEsh,tCve;n,raD;d0t;aFiEo7;ew,sB;l68ry;nFpEr3se;gra4Jli3W;dEi7lo5O;er47o;aKeJhIoHrFuEwi8;ne,rn;aEe0Ki5Ku8y;de,in,nsf0p,v5C;r2VuC;ank,reat2L;nd,st;lk,rg1Ms7;aXcUeThRi48kip,lQmPnee3Ho4WpOtHuEwitC;bmBck,ff0gge8ppFrEspe5;ge,pri1rou4Tvi4;ly,o32;aJeIoHrFuE;dy,mb6;a4NeEi4;ngth2Bss,tC;p,re;m,p;in,ke,r0Oy;la50oil,rink6;e1Vi6o3F;am,ip;a2iv0oE;ck,ut;arCem,le5n1r4tt6;aFo2rE;atCew;le,re;il,ve;a03eGisk,oFuE;in,le,sh;am,ll;aZcXdu9fWgVje5lSmRnt,pOquNsItHvEwa5L;eEiew,o32;al,l,rE;se,t;a41i2u3Y;eHi8oGtE;!o2rE;i5uc1W;l4rt;mb6nt,r4;e8i2;air,eFlEo3XreseD;a9y;at;a3Remb0i3To4;aFeEi4y;a1nt;te,x;a53r0F;act1Uer,le5u1;a0Zei4k5FoEyc6;gni28nci6rd;ch,li27s5D;i1nE;ge,k;aRerQiPlMoKrGuE;b1Xll,mp,rEsh;cha1s4G;ai1eGiDoE;cEdu9greAhibBmi1te8vi2R;eAlaim;di5pa2ss,veD;iDp,rtr3WsEur;e,t;aFuE;g,n3;n,y;ck,le;fo2YmBsi8;ck,iDrt4Css,u1;bGccur,ff0pera7utweFverEwe;co3Xlap,ta1Yu1whelm;igh;ser4ta2Y;eFotE;e,i9;ed,gle5;aJeIiGoFuE;ltip3Ard0;nit10ve;nErr0Z;d,g6us;asu2lt,n0Mr3ssa3;inta2Ona3rFtE;ch,t0;ch,kEry;et;aKeJiGoEu1A;aEck,ok,ve;d,n;ft,ke,mBnFstEve;!en;e,k;a2Bc0Ct;b0Lck,uE;gh,nC;iEno2W;ck,ll,ss;am,o29uE;d3mp;gno2mOnEss39;cMdica7flu0KhLsItGvE;eEol4;nt,st;erErodu9;a5fe2;i8tE;aEru5;ll;abBibB;lu1Cr1A;agi20pE;lemeDo1Yro4;aIeGi2oFuE;nt,rry;n00pe,st;aElp;d,t;nd6ppErm,te;en;aIloAove1KrGuE;arEeAi11;ant30d;aEip,umb6;b,sp;in,th0ze;aOeaNiLlJoGracFuncE;ti3A;tu2;cus,lFrE;ce,eca8m,s2S;d,l1W;a1ToE;at,od,w;gu2lEni1Rx;e,l;r,tu2;il,vE;or;a11cho,le5mQnNstLvalua7xE;a08cJerIi8pEte15;a14eFla12oEreA;rt,se;ct,riE;en9;ci1t;el,han3;abEima7;li1D;ab6couVdFfor9ga3han9j01riCsu2t0vE;isi2Ny;!u2;body,er3pE;hasiEow0;ze;a04eSiJoIrFuE;mp;aFeAiE;ft;g,in;d3ubt;ff0p,re5sFvE;iWor9;aIcFliEmiApl13tingui0Y;ke;oEuA;uEv0;ra3;gr1QppE;ear,ro4;cLem,fJliv0ma0Bny,pIsFterE;mi0C;cribe,er4iFtrE;oy;gn,re;a07e06i5osB;eEi07y;at,ct;iGlFrE;ea1;a2i03;de;ma3n9re,te;a08e07h04i7l02oHrE;aFeEoAu0Dy;a7dB;ck,ve;llXmQnFok,py,uEv0;gh,nt;ceNdu5fKsItGvE;eEin9;rt,y;aNin0PrE;a8ibu7ol;iEtitu7;d0st;iFoEroD;rm;gu2rm;rn;biJfoImaHpE;a2laE;in;re;nd;rt;ne;ap1e5;aEip,o1;im,w;aFeE;at,ck,w;llen3n3r3se;a1nt0;ll,ncFrEt0u1;e,ry;el;aNeKloJoHruGuE;lEry;ly;sh;a8mb,o8rrEth0un9;ow;ck;ar,lFnefBtrE;ay;ie4ong;ng,se;band0Hc09d04ffo03gr02id,lZmu1nWppRrOsIttEvoid,waB;acGeFra5;ct;m0Dnd;h,k;k,sE;eGiFocia7uE;me;gn,st;mb6rt;le;chFgEri4;ue;!i4;eaHlGroE;aCve;ch;aud,y;l,r;noun9sw0tE;icipa7;ce;lFt0;er;e3ow;ee;rd;aPdGju8mBoP;it;st;!reA;ss;cHhie4knowled3tiva7;te;ge;ve;eGouDu1;se;nt;pt;on", + "Unit": "true¦0:16;a11b0Zc0Ld0Ke0If0Dg09h06in0Ejoule0k00lYmNnMoLpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Kb,d0Qears old,o1;tt0E;att0b;able4b3e2on1sp;!ne0;a2r0A;!l,sp;spo01; ft,uare 1;c0Fd0Ef3i0Ckilo0Gm1ya0B;e0Jil1;e0li0E;eet0o0A;t,uart0;ascals,e2i1ou0Mt;c0Jnt0;rcent,tZ;hms,uVz;an0GewtQ;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;e1g,z;ct1rtz0;aXogQ;al2b,igAra1;in0m0;!l1;on0;a4emtPl2t1;²,³; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s", + "Organization": "true¦0:46;a3Ab2Qc2Ad21e1Xf1Tg1Lh1Gi1Dj19k17l13m0Sn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0Xou1w0X;gov,tu2S;a3e1orld trade organizati41;lls fargo,st1;fie22inghou16;l1rner br3D;-m11gree31l street journ25m11;an halNeriz3Wisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Rps;es35i1;lev2Xted natio2Uv; mobi2Kaco bePd bMeAgi frida9h3im horto2Tmz,o1witt2W;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen33daily ma2Xguess w2holli0rolling st1Ms1w2;mashing pumpki2Ouprem0;ho;ea1lack eyed pe3Fyrds;ch bo1tl0;ys;l2s1;co,la m12;efoni07us;a6e4ieme2Gnp,o2pice gir5ta1ubaru;rbucks,to2N;ny,undgard1;en;a2Rx pisto1;ls;few25insbu26msu1X;.e.m.,adiohead,b6e3oyal 1yan2X;b1dutch she4;ank;/max,aders dige1Ed 1vl32;bu1c1Uhot chili peppe2Klobst28;ll;c,s;ant2Vizno2F;an5bs,e3fiz24hilip morrBi2r1;emier27octer & gamb1Rudenti14;nk floyd,zza hut;psi28tro1uge08;br2Qchina,n2Q; 2ason1Xda2G;ld navy,pec,range juli2xf1;am;us;a9b8e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0K;l,s;c,st1Etflix,w1; 1sweek;kids on the block,york08;a,c;nd1Us2t1;ional aca2Fo,we0Q;a,cYd0O;aAcdonald9e5i3lb,o1tv,yspace;b1Nnsanto,ody blu0t1;ley crue,or0O;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt13z1Y;'ore09a3e1g,ittle caesa1Ktd;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1K;art;iffy lu0Lo3pmorgan1sa;! cha1;se;hnson & johns1Sy d1R;bm,hop,n1tv;c,g,te1;l,rpol; & m,asbro,ewlett-packaTi3o1sbc,yundai;me dep1n1J;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Iu1;cci,ns n ros0;ldman sachs,o1;dye1g0B;ar;axo smith kliZencore;electr0Im1;oto0V;a3bi,da,edex,i1leetwood mac,oGrito-l0A;at,nancial1restoV; tim0;cebook,nnie mae;b06sa,u3xxon1; m1m1;ob0H;!rosceptics;aiml0Ae5isney,o3u1;nkin donuts,po0Wran dur1;an;j,w j1;on0;a,f leppa3ll,p2r spiegZstiny's chi1;ld;eche mode,t;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra05;al;!ca c5l4m1o0Ast05;ca2p1;aq;st;dplMgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Hy;dbury,pital o1rl's jr;ne;aGbc,eCfAl6mw,ni,o2p,r1;exiteeWos;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roX;ckbuster video,omingda1;le; g1g1;oodriN;cht3e ge0n & jer2rkshire hathaw1;ay;ryH;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bXcSdidRerosmith,ig,lLmFnheuser-busEol,ppleAr7s3t&t,v2y1;er;is,on;hland2s1;n,ociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c", + "Demonym": "true¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an", + "Possessive": "true¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne", + "Currency": "true¦$,aud,bScQdLeurKfJgbp,hkd,iIjpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotySł;en,uanR;af,of;h0t5;e0il5;k0q0;elM;iel,oubleLp,upeeL;e2ound st0;er0;lingI;n0soH;ceGn0;ies,y;e0i8;i,mpi7;n,r0wanzaCyatC;!onaBw;ls,nr;ori7ranc9;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s", + "City": "true¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,sario,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg", + "Abbreviation": "true¦a08b05cZdXeUfSgRhQiPjNkanMlKmGnEoDpCque,rAs6t4u3v2w0;is0y00;!c;a,s,t;niv,safa,t;ce,e0;nn,x;ask,e1fc,gt,ir,r,t,u0;pt,rg;nDp0;!t;d,e0;pAs,v;a,d,ennGhd,l,rof,vt;ct,kla,nt,p,rd;eb0ov;!r;a2d,essrs,i1lle,me,r5s0t;!tr;nn,ster;!j,r;it,lb,t0;!d;!s;an,r,u0;l,n;a,da,e,nc;on,wy;a,en,ov;eb,l0t,y;!a;g,s1tc,x0;!p;p,q;ak,e0ist,r;c,pt,t;a3ca,l,m2o0pl,res,t;!l0m1nn,rp;!o;dr;!l0pt;!if;a,c,l1r0;ig,os;!dg,vd;d3l2pr,r1ss0tty,ug,ve;n,t;c,iz;!ta;!j,m,v", + "Place": "true¦a07b05cZdYeXfVgRhQiOjfk,kMlKmHneEoDp9que,rd,s8t5u4v3w0yyz;is1y0;!o;!c;a,t;pYsafa,t;e1he 0;bronx,hamptons;nn,x;ask,fo,oho,t,under6yd;a2e1h0;l,x;k,nnK;!cifX;kla,nt;b1w eng0;land;!r;a1co,i0t,uc;dKnn;libu,nhattS;a0gw,hr;s,x;an0ul;!s;a0cn,da,ndianMst;!x;arlem,kg,nd,wy;a2re0;at 0enwich;britain,lak6;!y village;co,l0ra;!a;urope,verglad2;ak,en,fw,ist,own4xb;al4dg,gk,hina3l2o1r0t;es;lo,nn;!t;town;!if;cn,e0kk,lvd,rooklyn;l air,verly hills;frica,lta,m5ntarct2r1sia,tl0ve;!ant1;ct0iz;ic0; oce0;an;ericas,s", + "Country": "true¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an", + "Region": "true¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma", + "FemaleName": "true¦0:FY;1:G2;2:FR;3:FD;4:FC;5:EP;6:ER;7:FS;8:GF;9:EZ;A:GB;B:E5;C:FO;D:FL;E:G8;F:EG;aE2bD4cB8dAIe9Gf91g8Hh83i7Sj6Uk60l4Om38n2To2Qp2Fqu2Er1Os0Qt04ursu6vUwOyLzG;aJeHoG;e,la,ra;lGna;da,ma;da,ra;as7EeHol1TvG;et5onB9;le0sen3;an9endBNhiB4iG;lInG;if3AniGo0;e,f39;a,helmi0lGma;a,ow;aMeJiG;cHviG;an9XenG1;kCZtor3;da,l8Vnus,rG;a,nGoniD2;a,iDC;leGnesEC;nDLrG;i1y;aSePhNiMoJrGu6y4;acG3iGu0E;c3na,sG;h9Mta;nHrG;a,i;i9Jya;a5IffaCGna,s7;al3eGomasi0;a,l8Go6Xres1;g7Uo6WrHssG;!a,ie;eFi,ri8;bNliMmKnIrHs7tGwa0;ia0um;a,yn;iGya;a,ka,s7;a4e4iGmCAra;!ka;a,t7;at7it7;a05carlet2Ye04hUiSkye,oQtMuHyG;bFJlvi1;e,sHzG;an2Tet5ie,y;anGi8;!a,e,nG;aDe;aIeG;fGl3DphG;an2;cF8r6;f3nGphi1;d4ia,ja,ya;er4lv3mon1nGobh75;dy;aKeGirlBLo0y6;ba,e0i6lIrG;iGrBPyl;!d70;ia,lBV;ki4nIrHu0w0yG;la,na;i,leAon,ron;a,da,ia,nGon;a,on;l5Yre0;bMdLi9lKmIndHrGs7vannaD;aDi0;ra,y;aGi4;nt7ra;lBNome;e,ie;in1ri0;a02eXhViToHuG;by,thBK;bQcPlOnNsHwe0xG;an94ie,y;aHeGie,lE;ann8ll1marBFtB;!lGnn1;iGyn;e,nG;a,d7W;da,i,na;an9;hel53io;bin,erByn;a,cGkki,na,ta;helBZki;ea,iannDXoG;da,n12;an0bIgi0i0nGta,y0;aGee;!e,ta;a,eG;cARkaD;chGe,i0mo0n5EquCDvCy0;aCCelGi9;!e,le;een2ia0;aMeLhJoIrG;iGudenAW;scil1Uyamva9;lly,rt3;ilome0oebe,ylG;is,lis;arl,ggy,nelope,r6t4;ige,m0Fn4Oo6rvaBBtHulG;a,et5in1;ricGsy,tA8;a,e,ia;ctav3deHfAWlGphAW;a,ga,iv3;l3t5;aQePiJoGy6;eHrG;aDeCma;ll1mi;aKcIkGla,na,s7ta;iGki;!ta;hoB2k8BolG;a,eBH;!mh;l7Tna,risF;dIi5PnHo23taG;li1s7;cy,et5;eAiCO;a01ckenz2eViLoIrignayani,uriBGyG;a,rG;a,na,tAS;i4ll9XnG;a,iG;ca,ka,qB4;a,chOkaNlJmi,nIrGtzi;aGiam;!n9;a,dy,erva,h,n2;a,dIi9JlG;iGy;cent,e;red;!e6;ae6el3G;ag4KgKi,lHrG;edi61isFyl;an2iGliF;nGsAM;a,da;!an,han;b08c9Ed06e,g04i03l01nZrKtJuHv6Sx87yGz2;a,bell,ra;de,rG;a,eC;h75il9t2;a,cSgOiJjor2l6In2s7tIyG;!aGbe5QjaAlou;m,n9S;a,ha,i0;!aIbALeHja,lEna,sGt53;!a,ol,sa;!l06;!h,m,nG;!a,e,n1;arIeHie,oGr3Kueri5;!t;!ry;et3IiB;elGi61y;a,l1;dGon,ue6;akranBy;iGlo36;a,ka,n9;a,re,s2;daGg2;!l2W;alEd2elGge,isBGon0;eiAin1yn;el,le;a0Ie08iWoQuKyG;d3la,nG;!a,dHe9SnGsAQ;!a,e9R;a,sAO;aB1cJelIiFlHna,pGz;e,iB;a,u;a,la;iGy;a2Ae,l25n9;is,l1GrHtt2uG;el6is1;aIeHi8na,rG;a6Zi8;lei,n1tB;!in1;aQbPd3lLnIsHv3zG;!a,be4Ket5z2;a,et5;a,dG;a,sGy;ay,ey,i,y;a,iaIlG;iGy;a8Ge;!n4F;b7Terty;!n5R;aNda,e0iLla,nKoIslARtGx2;iGt2;c3t3;la,nGra;a,ie,o4;a,or1;a,gh,laG;!ni;!h,nG;a,d4e,n4N;cNdon7Si6kes7na,rMtKurIvHxGy6;mi;ern1in3;a,eGie,yn;l,n;as7is7oG;nya,ya;a,isF;ey,ie,y;aZeUhadija,iMoLrIyG;lGra;a,ee,ie;istGy5B;a,en,iGy;!e,n48;ri,urtn9A;aMerLl99mIrGzzy;a,stG;en,in;!berlG;eGi,y;e,y;a,stC;!na,ra;el6PiJlInHrG;a,i,ri;d4na;ey,i,l9Qs2y;ra,s7;c8Wi5XlOma6nyakumari,rMss5LtJviByG;!e,lG;a,eG;e,i78;a5EeHhGi3PlEri0y;ar5Cer5Cie,leCr9Fy;!lyn73;a,en,iGl4Uyn;!ma,n31sF;ei72i,l2;a04eVilToMuG;anKdJliGst56;aHeGsF;!nAt0W;!n8X;i2Ry;a,iB;!anLcelEd5Vel71han6IlJni,sHva0yG;a,ce;eGie;fi0lEph4X;eGie;en,n1;!a,e,n36;!i10lG;!i0Z;anLle0nIrHsG;i5Qsi5Q;i,ri;!a,el6Pif1RnG;a,et5iGy;!e,f1P;a,e72iHnG;a,e71iG;e,n1;cLd1mi,nHqueliAsmin2Uvie4yAzG;min8;a8eHiG;ce,e,n1s;!lGsFt06;e,le;inHk2lEquelG;in1yn;da,ta;lPmNnMo0rLsHvaG;!na;aHiGob6U;do4;!belGdo4;!a,e,l2G;en1i0ma;a,di4es,gr5R;el9ogG;en1;a,eAia0o0se;aNeKilHoGyacin1N;ll2rten1H;aHdGlaH;a,egard;ry;ath0WiHlGnrietBrmiAst0W;en24ga;di;il75lKnJrGtt2yl75z6D;iGmo4Fri4G;etG;!te;aDnaD;ey,l2;aYeTiOlMold12rIwG;enGyne18;!dolE;acHetGisel9;a,chC;e,ieG;!la;adys,enGor3yn1Y;a,da,na;aJgi,lHna,ov71selG;a,e,le;da,liG;an;!n0;mYnIorgHrG;ald35i,m2Stru73;et5i5T;a,eGna;s1Nvieve;briel3Fil,le,rnet,yle;aReOio0loMrG;anHe9iG;da,e9;!cG;esHiGoi0G;n1s3V;!ca;!rG;a,en43;lHrnG;!an9;ec3ic3;rHtiGy8;ma;ah,rah;d0FileCkBl00mUn4ArRsMtLuKvG;aIelHiG;e,ta;in0Ayn;!ngel2H;geni1la,ni3R;h52ta;meral9peranJtG;eHhGrel6;er;l2Pr;za;iGma,nest29yn;cGka,n;a,ka;eJilImG;aGie,y;!liA;ee,i1y;lGrald;da,y;aTeRiMlLma,no4oJsIvG;a,iG;na,ra;a,ie;iGuiG;se;a,en,ie,y;a0c3da,nJsGzaH;aGe;!beG;th;!a,or;anor,nG;!a;in1na;en,iGna,wi0;e,th;aWeKiJoGul2U;lor51miniq3Yn30rGtt2;a,eCis,la,othGthy;ea,y;an09naDonAx2;anPbOde,eNiLja,lImetr3nGsir4U;a,iG;ce,se;a,iHla,orGphiA;es,is;a,l5J;dGrdG;re;!d4Mna;!b2CoraDra;a,d4nG;!a,e;hl3i0mMnKphn1rHvi1WyG;le,na;a,by,cHia,lG;a,en1;ey,ie;a,et5iG;!ca,el1Aka;arGia;is;a0Qe0Mh04i02lUoJrHynG;di,th3;istGy04;al,i0;lOnLrHurG;tn1D;aId28iGn28riA;!nG;a,e,n1;!l1S;n2sG;tanGuelo;ce,za;eGleC;en,t5;aIeoHotG;il4B;!pat4;ir8rIudG;et5iG;a,ne;a,e,iG;ce,sX;a4er4ndG;i,y;aPeMloe,rG;isHyG;stal;sy,tG;aHen,iGy;!an1e,n1;!l;lseHrG;!i8yl;a,y;nLrG;isJlHmG;aiA;a,eGot5;n1t5;!sa;d4el1PtG;al,el1O;cHlG;es5i3F;el3ilG;e,ia,y;iYlXmilWndVrNsLtGy6;aJeIhGri0;erGleCrEy;in1;ri0;li0ri0;a2GsG;a2Fie;a,iMlKmeIolHrG;ie,ol;!e,in1yn;lGn;!a,la;a,eGie,y;ne,y;na,sF;a0Di0D;a,e,l1;isBl2;tlG;in,yn;arb0CeYianXlVoTrG;andRePiIoHyG;an0nn;nwEok8;an2NdgKg0ItG;n27tG;!aHnG;ey,i,y;ny;etG;!t8;an0e,nG;da,na;i8y;bbi8nG;iBn2;ancGossom,ythe;a,he;ca;aRcky,lin9niBrNssMtIulaDvG;!erlG;ey,y;hHsy,tG;e,i0Zy8;!anG;ie,y;!ie;nGt7yl;adHiG;ce;et5iA;!triG;ce,z;a4ie,ra;aliy29b24d1Lg1Hi19l0Sm0Nn01rWsNthe0uJvIyG;anGes7;a,na;a,r25;drIgusHrG;el3;ti0;a,ey,i,y;hHtrG;id;aKlGt1P;eHi8yG;!n;e,iGy;gh;!nG;ti;iIleHpiB;ta;en,n1t5;an19elG;le;aYdWeUgQiOja,nHtoGya;inet5n3;!aJeHiGmI;e,ka;!mGt5;ar2;!belHliFmT;sa;!le;ka,sGta;a,sa;elGie;a,iG;a,ca,n1qG;ue;!t5;te;je6rea;la;!bHmGstas3;ar3;el;aIberHel3iGy;e,na;!ly;l3n9;da;aTba,eNiKlIma,yG;a,c3sG;a,on,sa;iGys0J;e,s0I;a,cHna,sGza;a,ha,on,sa;e,ia;c3is7jaIna,ssaIxG;aGia;!nd4;nd4;ra;ia;i0nHyG;ah,na;a,is,naD;c7da,leCmLnslKsG;haDlG;inGyW;g,n;!h;ey;ee;en;at7g2nG;es;ie;ha;aVdiSelLrG;eIiG;anLenG;a,e,ne;an0;na;aKeJiHyG;nn;a,n1;a,e;!ne;!iG;de;e,lEsG;on;yn;!lG;iAyn;ne;agaJbHiG;!gaI;ey,i8y;!e;il;ah", + "WeekDay": "true¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s", + "Month": "true¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il", + "FirstName": "true¦aEblair,cCdevBj8k6lashawn,m3nelly,quinn,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0r9;ls7nyatta,rry;am0ess1ude;ie,m0;ie;an,on;as0heyenne;ey,sidy;lex1ndra,ubr0;ey;is", + "LastName": "true¦0:34;1:39;2:3B;3:2Y;4:2E;5:30;a3Bb31c2Od2Ee2Bf25g1Zh1Pi1Kj1Ek17l0Zm0Nn0Jo0Gp05rYsMtHvFwCxBy8zh6;a6ou,u;ng,o;a6eun2Uoshi1Kun;ma6ng;da,guc1Zmo27sh21zaR;iao,u;a7eb0il6o3right,u;li3Bs1;gn0lk0ng,tanabe;a6ivaldi;ssilj37zqu2;a9h8i2Go7r6sui,urn0;an,ynisJ;lst0Prr1Uth;at1Uomps1;kah0Vnaka,ylor;aEchDeChimizu,iBmiAo9t7u6zabo;ar2lliv2AzuE;a6ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n7sa6to;ki;ch2dLtos,z;amBeag1Zi9o7u6;bio,iz,sD;b6dri1MgIj0Tme24osevelt,ssi,ux;erts,ins1;c6ve0F;ci,hards1;ir2os;aEeAh8ic6ow20;as6hl0;so;a6illips;m,n1T;ders5et8r7t6;e0Nr4;ez,ry;ers;h21rk0t6vl4;el,te0J;baBg0Blivei01r6;t6w1O;ega,iz;a6eils1guy5ix1owak,ym1E;gy,ka6var1K;ji6muW;ma;aEeCiBo8u6;ll0n6rr0Bssolini,ñ6;oz;lina,oKr6zart;al0Me6r0U;au,no;hhail4ll0;rci0ssi6y0;!er;eWmmad4r6tsu07;in6tin2;!o;aCe8i6op2uo;!n6u;coln,dholm;fe7n0Qr6w0J;oy;bv6v6;re;mmy,rs5u;aBennedy,imuAle0Lo8u7wo6;k,n;mar,znets4;bay6vacs;asY;ra;hn,rl9to,ur,zl4;aAen9ha3imen2o6u3;h6nYu3;an6ns1;ss1;ki0Es5;cks1nsse0D;glesi9ke8noue,shik7to,vano6;u,v;awa;da;as;aBe8itchcock,o7u6;!a3b0ghNynh;a3ffmann,rvat;mingw7nde6rN;rs1;ay;ns5rrQs7y6;asDes;an4hi6;moJ;a9il,o8r7u6;o,tierr2;ayli3ub0;m2nzal2;nd6o,rcia;hi;erAis9lor8o7uj6;ita;st0urni0;es;ch0;nand2;d7insteHsposi6vaL;to;is1wards;aCeBi9omin8u6;bo6rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw7vi6;es,s;in;aFhBlarkAo6;h5l6op0rbyn,x;em7li6;ns;an;!e;an8e7iu,o6ristens5u3we;i,ng,u3w,y;!n,on6u3;!g;mpb7rt0st6;ro;ell;aBe8ha3lanco,oyko,r6yrne;ooks,yant;ng;ck7ethov5nnett;en;er,ham;ch,h8iley,rn6;es,i0;er;k,ng;dDl9nd6;ers6rA;en,on,s1;on;eks7iy8var2;ez;ej6;ev;ams", + "MaleName": "true¦0:CE;1:BL;2:C2;3:BT;4:B5;5:9V;6:BZ;7:AT;8:BD;9:AX;A:AO;aB4bA8c97d87e7Gf6Yg6Gh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt06u05v00wNxavi3yGzB;aBor0;cBh8Ine;hCkB;!aB1;ar51eB0;ass2i,oCuB;sDu25;nEsDusB;oBsC;uf;ef;at0g;aJeHiCoByaAP;lfgang,odrow;lBn1O;bDey,frBJlB;aA5iB;am,e,s;e89ur;i,nde5sB;!l7t1;de,lCrr6yB;l1ne;lBt3;a93y;aEern1iB;cCha0nceBrg9Bva0;!nt;ente,t5A;lentin49n8Yughn;lyss4Msm0;aTeOhKiIoErCyB;!l3ro8s1;av9QeBist0oy,um0;nt9Iv54y;bDd7XmBny;!as,mBoharu;aAYie,y;i83y;mBt9;!my,othy;adDeoCia7DomB;!as;!do7M;!de9;dErB;en8HrB;an8GeBy;ll,n8F;!dy;dgh,ic9Tnn3req,ts45;aRcotPeNhJiHoFpenc3tBur1Oylve8Hzym1;anDeBua7B;f0phAFvBwa7A;e57ie;!islaw,l7;lom1nA3uB;leyma8ta;dBl7Jm1;!n7;aDeB;lBrm0;d1t1;h6Sne,qu0Uun,wn,y8;aBbasti0k1Xl41rg40th,ymo9I;m9n;!tB;!ie,y;lCmBnti21q4Iul;!mAu4;ik,vato6V;aWeShe92iOoFuCyB;an,ou;b6LdCf9pe6QssB;!elAI;ol2Uy;an,bIcHdGel,geFh0landA9mEnDry,sCyB;!ce;coe,s;!a95nA;an,eo;l3Jr;e4Qg3n7olfo,ri68;co,ky;bAe9U;cBl7;ar5Oc5NhCkBo;!ey,ie,y;a85ie;gCid,ub6x,yBza;ansh,nS;g8WiB;na8Ss;ch5Yfa4lDmCndBpha4sh6Uul,ymo70;al9Yol2By;i9Ion;f,ph;ent2inB;cy,t1;aFeDhilCier62ol,reB;st1;!ip,lip;d9Brcy,tB;ar,e2V;b3Sdra6Ft44ul;ctav2Vliv3m96rFsCtBum8Uw6;is,to;aCc8SvB;al52;ma;i,l49vJ;athJeHiDoB;aBel,l0ma0r2X;h,m;cCg4i3IkB;h6Uola;hol5XkBol5X;!ol5W;al,d,il,ls1vB;il50;anBy;!a4i4;aWeTiKoFuCyB;l21r1;hamCr5ZstaB;fa,p4G;ed,mF;dibo,e,hamDis1XntCsBussa;es,he;e,y;ad,ed,mB;ad,ed;cGgu4kElDnCtchB;!e5;a78ik;house,o03t1;e,olB;aj;ah,hBk7;a4eB;al,l;hClv2rB;le,ri5v2;di,met;ck,hNlLmOnu4rHs1tDuricCxB;!imilian8Cwe5;e,io;eo,hCi52tB;!eo,hew,ia;eBis;us,w;cDio,k86lCqu6Gsha5tBv2;i2Hy;in,on;!el,oKus;achBcolm,ik;ai,y;amBdi,moud;adB;ou;aReNiMlo2RoIuCyB;le,nd1;cEiDkBth3;aBe;!s;gi,s;as,iaB;no;g0nn6RrenDuBwe5;!iB;e,s;!zo;am,on4;a7Bevi,la4SnDoBst3vi;!nB;!a60el;!ny;mCnBr67ur4Twr4T;ce,d1;ar,o4N;aIeDhaled,iBrist4Vu48y3B;er0p,rB;by,k,ollos;en0iEnBrmit,v2;!dCnBt5C;e0Yy;a5ri4N;r,th;na68rBthem;im,l;aYeQiOoDuB;an,liBst2;an,o,us;aqu2eJhnInGrEsB;eChBi7Bue;!ua;!ph;dBge;an,i,on;!aBny;h,s,th4X;!ath4Wie,nA;!l,sBy;ph;an,e,mB;!mA;d,ffGrDsB;sBus;!e;a5JemCmai8oBry;me,ni0O;i6Uy;!e58rB;ey,y;cHd6kGmFrDsCvi3yB;!d6s1;on,p3;ed,od,rBv4M;e4Zod;al,es,is1;e,ob,ub;k,ob,quB;es;aNbrahMchika,gKkeJlija,nuIrGsDtBv0;ai,sB;uki;aBha0i6Fma4sac;ac,iaB;h,s;a,vinBw2;!g;k,nngu52;!r;nacBor;io;im;in,n;aJeFina4VoDuByd56;be25gBmber4CsD;h,o;m3ra33sBwa3X;se2;aDctCitCn4ErB;be20m0;or;th;bKlJmza,nIo,rDsCyB;a43d6;an,s0;lEo4FrDuBv7;hi40ki,tB;a,o;is1y;an,ey;k,s;!im;ib;aQeMiLlenKoIrEuB;illerCsB;!tavo;mo;aDegBov3;!g,orB;io,y;dy,h57nt;nzaBrd1;lo;!n;lbe4Qno,ovan4R;ne,oDrB;aBry;ld,rd4U;ffr7rge;bri4l6rBv2;la1Zr3Eth,y;aReNiLlJorr0IrB;anDedBitz;!dAeBri24;ri23;cDkB;!ie,lB;in,yn;esJisB;!co,zek;etch3oB;yd;d4lBonn;ip;deriDliCng,rnB;an01;pe,x;co;bi0di;arZdUfrTit0lNmGnFo2rCsteb0th0uge8vBym6zra;an,ere2V;gi,iCnBrol,v2w2;est45ie;c07k;och,rique,zo;aGerFiCmB;aFe2P;lCrB;!h0;!io;s1y;nu4;be09d1iEliDmCt1viBwood;n,s;er,o;ot1Ts;!as,j43sB;ha;a2en;!dAg32mEuCwB;a25in;arB;do;o0Su0S;l,nB;est;aYeOiLoErDuCwByl0;ay8ight;a8dl7nc0st2;ag0ew;minFnDri0ugCyB;le;!l03;!a29nBov0;e5ie,y;go,icB;!k;armuCeBll1on,rk;go;id;anIj0lbeHmetri9nFon,rEsDvCwBxt3;ay8ey;en,in;hawn,mo08;ek,ri0F;is,nBv3;is,y;rt;!dB;re;lKmInHrDvB;e,iB;!d;en,iDne5rByl;eBin,yl;l2Vn;n,o,us;!e,i4ny;iBon;an,en,on;e,lB;as;a06e04hWiar0lLoGrEuCyrB;il,us;rtB;!is;aBistobal;ig;dy,lEnCrB;ey,neli9y;or,rB;ad;by,e,in,l2t1;aGeDiByI;fBnt;fo0Ct1;meCt9velaB;nd;nt;rDuCyB;!t1;de;enB;ce;aFeErisCuB;ck;!tB;i0oph3;st3;d,rlBs;eBie;s,y;cBdric,s11;il;lEmer1rB;ey,lCro5y;ll;!os,t1;eb,v2;ar02eUilTlaSoPrCuByr1;ddy,rtI;aJeEiDuCyB;an,ce,on;ce,no;an,ce;nCtB;!t;dCtB;!on;an,on;dCndB;en,on;!foBl7y;rd;bCrByd;is;!by;i8ke;al,lA;nFrBshoi;at,nCtB;!r10;aBie;rd0S;!edict,iCjam2nA;ie,y;to;n7rBt;eBy;tt;ey;ar0Xb0Nd0Jgust2hm0Gid6ja0ElZmXnPputsiOrFsaEuCveBya0ziz;ry;gust9st2;us;hi;aIchHi4jun,maFnDon,tBy0;hBu06;ur;av,oB;ld;an,nd0A;el;ie;ta;aq;dGgel05tB;hoEoB;i8nB;!i02y;ne;ny;reBy;!as,s,w;ir,mBos;ar;an,beOd6eIfFi,lEonDphonHt1vB;aMin;on;so,zo;an,en;onCrB;edP;so;c,jaEksandDssaExB;!and3;er;ar,er;ndB;ro;rtH;ni;en;ad,eB;d,t;in;aColfBri0vik;!o;mBn;!a;dFeEraCuB;!bakr,lfazl;hBm;am;!l;allEel,oulaye,ulB;!lCrahm0;an;ah,o;ah;av,on", + "Person": "true¦ashton kutchSbRcMdKeIgastNhGinez,jEkDleCmBnettJoAp8r4s3t2v0;a0irgin maG;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussain,carlett johanssJlobodan milosevic,uB;ay romano,eese witherspoIo1ush limbau0;gh;d stewart,nald0;inho,o;a0ipJ;lmIris hiltD;prah winfrFra;essiaen,itt romnEubarek;bron james,e;anye west,iefer sutherland,obe bryant;aime,effers8k rowli0;ng;alle ber0itlBulk hogan;ry;ff0meril lagasse,zekiel;ie;a0enzel washingt2ick wolf;lt1nte;ar1lint0ruz;on;dinal wols1son0;! palm2;ey;arack obama,rock;er", + "Verb": "true¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en", + "PhrasalVerb": "true¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2fast,oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut", + "Modal": "true¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld", + "Adjective": "true¦0:75;1:7K;2:7Q;3:7J;4:7C;5:5C;6:48;7:49;8:4S;9:61;A:7H;B:70;C:6Z;D:73;E:5X;a6Jb65c5Rd57e4Tf49g41h3Qi35j33k32l2Rm2Gn27o1Rp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6C;d6Ezy;despr75s5G;!sa7;eGlFste26;co1Il o4L;!k5;aGiFola4B;b7Tce versa,ol55;ca2gabo63nilla;ltWnJpGrb5Asu4tterF;!moC; f34b1OpGsFti1H;ca7et,ide dMtairs;er,i3N;aPbeco6Rconvin27deMeLfair,ivers4knKprecedYrIsGwF;iel20ritt5Z;i1VuF;pervis0specti3;eFu5;cognLgul6Hl6H;own;ndi3v5Txpect0;cid0rF;!grou5OsF;iz0tood;b7ppeaLssu6GuthorF;iz0;i24ra;aJeHhough4PoGrF;i1oubl0;geth8p,rpB;en5QlFm50rr2Ust0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3EoPpOqueami3EtJuFymb64;bHi gener55pFrprisi3;erFre0L;! dup8b,i29;du0seq4U;anda6UeIi0PrFy38;aightFip0; fFfF;or5B;adfaCreotyp0;aEec2Gir1JlendBot on; call0le,mb8phist1XrFu0Xvi42;dBry;gnifica2nF;ceEg7;am2Pe8ocki3ut;cFda1em5lfi2Yni1Wpa69re6;o1Gr3W;at58ient28reec58;cr0me,ns serif;aMeIiGoF;buCtt4UuSy4;ghtFv4;!-29f9;ar,bel,condi1du63fres52lHpublic3WsFtard0;is48oF;lu1na2;e1Euc46;bBciF;al,st;aQeOicayu6lacBopuliCrGuF;bl5Amp0;eJiGoF;!b0AfuDmi32p8;mGor,sFva1;ti6;a4We;ciDmF;a0IiF;er,um;ac20rFti1;feAma2Uplexi3v34;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Msi46;en,posi1; boa5Gg2Kli6;!ay; gua5EbFli6;eat;eHsF;cFer0Hole1;e6uE;d2Tse;ak0eMiLoFua4P;nJrGtF;ab7;thF;!eF;rn;chala2descri50stop;ght5;arby,cessa3Xighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuE;di4FnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abEho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3D;!-0C;nguBst,tt8;ap1Tind5no0A;agg0uF;niOstifi0veni7;de4gno4Clleg4mSnHpso 1WrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenDoxF;ic37;a6i2S;a1er,oce2;iGoF;or;reA;deq3Kppr2Z;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0R;d2RnD;aKelJiHoFumdr3C;neCok0rrFs07ur5;if2T;ghfalut1PspF;an2R;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Kiga23lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Eob4;aUeOinNlMoHrF;a1UeFoz1L;e2Eq13tf9;oHrF; keeps,eFm8tuna1;g05ign;liF;sh;ag30ue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lDr Gux,voF;ri1uri1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiE;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erD;creHeas0gruntl0honeCordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarElJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraBg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainCgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerD;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt", + "Comparable": "true¦0:40;1:4H;2:44;3:4A;4:2X;5:3W;a4Nb43c3Nd3Ce34f2Qg2Eh23i1Uj1Tk1Ql1Hm1Bn15o13p0Tqu0Rr0IsRtKuIvFw7y6za11;ell26ou3;aBe9hi1Xi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Lt;k,ry;n1Sr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Lse5;like0ti1;aAen9hi8i7ough,r6;anqu2Pen1ue;dy,g3Tme0ny,r09;ck,n,rs2Q;d41se;ll,me,rt,s6wd46;te5;aVcarUeThRiQkin0FlMmKoHpGqua1GtAu7w6;eet,ift;b7dd14per0Gr6;e,re2I;sta2Gt4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Gn0V;a1ep,rn;le,rk;e23i3Gright0;ci29ft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g36m6;!y;ek,nd3E;ck,l0mp4;a6iTort,rill,y;dy,ll0Yrp;cu0Sve0Sxy;ce,ed,y;d,fe,int0l1Wv15;aBe9i8o6ude;mantic,o1Jsy,u6;gh,nd;ch,pe,tzy;a6d,mo0I;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aEhoDi1RlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fouZud;ey,k0;li05or,te1C;ain,easa2;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd", + "TextValue": "true¦bMeIfChundredNmMnin9one,qu8s6t0zeroN;enMh3rLw0;e0o;l0ntC;fGve;ir0ousandIree;d,t5;e0ix7;cond,ptEven6xtE;adrDintD;e0th;!t0;e9ie8y;i3o0;rt1ur0;!t2;ie4y;ft0rst,ve;e3h,ie2y;ight0lev2;!e1h,ie0y;th;en1;illion0;!th", + "Ordinal": "true¦bGeDf9hundredHmGnin7qu6s4t0zeroH;enGh1rFwe0;lfFn9;ir0ousandE;d,t4;e0ixt9;cond,ptAvent8xtA;adr9int9;et0th;e6ie8;i2o0;r0urt3;tie5;ft1rst;ight0lev1;e0h,ie2;en1;illion0;th", + "Cardinal": "true¦bGeDf7hundred,mGnine9one,qu6s4t0zero;en,h2rFw0;e0o;lve,n7;irt8ousand,ree;e0ix4;ptAven3xtA;adr9int9;i3o0;r1ur0;!t2;ty;ft0ve;e2y;ight0lev1;!e0y;en;illion", + "Expression": "true¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la", + "Adverb": "true¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori", + "Preposition": "true¦'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut", + "Determiner": "true¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er" +}; + +var entity = ['Person', 'Place', 'Organization']; +var nouns = { + Noun: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + // - singular + Singular: { + isA: 'Noun', + notA: 'Plural' + }, + //a specific thing that's capitalized + ProperNoun: { + isA: 'Noun' + }, + // -- people + Person: { + isA: ['ProperNoun', 'Singular'], + notA: ['Place', 'Organization'] + }, + FirstName: { + isA: 'Person' + }, + MaleName: { + isA: 'FirstName', + notA: ['FemaleName', 'LastName'] + }, + FemaleName: { + isA: 'FirstName', + notA: ['MaleName', 'LastName'] + }, + LastName: { + isA: 'Person', + notA: ['FirstName'] + }, + Honorific: { + isA: 'Noun', + notA: ['FirstName', 'LastName'] + }, + // -- places + Place: { + isA: 'Singular', + notA: ['Person', 'Organization'] + }, + Country: { + isA: ['Place', 'ProperNoun'], + notA: ['City'] + }, + City: { + isA: ['Place', 'ProperNoun'], + notA: ['Country'] + }, + Region: { + isA: ['Place', 'ProperNoun'] + }, + Address: { + isA: 'Place' + }, + //---Orgs--- + Organization: { + isA: ['Singular', 'ProperNoun'], + notA: ['Person', 'Place'] + }, + SportsTeam: { + isA: 'Organization' + }, + School: { + isA: 'Organization' + }, + Company: { + isA: 'Organization' + }, + // - plural + Plural: { + isA: 'Noun', + notA: ['Singular'] + }, + //(not plural or singular) + Uncountable: { + isA: 'Noun' + }, + Pronoun: { + isA: 'Noun', + notA: entity + }, + //a word for someone doing something -'plumber' + Actor: { + isA: 'Noun', + notA: entity + }, + //a gerund-as-noun - 'swimming' + Activity: { + isA: 'Noun', + notA: ['Person', 'Place'] + }, + //'kilograms' + Unit: { + isA: 'Noun', + notA: entity + }, + //'Canadians' + Demonym: { + isA: ['Noun', 'ProperNoun'], + notA: entity + }, + //`john's` + Possessive: { + isA: 'Noun' // notA: 'Pronoun', + + } +}; + +var verbs = { + Verb: { + notA: ['Noun', 'Adjective', 'Adverb', 'Value'] + }, + // walks + PresentTense: { + isA: 'Verb', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // neutral form - 'walk' + Infinitive: { + isA: 'PresentTense', + notA: ['PastTense', 'Gerund'] + }, + // walking + Gerund: { + isA: 'PresentTense', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // walked + PastTense: { + isA: 'Verb', + notA: ['FutureTense'] + }, + // will walk + FutureTense: { + isA: 'Verb' + }, + // is + Copula: { + isA: 'Verb' + }, + // would have + Modal: { + isA: 'Verb', + notA: ['Infinitive'] + }, + // had walked + PerfectTense: { + isA: 'Verb', + notA: 'Gerund' + }, + Pluperfect: { + isA: 'Verb' + }, + // shown + Participle: { + isA: 'Verb' + }, + // show up + PhrasalVerb: { + isA: 'Verb' + }, + //'up' part + Particle: { + isA: 'PhrasalVerb' + } +}; + +var values = { + Value: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + Ordinal: { + isA: 'Value', + notA: ['Cardinal'] + }, + Cardinal: { + isA: 'Value', + notA: ['Ordinal'] + }, + RomanNumeral: { + isA: 'Cardinal', + //can be a person, too + notA: ['Ordinal', 'TextValue'] + }, + TextValue: { + isA: 'Value', + notA: ['NumericValue'] + }, + NumericValue: { + isA: 'Value', + notA: ['TextValue'] + }, + Money: { + isA: 'Cardinal' + }, + Percent: { + isA: 'Value' + } +}; + +var anything = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Value']; +var misc = { + //--Adjectives-- + Adjective: { + notA: ['Noun', 'Verb', 'Adverb', 'Value'] + }, + // adjectives that can conjugate + Comparable: { + isA: ['Adjective'] + }, + // better + Comparative: { + isA: ['Adjective'] + }, + // best + Superlative: { + isA: ['Adjective'], + notA: ['Comparative'] + }, + NumberRange: { + isA: ['Contraction'] + }, + Adverb: { + notA: ['Noun', 'Verb', 'Adjective', 'Value'] + }, + // Dates: + //not a noun, but usually is + Date: { + notA: ['Verb', 'Conjunction', 'Adverb', 'Preposition', 'Adjective'] + }, + Month: { + isA: ['Date', 'Singular'], + notA: ['Year', 'WeekDay', 'Time'] + }, + WeekDay: { + isA: ['Date', 'Noun'] + }, + //glue + Determiner: { + notA: anything + }, + Conjunction: { + notA: anything + }, + Preposition: { + notA: anything + }, + // what, who, why + QuestionWord: { + notA: ['Determiner'] + }, + // peso, euro + Currency: {}, + // ughh + Expression: { + notA: ['Noun', 'Adjective', 'Verb', 'Adverb'] + }, + // dr. + Abbreviation: {}, + // internet tags + Url: { + notA: ['HashTag', 'PhoneNumber', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + PhoneNumber: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + HashTag: {}, + AtMention: { + isA: ['Noun'], + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'Email'] + }, + Emoji: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Emoticon: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Email: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + //non-exclusive + Auxiliary: { + notA: ['Noun', 'Adjective', 'Value'] + }, + Acronym: { + notA: ['Plural', 'RomanNumeral'] + }, + Negative: { + notA: ['Noun', 'Adjective', 'Value'] + }, + // if, unless, were + Condition: { + notA: ['Verb', 'Adjective', 'Noun', 'Value'] + } +}; + +// i just made these up +var colorMap = { + Noun: 'blue', + Verb: 'green', + Negative: 'green', + Date: 'red', + Value: 'red', + Adjective: 'magenta', + Preposition: 'cyan', + Conjunction: 'cyan', + Determiner: 'cyan', + Adverb: 'cyan' +}; +/** add a debug color to some tags */ + +var addColors = function addColors(tags) { + Object.keys(tags).forEach(function (k) { + if (colorMap[k]) { + tags[k].color = colorMap[k]; + return; + } + + tags[k].isA.some(function (t) { + if (colorMap[t]) { + tags[k].color = colorMap[t]; + return true; + } + + return false; + }); + }); + return tags; +}; + +var _color = addColors; + +var unique$2 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); +}; //add 'downward' tags (that immediately depend on this one) + + +var inferIsA = function inferIsA(tags) { + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; + var len = tag.isA.length; + + for (var i = 0; i < len; i++) { + var down = tag.isA[i]; + + if (tags[down]) { + tag.isA = tag.isA.concat(tags[down].isA); + } + } // clean it up + + + tag.isA = unique$2(tag.isA); + }); + return tags; +}; + +var _isA = inferIsA; + +var unique$3 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); +}; // crawl the tag-graph and infer any conflicts +// faster than doing this at tag-time + + +var inferNotA = function inferNotA(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.notA = tag.notA || []; + tag.isA.forEach(function (down) { + if (tags[down] && tags[down].notA) { + // borrow its conflicts + var notA = typeof tags[down].notA === 'string' ? [tags[down].isA] : tags[down].notA || []; + tag.notA = tag.notA.concat(notA); + } + }); // any tag that lists us as a conflict, we conflict it back. + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + + if (tags[key].notA.indexOf(k) !== -1) { + tag.notA.push(key); + } + } // clean it up + + + tag.notA = unique$3(tag.notA); + }); + return tags; +}; + +var _notA = inferNotA; + +// a lineage is all 'incoming' tags that have this as 'isA' +var inferLineage = function inferLineage(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.lineage = []; // find all tags with it in their 'isA' set + + for (var i = 0; i < keys.length; i++) { + if (tags[keys[i]].isA.indexOf(k) !== -1) { + tag.lineage.push(keys[i]); + } + } + }); + return tags; +}; + +var _lineage = inferLineage; + +var validate = function validate(tags) { + // cleanup format + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; // ensure isA is an array + + tag.isA = tag.isA || []; + + if (typeof tag.isA === 'string') { + tag.isA = [tag.isA]; + } // ensure notA is an array + + + tag.notA = tag.notA || []; + + if (typeof tag.notA === 'string') { + tag.notA = [tag.notA]; + } + }); + return tags; +}; // build-out the tag-graph structure + + +var inferTags = function inferTags(tags) { + // validate data + tags = validate(tags); // build its 'down tags' + + tags = _isA(tags); // infer the conflicts + + tags = _notA(tags); // debug tag color + + tags = _color(tags); // find incoming links + + tags = _lineage(tags); + return tags; +}; + +var inference = inferTags; + +var addIn = function addIn(obj, tags) { + Object.keys(obj).forEach(function (k) { + tags[k] = obj[k]; + }); +}; + +var build = function build() { + var tags = {}; + addIn(nouns, tags); + addIn(verbs, tags); + addIn(values, tags); + addIn(misc, tags); // do the graph-stuff + + tags = inference(tags); + return tags; +}; + +var tags = build(); + +var seq = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", + cache = seq.split("").reduce(function (n, o, e) { + return n[o] = e, n; +}, {}), + toAlphaCode = function toAlphaCode(n) { + if (void 0 !== seq[n]) return seq[n]; + var o = 1, + e = 36, + t = ""; + + for (; n >= e; n -= e, o++, e *= 36) { + } + + for (; o--;) { + var _o = n % 36; + + t = String.fromCharCode((_o < 10 ? 48 : 55) + _o) + t, n = (n - _o) / 36; + } + + return t; +}, + fromAlphaCode = function fromAlphaCode(n) { + if (void 0 !== cache[n]) return cache[n]; + var o = 0, + e = 1, + t = 36, + r = 1; + + for (; e < n.length; o += t, e++, t *= 36) { + } + + for (var _e = n.length - 1; _e >= 0; _e--, r *= 36) { + var _t = n.charCodeAt(_e) - 48; + + _t > 10 && (_t -= 7), o += _t * r; + } + + return o; +}; + +var encoding = { + toAlphaCode: toAlphaCode, + fromAlphaCode: fromAlphaCode +}, + symbols = function symbols(n) { + var o = new RegExp("([0-9A-Z]+):([0-9A-Z]+)"); + + for (var e = 0; e < n.nodes.length; e++) { + var t = o.exec(n.nodes[e]); + + if (!t) { + n.symCount = e; + break; + } + + n.syms[encoding.fromAlphaCode(t[1])] = encoding.fromAlphaCode(t[2]); + } + + n.nodes = n.nodes.slice(n.symCount, n.nodes.length); +}; + +var indexFromRef = function indexFromRef(n, o, e) { + var t = encoding.fromAlphaCode(o); + return t < n.symCount ? n.syms[t] : e + t + 1 - n.symCount; +}, + toArray = function toArray(n) { + var o = [], + e = function e(t, r) { + var s = n.nodes[t]; + "!" === s[0] && (o.push(r), s = s.slice(1)); + var c = s.split(/([A-Z0-9,]+)/g); + + for (var _s = 0; _s < c.length; _s += 2) { + var u = c[_s], + i = c[_s + 1]; + if (!u) continue; + var l = r + u; + + if ("," === i || void 0 === i) { + o.push(l); + continue; + } + + var f = indexFromRef(n, i, t); + e(f, l); + } + }; + + return e(0, ""), o; +}, + unpack = function unpack(n) { + var o = { + nodes: n.split(";"), + syms: [], + symCount: 0 + }; + return n.match(":") && symbols(o), toArray(o); +}; + +var unpack_1 = unpack, + unpack_1$1 = function unpack_1$1(n) { + var o = n.split("|").reduce(function (n, o) { + var e = o.split("¦"); + return n[e[0]] = e[1], n; + }, {}), + e = {}; + return Object.keys(o).forEach(function (n) { + var t = unpack_1(o[n]); + "true" === n && (n = !0); + + for (var _o2 = 0; _o2 < t.length; _o2++) { + var r = t[_o2]; + !0 === e.hasOwnProperty(r) ? !1 === Array.isArray(e[r]) ? e[r] = [e[r], n] : e[r].push(n) : e[r] = n; + } + }), e; +}; + +var efrtUnpack_min = unpack_1$1; + +//safely add it to the lexicon +var addWord = function addWord(word, tag, lex) { + if (lex[word] !== undefined) { + if (typeof lex[word] === 'string') { + lex[word] = [lex[word]]; + } + + lex[word].push(tag); + } else { + lex[word] = tag; + } +}; // blast-out more forms for some given words + + +var addMore = function addMore(word, tag, world) { + var lexicon = world.words; + var transform = world.transforms; // cache multi-words + + var words = word.split(' '); + + if (words.length > 1) { + //cache the beginning word + world.hasCompound[words[0]] = true; + } // inflect our nouns + + + if (tag === 'Singular') { + var plural = transform.toPlural(word, world); + lexicon[plural] = lexicon[plural] || 'Plural'; // only if it's safe + } //conjugate our verbs + + + if (tag === 'Infinitive') { + var conj = transform.conjugate(word, world); + var tags = Object.keys(conj); + + for (var i = 0; i < tags.length; i++) { + var w = conj[tags[i]]; + lexicon[w] = lexicon[w] || tags[i]; // only if it's safe + } + } //derive more adjective forms + + + if (tag === 'Comparable') { + var _conj = transform.adjectives(word); + + var _tags = Object.keys(_conj); + + for (var _i = 0; _i < _tags.length; _i++) { + var _w = _conj[_tags[_i]]; + lexicon[_w] = lexicon[_w] || _tags[_i]; // only if it's safe + } + } //conjugate phrasal-verbs + + + if (tag === 'PhrasalVerb') { + //add original form + addWord(word, 'Infinitive', lexicon); //conjugate first word + + var _conj2 = transform.conjugate(words[0], world); + + var _tags2 = Object.keys(_conj2); + + for (var _i2 = 0; _i2 < _tags2.length; _i2++) { + //add it to our cache + world.hasCompound[_conj2[_tags2[_i2]]] = true; //first + last words + + var _w2 = _conj2[_tags2[_i2]] + ' ' + words[1]; + + addWord(_w2, _tags2[_i2], lexicon); + addWord(_w2, 'PhrasalVerb', lexicon); + } + } // inflect our demonyms - 'germans' + + + if (tag === 'Demonym') { + var _plural = transform.toPlural(word, world); + + lexicon[_plural] = lexicon[_plural] || ['Demonym', 'Plural']; // only if it's safe + } +}; // throw a bunch of words in our lexicon +// const doWord = function(words, tag, world) { +// let lexicon = world.words +// for (let i = 0; i < words.length; i++) { +// addWord(words[i], tag, lexicon) +// // do some fancier stuff +// addMore(words[i], tag, world) +// } +// } + + +var addWords = { + addWord: addWord, + addMore: addMore +}; + +// add words from plurals and conjugations data +var addIrregulars = function addIrregulars(world) { + //add irregular plural nouns + var nouns = world.irregulars.nouns; + var words = Object.keys(nouns); + + for (var i = 0; i < words.length; i++) { + var w = words[i]; + world.words[w] = 'Singular'; + world.words[nouns[w]] = 'Plural'; + } // add irregular verb conjugations + + + var verbs = world.irregulars.verbs; + var keys = Object.keys(verbs); + + var _loop = function _loop(_i) { + var inf = keys[_i]; //add only if it it's safe... + + world.words[inf] = world.words[inf] || 'Infinitive'; + var forms = world.transforms.conjugate(inf, world); + forms = Object.assign(forms, verbs[inf]); //add the others + + Object.keys(forms).forEach(function (tag) { + world.words[forms[tag]] = world.words[forms[tag]] || tag; + }); + }; + + for (var _i = 0; _i < keys.length; _i++) { + _loop(_i); + } +}; + +var addIrregulars_1 = addIrregulars; + +//words that can't be compressed, for whatever reason +var misc$1 = { + // numbers + '20th century fox': 'Organization', + // '3m': 'Organization', + '7 eleven': 'Organization', + '7-eleven': 'Organization', + g8: 'Organization', + 'motel 6': 'Organization', + vh1: 'Organization', + q1: 'Date', + q2: 'Date', + q3: 'Date', + q4: 'Date' +}; + +//nouns with irregular plural/singular forms +//used in noun.inflect, and also in the lexicon. +var plurals = { + addendum: 'addenda', + alga: 'algae', + alumna: 'alumnae', + alumnus: 'alumni', + analysis: 'analyses', + antenna: 'antennae', + appendix: 'appendices', + avocado: 'avocados', + axis: 'axes', + bacillus: 'bacilli', + barracks: 'barracks', + beau: 'beaux', + bus: 'buses', + cactus: 'cacti', + chateau: 'chateaux', + child: 'children', + circus: 'circuses', + clothes: 'clothes', + corpus: 'corpora', + criterion: 'criteria', + curriculum: 'curricula', + database: 'databases', + deer: 'deer', + diagnosis: 'diagnoses', + echo: 'echoes', + embargo: 'embargoes', + epoch: 'epochs', + foot: 'feet', + formula: 'formulae', + fungus: 'fungi', + genus: 'genera', + goose: 'geese', + halo: 'halos', + hippopotamus: 'hippopotami', + index: 'indices', + larva: 'larvae', + leaf: 'leaves', + libretto: 'libretti', + loaf: 'loaves', + man: 'men', + matrix: 'matrices', + memorandum: 'memoranda', + modulus: 'moduli', + mosquito: 'mosquitoes', + mouse: 'mice', + move: 'moves', + nebula: 'nebulae', + nucleus: 'nuclei', + octopus: 'octopi', + opus: 'opera', + ovum: 'ova', + ox: 'oxen', + parenthesis: 'parentheses', + person: 'people', + phenomenon: 'phenomena', + prognosis: 'prognoses', + quiz: 'quizzes', + radius: 'radii', + referendum: 'referenda', + rodeo: 'rodeos', + sex: 'sexes', + shoe: 'shoes', + sombrero: 'sombreros', + stimulus: 'stimuli', + stomach: 'stomachs', + syllabus: 'syllabi', + synopsis: 'synopses', + tableau: 'tableaux', + thesis: 'theses', + thief: 'thieves', + tooth: 'teeth', + tornado: 'tornados', + tuxedo: 'tuxedos', + vertebra: 'vertebrae' // virus: 'viri', + // zero: 'zeros', + +}; + +// a list of irregular verb conjugations +// used in verbs().conjugate() +// but also added to our lexicon +//use shorter key-names +var mapping = { + g: 'Gerund', + prt: 'Participle', + perf: 'PerfectTense', + pst: 'PastTense', + fut: 'FuturePerfect', + pres: 'PresentTense', + pluperf: 'Pluperfect', + a: 'Actor' +}; // '_' in conjugations is the infinitive form + +var conjugations = { + act: { + a: '_or' + }, + age: { + g: 'ageing', + pst: 'aged', + pres: 'ages' + }, + aim: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + arise: { + prt: '_n', + pst: 'arose' + }, + babysit: { + a: '_ter', + pst: 'babysat' + }, + ban: { + a: '', + g: '_ning', + pst: '_ned' + }, + be: { + a: '', + g: 'am', + prt: 'been', + pst: 'was', + pres: 'is' + }, + beat: { + a: '_er', + g: '_ing', + prt: '_en' + }, + become: { + prt: '_' + }, + begin: { + g: '_ning', + prt: 'begun', + pst: 'began' + }, + being: { + g: 'are', + pst: 'were', + pres: 'are' + }, + bend: { + prt: 'bent' + }, + bet: { + a: '_ter', + prt: '_' + }, + bind: { + pst: 'bound' + }, + bite: { + g: 'biting', + prt: 'bitten', + pst: 'bit' + }, + bleed: { + prt: 'bled', + pst: 'bled' + }, + blow: { + prt: '_n', + pst: 'blew' + }, + boil: { + a: '_er' + }, + brake: { + prt: 'broken' + }, + "break": { + pst: 'broke' + }, + breed: { + pst: 'bred' + }, + bring: { + prt: 'brought', + pst: 'brought' + }, + broadcast: { + pst: '_' + }, + budget: { + pst: '_ed' + }, + build: { + prt: 'built', + pst: 'built' + }, + burn: { + prt: '_ed' + }, + burst: { + prt: '_' + }, + buy: { + prt: 'bought', + pst: 'bought' + }, + can: { + a: '', + fut: '_', + g: '', + pst: 'could', + perf: 'could', + pluperf: 'could', + pres: '_' + }, + "catch": { + pst: 'caught' + }, + choose: { + g: 'choosing', + prt: 'chosen', + pst: 'chose' + }, + cling: { + prt: 'clung' + }, + come: { + prt: '_', + pst: 'came' + }, + compete: { + a: 'competitor', + g: 'competing', + pst: '_d' + }, + cost: { + pst: '_' + }, + creep: { + prt: 'crept' + }, + cut: { + prt: '_' + }, + deal: { + prt: '_t', + pst: '_t' + }, + develop: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + die: { + g: 'dying', + pst: '_d' + }, + dig: { + g: '_ging', + prt: 'dug', + pst: 'dug' + }, + dive: { + prt: '_d' + }, + "do": { + pst: 'did', + pres: '_es' + }, + draw: { + prt: '_n', + pst: 'drew' + }, + dream: { + prt: '_t' + }, + drink: { + prt: 'drunk', + pst: 'drank' + }, + drive: { + g: 'driving', + prt: '_n', + pst: 'drove' + }, + drop: { + g: '_ping', + pst: '_ped' + }, + eat: { + a: '_er', + g: '_ing', + prt: '_en', + pst: 'ate' + }, + edit: { + g: '_ing' + }, + egg: { + pst: '_ed' + }, + fall: { + prt: '_en', + pst: 'fell' + }, + feed: { + prt: 'fed', + pst: 'fed' + }, + feel: { + a: '_er', + pst: 'felt' + }, + fight: { + prt: 'fought', + pst: 'fought' + }, + find: { + pst: 'found' + }, + flee: { + g: '_ing', + prt: 'fled' + }, + fling: { + prt: 'flung' + }, + fly: { + prt: 'flown', + pst: 'flew' + }, + forbid: { + pst: 'forbade' + }, + forget: { + g: '_ing', + prt: 'forgotten', + pst: 'forgot' + }, + forgive: { + g: 'forgiving', + prt: '_n', + pst: 'forgave' + }, + free: { + a: '', + g: '_ing' + }, + freeze: { + g: 'freezing', + prt: 'frozen', + pst: 'froze' + }, + get: { + pst: 'got', + prt: 'gotten' + }, + give: { + g: 'giving', + prt: '_n', + pst: 'gave' + }, + go: { + prt: '_ne', + pst: 'went', + pres: 'goes' + }, + grow: { + prt: '_n' + }, + hang: { + prt: 'hung', + pst: 'hung' + }, + have: { + g: 'having', + prt: 'had', + pst: 'had', + pres: 'has' + }, + hear: { + prt: '_d', + pst: '_d' + }, + hide: { + prt: 'hidden', + pst: 'hid' + }, + hit: { + prt: '_' + }, + hold: { + prt: 'held', + pst: 'held' + }, + hurt: { + prt: '_', + pst: '_' + }, + ice: { + g: 'icing', + pst: '_d' + }, + imply: { + pst: 'implied', + pres: 'implies' + }, + is: { + a: '', + g: 'being', + pst: 'was', + pres: '_' + }, + keep: { + prt: 'kept' + }, + kneel: { + prt: 'knelt' + }, + know: { + prt: '_n' + }, + lay: { + prt: 'laid', + pst: 'laid' + }, + lead: { + prt: 'led', + pst: 'led' + }, + leap: { + prt: '_t' + }, + leave: { + prt: 'left', + pst: 'left' + }, + lend: { + prt: 'lent' + }, + lie: { + g: 'lying', + pst: 'lay' + }, + light: { + prt: 'lit', + pst: 'lit' + }, + log: { + g: '_ging', + pst: '_ged' + }, + loose: { + prt: 'lost' + }, + lose: { + g: 'losing', + pst: 'lost' + }, + make: { + prt: 'made', + pst: 'made' + }, + mean: { + prt: '_t', + pst: '_t' + }, + meet: { + a: '_er', + g: '_ing', + prt: 'met', + pst: 'met' + }, + miss: { + pres: '_' + }, + pay: { + prt: 'paid', + pst: 'paid' + }, + prove: { + prt: '_n' + }, + puke: { + g: 'puking' + }, + put: { + prt: '_' + }, + quit: { + prt: '_' + }, + read: { + prt: '_', + pst: '_' + }, + ride: { + prt: 'ridden' + }, + ring: { + prt: 'rung', + pst: 'rang' + }, + rise: { + fut: 'will have _n', + g: 'rising', + prt: '_n', + pst: 'rose', + pluperf: 'had _n' + }, + rub: { + g: '_bing', + pst: '_bed' + }, + run: { + g: '_ning', + prt: '_', + pst: 'ran' + }, + say: { + prt: 'said', + pst: 'said', + pres: '_s' + }, + seat: { + prt: 'sat' + }, + see: { + g: '_ing', + prt: '_n', + pst: 'saw' + }, + seek: { + prt: 'sought' + }, + sell: { + prt: 'sold', + pst: 'sold' + }, + send: { + prt: 'sent' + }, + set: { + prt: '_' + }, + sew: { + prt: '_n' + }, + shake: { + prt: '_n' + }, + shave: { + prt: '_d' + }, + shed: { + g: '_ding', + pst: '_', + pres: '_s' + }, + shine: { + prt: 'shone', + pst: 'shone' + }, + shoot: { + prt: 'shot', + pst: 'shot' + }, + show: { + pst: '_ed' + }, + shut: { + prt: '_' + }, + sing: { + prt: 'sung', + pst: 'sang' + }, + sink: { + pst: 'sank', + pluperf: 'had sunk' + }, + sit: { + pst: 'sat' + }, + ski: { + pst: '_ied' + }, + slay: { + prt: 'slain' + }, + sleep: { + prt: 'slept' + }, + slide: { + prt: 'slid', + pst: 'slid' + }, + smash: { + pres: '_es' + }, + sneak: { + prt: 'snuck' + }, + speak: { + fut: 'will have spoken', + prt: 'spoken', + pst: 'spoke', + perf: 'have spoken', + pluperf: 'had spoken' + }, + speed: { + prt: 'sped' + }, + spend: { + prt: 'spent' + }, + spill: { + prt: '_ed', + pst: 'spilt' + }, + spin: { + g: '_ning', + prt: 'spun', + pst: 'spun' + }, + spit: { + prt: 'spat' + }, + split: { + prt: '_' + }, + spread: { + pst: '_' + }, + spring: { + prt: 'sprung' + }, + stand: { + pst: 'stood' + }, + steal: { + a: '_er', + pst: 'stole' + }, + stick: { + pst: 'stuck' + }, + sting: { + pst: 'stung' + }, + stink: { + prt: 'stunk', + pst: 'stunk' + }, + stream: { + a: '_er' + }, + strew: { + prt: '_n' + }, + strike: { + g: 'striking', + pst: 'struck' + }, + suit: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + sware: { + prt: 'sworn' + }, + swear: { + pst: 'swore' + }, + sweep: { + prt: 'swept' + }, + swim: { + g: '_ming', + pst: 'swam' + }, + swing: { + pst: 'swung' + }, + take: { + fut: 'will have _n', + pst: 'took', + perf: 'have _n', + pluperf: 'had _n' + }, + teach: { + pst: 'taught', + pres: '_es' + }, + tear: { + pst: 'tore' + }, + tell: { + pst: 'told' + }, + think: { + pst: 'thought' + }, + thrive: { + prt: '_d' + }, + tie: { + g: 'tying', + pst: '_d' + }, + undergo: { + prt: '_ne' + }, + understand: { + pst: 'understood' + }, + upset: { + prt: '_' + }, + wait: { + a: '_er', + g: '_ing', + pst: '_ed' + }, + wake: { + pst: 'woke' + }, + wear: { + pst: 'wore' + }, + weave: { + prt: 'woven' + }, + weep: { + prt: 'wept' + }, + win: { + g: '_ning', + pst: 'won' + }, + wind: { + prt: 'wound' + }, + withdraw: { + pst: 'withdrew' + }, + wring: { + prt: 'wrung' + }, + write: { + g: 'writing', + prt: 'written', + pst: 'wrote' + } +}; //uncompress our ad-hoc compression scheme + +var keys = Object.keys(conjugations); + +var _loop = function _loop(i) { + var inf = keys[i]; + var _final = {}; + Object.keys(conjugations[inf]).forEach(function (key) { + var str = conjugations[inf][key]; //swap-in infinitives for '_' + + str = str.replace('_', inf); + var full = mapping[key]; + _final[full] = str; + }); //over-write original + + conjugations[inf] = _final; +}; + +for (var i = 0; i < keys.length; i++) { + _loop(i); +} + +var conjugations_1 = conjugations; + +var endsWith = { + b: [{ + reg: /([^aeiou][aeiou])b$/i, + repl: { + pr: '$1bs', + pa: '$1bbed', + gr: '$1bbing' + } + }], + d: [{ + reg: /(end)$/i, + repl: { + pr: '$1s', + pa: 'ent', + gr: '$1ing', + ar: '$1er' + } + }, { + reg: /(eed)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + ar: '$1er' + } + }, { + reg: /(ed)$/i, + repl: { + pr: '$1s', + pa: '$1ded', + ar: '$1der', + gr: '$1ding' + } + }, { + reg: /([^aeiou][ou])d$/i, + repl: { + pr: '$1ds', + pa: '$1dded', + gr: '$1dding' + } + }], + e: [{ + reg: /(eave)$/i, + repl: { + pr: '$1s', + pa: '$1d', + gr: 'eaving', + ar: '$1r' + } + }, { + reg: /(ide)$/i, + repl: { + pr: '$1s', + pa: 'ode', + gr: 'iding', + ar: 'ider' + } + }, { + reg: /(ake)$/i, + repl: { + pr: '$1s', + pa: 'ook', + gr: 'aking', + ar: '$1r' + } + }, { + reg: /(a[tg]|i[zn]|ur|nc|gl|is)e$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing', + prt: '$1en' + } + }, { + reg: /([bd]l)e$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /(om)e$/i, + repl: { + pr: '$1es', + pa: 'ame', + gr: '$1ing' + } + }], + g: [{ + reg: /([^aeiou][ou])g$/i, + repl: { + pr: '$1gs', + pa: '$1gged', + gr: '$1gging' + } + }], + h: [{ + reg: /(..)([cs]h)$/i, + repl: { + pr: '$1$2es', + pa: '$1$2ed', + gr: '$1$2ing' + } + }], + k: [{ + reg: /(ink)$/i, + repl: { + pr: '$1s', + pa: 'unk', + gr: '$1ing', + ar: '$1er' + } + }], + m: [{ + reg: /([^aeiou][aeiou])m$/i, + repl: { + pr: '$1ms', + pa: '$1mmed', + gr: '$1mming' + } + }], + n: [{ + reg: /(en)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }], + p: [{ + reg: /(e)(ep)$/i, + repl: { + pr: '$1$2s', + pa: '$1pt', + gr: '$1$2ing', + ar: '$1$2er' + } + }, { + reg: /([^aeiou][aeiou])p$/i, + repl: { + pr: '$1ps', + pa: '$1pped', + gr: '$1pping' + } + }, { + reg: /([aeiu])p$/i, + repl: { + pr: '$1ps', + pa: '$1p', + gr: '$1pping' + } + }], + r: [{ + reg: /([td]er)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /(er)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }], + s: [{ + reg: /(ish|tch|ess)$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing' + } + }], + t: [{ + reg: /(ion|end|e[nc]t)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /(.eat)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing' + } + }, { + reg: /([aeiu])t$/i, + repl: { + pr: '$1ts', + pa: '$1t', + gr: '$1tting' + } + }, { + reg: /([^aeiou][aeiou])t$/i, + repl: { + pr: '$1ts', + pa: '$1tted', + gr: '$1tting' + } + }], + w: [{ + reg: /(..)(ow)$/i, + repl: { + pr: '$1$2s', + pa: '$1ew', + gr: '$1$2ing', + prt: '$1$2n' + } + }], + y: [{ + reg: /([i|f|rr])y$/i, + repl: { + pr: '$1ies', + pa: '$1ied', + gr: '$1ying' + } + }], + z: [{ + reg: /([aeiou]zz)$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing' + } + }] +}; +var suffixes = endsWith; + +var posMap = { + pr: 'PresentTense', + pa: 'PastTense', + gr: 'Gerund', + prt: 'Participle', + ar: 'Actor' +}; + +var doTransform = function doTransform(str, obj) { + var found = {}; + var keys = Object.keys(obj.repl); + + for (var i = 0; i < keys.length; i += 1) { + var pos = keys[i]; + found[posMap[pos]] = str.replace(obj.reg, obj.repl[pos]); + } + + return found; +}; //look at the end of the word for clues + + +var checkSuffix = function checkSuffix() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var c = str[str.length - 1]; + + if (suffixes.hasOwnProperty(c) === true) { + for (var r = 0; r < suffixes[c].length; r += 1) { + var reg = suffixes[c][r].reg; + + if (reg.test(str) === true) { + return doTransform(str, suffixes[c][r]); + } + } + } + + return {}; +}; + +var _01Suffixes = checkSuffix; + +//non-specifc, 'hail-mary' transforms from infinitive, into other forms +var hasY = /[bcdfghjklmnpqrstvwxz]y$/; +var generic = { + Gerund: function Gerund(inf) { + if (inf.charAt(inf.length - 1) === 'e') { + return inf.replace(/e$/, 'ing'); + } + + return inf + 'ing'; + }, + PresentTense: function PresentTense(inf) { + if (inf.charAt(inf.length - 1) === 's') { + return inf + 'es'; + } + + if (hasY.test(inf) === true) { + return inf.slice(0, -1) + 'ies'; + } + + return inf + 's'; + }, + PastTense: function PastTense(inf) { + if (inf.charAt(inf.length - 1) === 'e') { + return inf + 'd'; + } + + if (inf.substr(-2) === 'ed') { + return inf; + } + + if (hasY.test(inf) === true) { + return inf.slice(0, -1) + 'ied'; + } + + return inf + 'ed'; + } +}; +var _02Generic = generic; + +//we assume the input word is a proper infinitive + +var conjugate = function conjugate() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var world = arguments.length > 1 ? arguments[1] : undefined; + var found = {}; // 1. look at irregulars + //the lexicon doesn't pass this in + + if (world && world.irregulars) { + if (world.irregulars.verbs.hasOwnProperty(str) === true) { + found = Object.assign({}, world.irregulars.verbs[str]); + } + } //2. rule-based regex + + + found = Object.assign({}, _01Suffixes(str), found); //3. generic transformations + //'buzzing' + + if (found.Gerund === undefined) { + found.Gerund = _02Generic.Gerund(str); + } //'buzzed' + + + if (found.PastTense === undefined) { + found.PastTense = _02Generic.PastTense(str); + } //'buzzes' + + + if (found.PresentTense === undefined) { + found.PresentTense = _02Generic.PresentTense(str); + } + + return found; +}; + +var conjugate_1 = conjugate; + +//turn 'quick' into 'quickest' +var do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /oud$/, /...p$/]; +var dont_rules = [/ary$/]; +var irregulars = { + nice: 'nicest', + late: 'latest', + hard: 'hardest', + inner: 'innermost', + outer: 'outermost', + far: 'furthest', + worse: 'worst', + bad: 'worst', + good: 'best', + big: 'biggest', + large: 'largest' +}; +var transforms = [{ + reg: /y$/i, + repl: 'iest' +}, { + reg: /([aeiou])t$/i, + repl: '$1ttest' +}, { + reg: /([aeou])de$/i, + repl: '$1dest' +}, { + reg: /nge$/i, + repl: 'ngest' +}, { + reg: /([aeiou])te$/i, + repl: '$1test' +}]; + +var to_superlative = function to_superlative(str) { + //irregulars + if (irregulars.hasOwnProperty(str)) { + return irregulars[str]; + } //known transforms + + + for (var i = 0; i < transforms.length; i++) { + if (transforms[i].reg.test(str)) { + return str.replace(transforms[i].reg, transforms[i].repl); + } + } //dont-rules + + + for (var _i = 0; _i < dont_rules.length; _i++) { + if (dont_rules[_i].test(str) === true) { + return null; + } + } //do-rules + + + for (var _i2 = 0; _i2 < do_rules.length; _i2++) { + if (do_rules[_i2].test(str) === true) { + if (str.charAt(str.length - 1) === 'e') { + return str + 'st'; + } + + return str + 'est'; + } + } + + return str + 'est'; +}; + +var toSuperlative = to_superlative; + +//turn 'quick' into 'quickly' +var do_rules$1 = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /old$/, /oud$/, /e[ae]p$/]; +var dont_rules$1 = [/ary$/, /ous$/]; +var irregulars$1 = { + grey: 'greyer', + gray: 'grayer', + green: 'greener', + yellow: 'yellower', + red: 'redder', + good: 'better', + well: 'better', + bad: 'worse', + sad: 'sadder', + big: 'bigger' +}; +var transforms$1 = [{ + reg: /y$/i, + repl: 'ier' +}, { + reg: /([aeiou])t$/i, + repl: '$1tter' +}, { + reg: /([aeou])de$/i, + repl: '$1der' +}, { + reg: /nge$/i, + repl: 'nger' +}]; + +var to_comparative = function to_comparative(str) { + //known-irregulars + if (irregulars$1.hasOwnProperty(str)) { + return irregulars$1[str]; + } //known-transforms + + + for (var i = 0; i < transforms$1.length; i++) { + if (transforms$1[i].reg.test(str) === true) { + return str.replace(transforms$1[i].reg, transforms$1[i].repl); + } + } //dont-patterns + + + for (var _i = 0; _i < dont_rules$1.length; _i++) { + if (dont_rules$1[_i].test(str) === true) { + return null; + } + } //do-patterns + + + for (var _i2 = 0; _i2 < do_rules$1.length; _i2++) { + if (do_rules$1[_i2].test(str) === true) { + return str + 'er'; + } + } //easy-one + + + if (/e$/.test(str) === true) { + return str + 'r'; + } + + return str + 'er'; +}; + +var toComparative = to_comparative; + +var fns$1 = { + toSuperlative: toSuperlative, + toComparative: toComparative +}; +/** conjugate an adjective into other forms */ + +var conjugate$1 = function conjugate(w) { + var res = {}; // 'greatest' + + var sup = fns$1.toSuperlative(w); + + if (sup) { + res.Superlative = sup; + } // 'greater' + + + var comp = fns$1.toComparative(w); + + if (comp) { + res.Comparative = comp; + } + + return res; +}; + +var adjectives = conjugate$1; + +/** patterns for turning 'bus' to 'buses'*/ +var suffixes$1 = { + a: [[/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae'], [/([ti])a$/i, '$1a']], + e: [[/(kn|l|w)ife$/i, '$1ives'], [/(hive)$/i, '$1s'], [/([m|l])ouse$/i, '$1ice'], [/([m|l])ice$/i, '$1ice']], + f: [[/^(dwar|handkerchie|hoo|scar|whar)f$/i, '$1ves'], [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)f$/i, '$1ves']], + i: [[/(octop|vir)i$/i, '$1i']], + m: [[/([ti])um$/i, '$1a']], + n: [[/^(oxen)$/i, '$1']], + o: [[/(al|ad|at|er|et|ed|ad)o$/i, '$1oes']], + s: [[/(ax|test)is$/i, '$1es'], [/(alias|status)$/i, '$1es'], [/sis$/i, 'ses'], [/(bu)s$/i, '$1ses'], [/(sis)$/i, 'ses'], [/^(?!talis|.*hu)(.*)man$/i, '$1men'], [/(octop|vir|radi|nucle|fung|cact|stimul)us$/i, '$1i']], + x: [[/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices'], [/^(ox)$/i, '$1en']], + y: [[/([^aeiouy]|qu)y$/i, '$1ies']], + z: [[/(quiz)$/i, '$1zes']] +}; +var _rules = suffixes$1; + +var addE = /(x|ch|sh|s|z)$/; + +var trySuffix = function trySuffix(str) { + var c = str[str.length - 1]; + + if (_rules.hasOwnProperty(c) === true) { + for (var i = 0; i < _rules[c].length; i += 1) { + var reg = _rules[c][i][0]; + + if (reg.test(str) === true) { + return str.replace(reg, _rules[c][i][1]); + } + } + } + + return null; +}; +/** Turn a singular noun into a plural + * assume the given string is singular + */ + + +var pluralize = function pluralize() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var world = arguments.length > 1 ? arguments[1] : undefined; + var irregulars = world.irregulars.nouns; // check irregulars list + + if (irregulars.hasOwnProperty(str)) { + return irregulars[str]; + } //we have some rules to try-out + + + var plural = trySuffix(str); + + if (plural !== null) { + return plural; + } //like 'church' + + + if (addE.test(str)) { + return str + 'es'; + } // ¯\_(ツ)_/¯ + + + return str + 's'; +}; + +var toPlural = pluralize; + +//patterns for turning 'dwarves' to 'dwarf' +var _rules$1 = [[/([^v])ies$/i, '$1y'], [/ises$/i, 'isis'], [/(kn|[^o]l|w)ives$/i, '$1ife'], [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i, '$1f'], [/^(dwar|handkerchie|hoo|scar|whar)ves$/i, '$1f'], [/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a'], [/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i, '$1us'], [/(buffal|tomat|tornad)(oes)$/i, '$1o'], // [/(analy|diagno|parenthe|progno|synop|the)ses$/i, '$1sis'], +[/(..[aeiou]s)es$/i, '$1'], [/(vert|ind|cort)(ices)$/i, '$1ex'], [/(matr|append)(ices)$/i, '$1ix'], [/(x|ch|ss|sh|z|o)es$/i, '$1'], [/men$/i, 'man'], [/(n)ews$/i, '$1ews'], [/([ti])a$/i, '$1um'], [/([^aeiouy]|qu)ies$/i, '$1y'], [/(s)eries$/i, '$1eries'], [/(m)ovies$/i, '$1ovie'], [/([m|l])ice$/i, '$1ouse'], [/(cris|ax|test)es$/i, '$1is'], [/(alias|status)es$/i, '$1'], [/(ss)$/i, '$1'], [/(ics)$/i, '$1'], [/s$/i, '']]; + +var invertObj = function invertObj(obj) { + return Object.keys(obj).reduce(function (h, k) { + h[obj[k]] = k; + return h; + }, {}); +}; + +var toSingular = function toSingular(str, world) { + var irregulars = world.irregulars.nouns; + var invert = invertObj(irregulars); // check irregulars list + + if (invert.hasOwnProperty(str)) { + return invert[str]; + } // go through our regexes + + + for (var i = 0; i < _rules$1.length; i++) { + if (_rules$1[i][0].test(str) === true) { + str = str.replace(_rules$1[i][0], _rules$1[i][1]); + return str; + } + } + + return str; +}; + +var toSingular_1 = toSingular; + +//rules for turning a verb into infinitive form +var rules = { + Participle: [{ + reg: /own$/i, + to: 'ow' + }, { + reg: /(.)un([g|k])$/i, + to: '$1in$2' + }], + Actor: [{ + reg: /(er)er$/i, + to: '$1' + }], + PresentTense: [{ + reg: /(..)(ies)$/i, + to: '$1y' + }, { + reg: /(tch|sh)es$/i, + to: '$1' + }, { + reg: /(ss|zz)es$/i, + to: '$1' + }, { + reg: /([tzlshicgrvdnkmu])es$/i, + to: '$1e' + }, { + reg: /(n[dtk]|c[kt]|[eo]n|i[nl]|er|a[ytrl])s$/i, + to: '$1' + }, { + reg: /(ow)s$/i, + to: '$1' + }, { + reg: /(op)s$/i, + to: '$1' + }, { + reg: /([eirs])ts$/i, + to: '$1t' + }, { + reg: /(ll)s$/i, + to: '$1' + }, { + reg: /(el)s$/i, + to: '$1' + }, { + reg: /(ip)es$/i, + to: '$1e' + }, { + reg: /ss$/i, + to: 'ss' + }, { + reg: /s$/i, + to: '' + }], + Gerund: [{ + reg: /pping$/i, + to: 'p' + }, { + reg: /lling$/i, + to: 'll' + }, { + reg: /tting$/i, + to: 't' + }, { + reg: /dding$/i, + to: 'd' + }, { + reg: /ssing$/i, + to: 'ss' + }, { + reg: /(..)gging$/i, + to: '$1g' + }, { + reg: /([^aeiou])ying$/i, + to: '$1y' + }, { + reg: /([^ae]i.)ing$/i, + to: '$1e' + }, { + reg: /(ea.)ing$/i, + to: '$1' + }, { + reg: /(u[rtcb]|[bdtpkg]l|n[cg]|a[gdkvtc]|[ua]s|[dr]g|yz|o[rlsp]|cre)ing$/i, + to: '$1e' + }, { + reg: /(ch|sh)ing$/i, + to: '$1' + }, { + reg: /(..)ing$/i, + to: '$1' + }], + PastTense: [{ + reg: /(ued)$/i, + to: 'ue' + }, { + reg: /a([^aeiouy])ed$/i, + to: 'a$1e' + }, { + reg: /([aeiou]zz)ed$/i, + to: '$1' + }, { + reg: /(e|i)lled$/i, + to: '$1ll' + }, { + reg: /(.)(sh|ch)ed$/i, + to: '$1$2' + }, { + reg: /(tl|gl)ed$/i, + to: '$1e' + }, { + reg: /(um?pt?)ed$/i, + to: '$1' + }, { + reg: /(ss)ed$/i, + to: '$1' + }, { + reg: /pped$/i, + to: 'p' + }, { + reg: /tted$/i, + to: 't' + }, { + reg: /(..)gged$/i, + to: '$1g' + }, { + reg: /(..)lked$/i, + to: '$1lk' + }, { + reg: /([^aeiouy][aeiou])ked$/i, + to: '$1ke' + }, { + reg: /(.[aeiou])led$/i, + to: '$1l' + }, { + reg: /(..)(h|ion|n[dt]|ai.|[cs]t|pp|all|ss|tt|int|ail|ld|en|oo.|er|k|pp|w|ou.|rt|ght|rm)ed$/i, + to: '$1$2' + }, { + reg: /(.ut)ed$/i, + to: '$1e' + }, { + reg: /(.pt)ed$/i, + to: '$1' + }, { + reg: /(us)ed$/i, + to: '$1e' + }, { + reg: /(..[^aeiouy])ed$/i, + to: '$1e' + }, { + reg: /(..)ied$/i, + to: '$1y' + }, { + reg: /(.o)ed$/i, + to: '$1o' + }, { + reg: /(..i)ed$/i, + to: '$1' + }, { + reg: /(.a[^aeiou])ed$/i, + to: '$1' + }, { + reg: /([rl])ew$/i, + to: '$1ow' + }, { + reg: /([pl])t$/i, + to: '$1t' + }] +}; +var _transform = rules; + +var guessVerb = { + Gerund: ['ing'], + Actor: ['erer'], + Infinitive: ['ate', 'ize', 'tion', 'rify', 'then', 'ress', 'ify', 'age', 'nce', 'ect', 'ise', 'ine', 'ish', 'ace', 'ash', 'ure', 'tch', 'end', 'ack', 'and', 'ute', 'ade', 'ock', 'ite', 'ase', 'ose', 'use', 'ive', 'int', 'nge', 'lay', 'est', 'ain', 'ant', 'ent', 'eed', 'er', 'le', 'own', 'unk', 'ung', 'en'], + PastTense: ['ed', 'lt', 'nt', 'pt', 'ew', 'ld'], + PresentTense: ['rks', 'cks', 'nks', 'ngs', 'mps', 'tes', 'zes', 'ers', 'les', 'acks', 'ends', 'ands', 'ocks', 'lays', 'eads', 'lls', 'els', 'ils', 'ows', 'nds', 'ays', 'ams', 'ars', 'ops', 'ffs', 'als', 'urs', 'lds', 'ews', 'ips', 'es', 'ts', 'ns'] +}; //flip it into a lookup object + +guessVerb = Object.keys(guessVerb).reduce(function (h, k) { + guessVerb[k].forEach(function (a) { + return h[a] = k; + }); + return h; +}, {}); +var _guess = guessVerb; + +/** it helps to know what we're conjugating from */ + +var guessTense = function guessTense(str) { + var three = str.substr(str.length - 3); + + if (_guess.hasOwnProperty(three) === true) { + return _guess[three]; + } + + var two = str.substr(str.length - 2); + + if (_guess.hasOwnProperty(two) === true) { + return _guess[two]; + } + + var one = str.substr(str.length - 1); + + if (one === 's') { + return 'PresentTense'; + } + + return null; +}; + +var toInfinitive = function toInfinitive(str, world, tense) { + if (!str) { + return ''; + } //1. look at known irregulars + + + if (world.words.hasOwnProperty(str) === true) { + var irregs = world.irregulars.verbs; + var keys = Object.keys(irregs); + + for (var i = 0; i < keys.length; i++) { + var forms = Object.keys(irregs[keys[i]]); + + for (var o = 0; o < forms.length; o++) { + if (str === irregs[keys[i]][forms[o]]) { + return keys[i]; + } + } + } + } // give'r! + + + tense = tense || guessTense(str); + + if (tense && _transform[tense]) { + for (var _i = 0; _i < _transform[tense].length; _i++) { + var rule = _transform[tense][_i]; + + if (rule.reg.test(str) === true) { + return str.replace(rule.reg, rule.to); + } + } + } + + return str; +}; + +var toInfinitive_1 = toInfinitive; + +var irregulars$2 = { + nouns: plurals, + verbs: conjugations_1 +}; //these behaviours are configurable & shared across some plugins + +var transforms$2 = { + conjugate: conjugate_1, + adjectives: adjectives, + toPlural: toPlural, + toSingular: toSingular_1, + toInfinitive: toInfinitive_1 +}; +var _isVerbose = false; +/** all configurable linguistic data */ + +var World = +/*#__PURE__*/ +function () { + function World() { + _classCallCheck(this, World); + + // quiet these properties from a console.log + Object.defineProperty(this, 'words', { + enumerable: false, + value: misc$1, + writable: true + }); + Object.defineProperty(this, 'hasCompound', { + enumerable: false, + value: {}, + writable: true + }); + Object.defineProperty(this, 'irregulars', { + enumerable: false, + value: irregulars$2, + writable: true + }); + Object.defineProperty(this, 'tags', { + enumerable: false, + value: Object.assign({}, tags), + writable: true + }); + Object.defineProperty(this, 'transforms', { + enumerable: false, + value: transforms$2, + writable: true + }); + Object.defineProperty(this, 'taggers', { + enumerable: false, + value: [], + writable: true + }); // add our compressed data to lexicon + + this.unpackWords(_data); // add our irregulars to lexicon + + this.addIrregulars(); // cache our abbreviations for our sentence-parser + + Object.defineProperty(this, 'cache', { + enumerable: false, + value: { + abbreviations: this.getByTag('Abbreviation') + } + }); + } + /** more logs for debugging */ + + + _createClass(World, [{ + key: "verbose", + value: function verbose(bool) { + _isVerbose = bool; + return this; + } + }, { + key: "isVerbose", + value: function isVerbose() { + return _isVerbose; + } + /** get all terms in our lexicon with this tag */ + + }, { + key: "getByTag", + value: function getByTag(tag) { + var lex = this.words; + var res = {}; + var words = Object.keys(lex); + + for (var i = 0; i < words.length; i++) { + if (typeof lex[words[i]] === 'string') { + if (lex[words[i]] === tag) { + res[words[i]] = true; + } + } else if (lex[words[i]].some(function (t) { + return t === tag; + })) { + res[words[i]] = true; + } + } + + return res; + } + /** augment our lingustic data with new data */ + + }, { + key: "unpackWords", + value: function unpackWords(lex) { + var tags = Object.keys(lex); + + for (var i = 0; i < tags.length; i++) { + var words = Object.keys(efrtUnpack_min(lex[tags[i]])); + + for (var w = 0; w < words.length; w++) { + addWords.addWord(words[w], tags[i], this.words); // do some fancier stuff + + addWords.addMore(words[w], tags[i], this); + } + } + } + /** put new words into our lexicon, properly */ + + }, { + key: "addWords", + value: function addWords$1(obj) { + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + var word = keys[i].toLowerCase(); + addWords.addWord(word, obj[keys[i]], this.words); // do some fancier stuff + + addWords.addMore(word, obj[keys[i]], this); + } + } + }, { + key: "addIrregulars", + value: function addIrregulars() { + addIrregulars_1(this); + + return this; + } + /** extend the compromise tagset */ + + }, { + key: "addTags", + value: function addTags(tags) { + tags = Object.assign({}, tags); + this.tags = Object.assign(this.tags, tags); // calculate graph implications for the new tags + + this.tags = inference(this.tags); + return this; + } + /** call methods after tagger runs */ + + }, { + key: "postProcess", + value: function postProcess(fn) { + this.taggers.push(fn); + return this; + } + /** helper method for logging + debugging */ + + }, { + key: "stats", + value: function stats() { + return { + words: Object.keys(this.words).length, + plurals: Object.keys(this.irregular.plurals).length, + conjugations: Object.keys(this.irregular.conjugations).length, + compounds: Object.keys(this.hasCompound).length, + postProcessors: this.taggers.length + }; + } + }]); + + return World; +}(); // ¯\_(:/)_/¯ + + +var clone$1 = function clone(obj) { + return JSON.parse(JSON.stringify(obj)); +}; +/** produce a deep-copy of all lingustic data */ + + +World.prototype.clone = function () { + var w2 = new World(); // these are simple to copy: + + w2.words = Object.assign({}, this.words); + w2.hasCompound = Object.assign({}, this.hasCompound); //these ones are nested: + + w2.irregulars = clone$1(this.irregulars); + w2.tags = clone$1(this.tags); // these are functions + + w2.transforms = this.transforms; + w2.taggers = this.taggers; + return w2; +}; + +var World_1 = World; + +var _01Utils$1 = createCommonjsModule(function (module, exports) { + // const cache = require('./_setCache') + + /** return the root, first document */ + exports.all = function () { + return this.parents()[0] || this; + }; + /** return the previous result */ + + + exports.parent = function () { + if (this.from) { + return this.from; + } + + return this; + }; + /** return a list of all previous results */ + + + exports.parents = function (n) { + var arr = []; + + var addParent = function addParent(doc) { + if (doc.from) { + arr.push(doc.from); + addParent(doc.from); + } + }; + + addParent(this); + arr = arr.reverse(); + + if (typeof n === 'number') { + return arr[n]; + } + + return arr; + }; + /** deep-copy the document, so that no references remain */ + + + exports.clone = function (doShallow) { + var list = this.list.map(function (ts) { + return ts.clone(doShallow); + }); + var tmp = this.buildFrom(list); + return tmp; + }; + /** how many seperate terms does the document have? */ + + + exports.wordCount = function () { + return this.list.reduce(function (count, p) { + count += p.wordCount(); + return count; + }, 0); + }; + + exports.wordcount = exports.wordCount; + /** turn on logging for decision-debugging */ + // exports.verbose = function(bool) { + // if (bool === undefined) { + // bool = true + // } + // this.world.verbose = bool + // } + + /** freeze the current state of the document, for speed-purposes*/ + + exports.cache = function (options) { + var _this = this; + + options = options || {}; + this.list.forEach(function (p) { + var words = {}; + p.cache = p.cache || {}; + p.cache.terms = p.cache.terms || p.terms(); // cache all the terms + + p.cache.terms.forEach(function (t) { + words[t.clean] = true; + words[t.reduced] = true; + words[t.text.toLowerCase()] = true; + + if (t.implicit) { + words[t.implicit] = true; + } + + if (t.root) { + words[t.root] = true; + } + + if (t.alias !== undefined) { + words = Object.assign(words, t.alias); + } + + if (options.root) { + t.setRoot(_this.world); + words[t.root] = true; + } + }); + delete words['']; + p.cache.words = words; + }); + return this; + }; + /** un-freezes the current state of the document, so it may be transformed */ + + + exports.uncache = function () { + this.list.forEach(function (p) { + p.cache = {}; + }); // do parents too? + + this.parents().forEach(function (doc) { + doc.list.forEach(function (p) { + p.cache = {}; + }); + }); + return this; + }; +}); +var _01Utils_1 = _01Utils$1.all; +var _01Utils_2 = _01Utils$1.parent; +var _01Utils_3 = _01Utils$1.parents; +var _01Utils_4 = _01Utils$1.clone; +var _01Utils_5 = _01Utils$1.wordCount; +var _01Utils_6 = _01Utils$1.wordcount; +var _01Utils_7 = _01Utils$1.cache; +var _01Utils_8 = _01Utils$1.uncache; + +var _02Accessors = createCommonjsModule(function (module, exports) { + /** use only the first result(s) */ + exports.first = function (n) { + if (n === undefined) { + return this.get(0); + } + + return this.slice(0, n); + }; + /** use only the last result(s) */ + + + exports.last = function (n) { + if (n === undefined) { + return this.get(this.list.length - 1); + } + + var end = this.list.length; + return this.slice(end - n, end); + }; + /** grab a given subset of the results*/ + + + exports.slice = function (start, end) { + var list = this.list.slice(start, end); + return this.buildFrom(list); + }; + /* grab nth result */ + + + exports.eq = function (n) { + var p = this.list[n]; + + if (p === undefined) { + return this.buildFrom([]); + } + + return this.buildFrom([p]); + }; + + exports.get = exports.eq; + /** grab term[0] for every match */ + + exports.firstTerm = function () { + return this.match('^.'); + }; + /** grab the last term for every match */ + + + exports.lastTerm = function () { + return this.match('.$'); + }; + /** return a flat array of term objects */ + + + exports.termList = function (num) { + var arr = []; //'reduce' but faster + + for (var i = 0; i < this.list.length; i++) { + var terms = this.list[i].terms(); + + for (var o = 0; o < terms.length; o++) { + arr.push(terms[o]); //support .termList(4) + + if (num !== undefined && arr[num] !== undefined) { + return arr[num]; + } + } + } + + return arr; + }; +}); +var _02Accessors_1 = _02Accessors.first; +var _02Accessors_2 = _02Accessors.last; +var _02Accessors_3 = _02Accessors.slice; +var _02Accessors_4 = _02Accessors.eq; +var _02Accessors_5 = _02Accessors.get; +var _02Accessors_6 = _02Accessors.firstTerm; +var _02Accessors_7 = _02Accessors.lastTerm; +var _02Accessors_8 = _02Accessors.termList; + +var _03Match = createCommonjsModule(function (module, exports) { + /** return a new Doc, with this one as a parent */ + exports.match = function (reg) { + //parse-up the input expression + var regs = syntax_1(reg); + + if (regs.length === 0) { + return this.buildFrom([]); + } //try expression on each phrase + + + var matches = this.list.reduce(function (arr, p) { + return arr.concat(p.match(regs)); + }, []); + return this.buildFrom(matches); + }; + /** return all results except for this */ + + + exports.not = function (reg) { + //parse-up the input expression + var regs = syntax_1(reg); //if it's empty, return them all! + + if (regs.length === 0) { + return this; + } //try expression on each phrase + + + var matches = this.list.reduce(function (arr, p) { + return arr.concat(p.not(regs)); + }, []); + return this.buildFrom(matches); + }; + /** return only the first match */ + + + exports.matchOne = function (reg) { + var regs = syntax_1(reg); + + for (var i = 0; i < this.list.length; i++) { + var match = this.list[i].match(regs); + return this.buildFrom(match); + } + + return this.buildFrom([]); + }; + /** return each current phrase, only if it contains this match */ + + + exports["if"] = function (reg) { + var regs = syntax_1(reg); + var found = this.list.filter(function (p) { + return p.match(regs).length > 0; + }); + return this.buildFrom(found); + }; + /** Filter-out any current phrases that have this match*/ + + + exports.ifNo = function (reg) { + var regs = syntax_1(reg); + var found = this.list.filter(function (p) { + return p.match(regs).length === 0; + }); + return this.buildFrom(found); + }; + /**Return a boolean if this match exists */ + + + exports.has = function (reg) { + var regs = syntax_1(reg); + return this.list.some(function (p) { + return p.has(regs) === true; + }); + }; + /** match any terms after our matches, within the sentence */ + + + exports.lookAhead = function (reg) { + // find everything afterwards, by default + if (!reg) { + reg = '.*'; + } + + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + matches = matches.concat(p.lookAhead(regs)); + }); + matches = matches.filter(function (p) { + return p; + }); + return this.buildFrom(matches); + }; + + exports.lookAfter = exports.lookAhead; + /** match any terms before our matches, within the sentence */ + + exports.lookBehind = function (reg) { + // find everything afterwards, by default + if (!reg) { + reg = '.*'; + } + + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + matches = matches.concat(p.lookBehind(regs)); + }); + matches = matches.filter(function (p) { + return p; + }); + return this.buildFrom(matches); + }; + + exports.lookBefore = exports.lookBehind; + /** return all terms before a match, in each phrase */ + + exports.before = function (reg) { + var regs = syntax_1(reg); //only the phrases we care about + + var phrases = this["if"](regs).list; + var befores = phrases.map(function (p) { + var ids = p.terms().map(function (t) { + return t.id; + }); //run the search again + + var m = p.match(regs)[0]; + var index = ids.indexOf(m.start); //nothing is before a first-term match + + if (index === 0 || index === -1) { + return null; + } + + return p.buildFrom(p.start, index); + }); + befores = befores.filter(function (p) { + return p !== null; + }); + return this.buildFrom(befores); + }; + /** return all terms after a match, in each phrase */ + + + exports.after = function (reg) { + var regs = syntax_1(reg); //only the phrases we care about + + var phrases = this["if"](regs).list; + var befores = phrases.map(function (p) { + var terms = p.terms(); + var ids = terms.map(function (t) { + return t.id; + }); //run the search again + + var m = p.match(regs)[0]; + var index = ids.indexOf(m.start); //skip if nothing is after it + + if (index === -1 || !terms[index + m.length]) { + return null; + } //create the new phrase, after our match. + + + var id = terms[index + m.length].id; + var len = p.length - index - m.length; + return p.buildFrom(id, len); + }); + befores = befores.filter(function (p) { + return p !== null; + }); + return this.buildFrom(befores); + }; +}); +var _03Match_1 = _03Match.match; +var _03Match_2 = _03Match.not; +var _03Match_3 = _03Match.matchOne; +var _03Match_4 = _03Match.ifNo; +var _03Match_5 = _03Match.has; +var _03Match_6 = _03Match.lookAhead; +var _03Match_7 = _03Match.lookAfter; +var _03Match_8 = _03Match.lookBehind; +var _03Match_9 = _03Match.lookBefore; +var _03Match_10 = _03Match.before; +var _03Match_11 = _03Match.after; + +/** apply a tag, or tags to all terms */ +var tagTerms = function tagTerms(tag, doc, safe, reason) { + var tagList = []; + + if (typeof tag === 'string') { + tagList = tag.split(' '); + } // console.log(doc.parents().length) + //do indepenent tags for each term: + + + doc.list.forEach(function (p) { + var terms = p.terms(); // tagSafe - apply only to fitting terms + + if (safe === true) { + terms = terms.filter(function (t) { + return t.canBe(tag, doc.world); + }); + } + + terms.forEach(function (t, i) { + //fancy version: + if (tagList.length > 1) { + if (tagList[i] && tagList[i] !== '.') { + t.tag(tagList[i], reason, doc.world); + } + } else { + //non-fancy version (same tag for all terms) + t.tag(tag, reason, doc.world); + } + }); + }); + return; +}; + +var _setTag = tagTerms; + +/** Give all terms the given tag */ + +var tag$1 = function tag(tags, why) { + if (!tags) { + return this; + } + + _setTag(tags, this, false, why); + return this; +}; +/** Only apply tag to terms if it is consistent with current tags */ + + +var tagSafe$1 = function tagSafe(tags, why) { + if (!tags) { + return this; + } + + _setTag(tags, this, true, why); + return this; +}; +/** Remove this term from the given terms */ + + +var unTag$1 = function unTag(tags, why) { + var _this = this; + + this.list.forEach(function (p) { + p.terms().forEach(function (t) { + return t.unTag(tags, why, _this.world); + }); + }); + return this; +}; +/** return only the terms that can be this tag*/ + + +var canBe$2 = function canBe(tag) { + if (!tag) { + return this; + } + + var world = this.world; + var matches = this.list.reduce(function (arr, p) { + return arr.concat(p.canBe(tag, world)); + }, []); + return this.buildFrom(matches); +}; + +var _04Tag = { + tag: tag$1, + tagSafe: tagSafe$1, + unTag: unTag$1, + canBe: canBe$2 +}; + +/* run each phrase through a function, and create a new document */ +var map = function map(fn) { + var _this = this; + + if (!fn) { + return this; + } + + var list = this.list.map(function (p, i) { + var doc = _this.buildFrom([p]); + + doc.from = null; //it's not a child/parent + + var res = fn(doc, i); + + if (res.list && res.list[0]) { + return res.list[0]; + } + + return res; + }); + + if (list.length === 0) { + return this.buildFrom(list); + } // if it is not a list of Phrase objects, then don't try to make a Doc object + + + if (_typeof(list[0]) !== 'object' || list[0].isA !== 'Phrase') { + return list; + } + + return this.buildFrom(list); +}; +/** run a function on each phrase */ + + +var forEach = function forEach(fn, detachParent) { + var _this2 = this; + + if (!fn) { + return this; + } + + this.list.forEach(function (p, i) { + var sub = _this2.buildFrom([p]); // if we're doing fancy insertions, we may want to skip updating the parent each time. + + + if (detachParent === true) { + sub.from = null; // + } // let len + // console.log(sub.from.list[0].text()) + + + fn(sub, i); // console.log(sub.from.list[0].text()) + }); + return this; +}; +/** return only the phrases that return true */ + + +var filter = function filter(fn) { + var _this3 = this; + + if (!fn) { + return this; + } + + var list = this.list.filter(function (p, i) { + var doc = _this3.buildFrom([p]); + + doc.from = null; //it's not a child/parent + + return fn(doc, i); + }); + return this.buildFrom(list); +}; +/** return a document with only the first phrase that matches */ + + +var find = function find(fn) { + var _this4 = this; + + if (!fn) { + return this; + } + + var phrase = this.list.find(function (p, i) { + var doc = _this4.buildFrom([p]); + + doc.from = null; //it's not a child/parent + + return fn(doc, i); + }); + + if (phrase) { + return this.buildFrom([phrase]); + } + + return undefined; +}; +/** return true or false if there is one matching phrase */ + + +var some = function some(fn) { + var _this5 = this; + + if (!fn) { + return this; + } + + return this.list.some(function (p, i) { + var doc = _this5.buildFrom([p]); + + doc.from = null; //it's not a child/parent + + return fn(doc, i); + }); +}; +/** sample a subset of the results */ + + +var random = function random(n) { + if (!this.found) { + return this; + } + + var r = Math.floor(Math.random() * this.list.length); + + if (n === undefined) { + var list = [this.list[r]]; + return this.buildFrom(list); + } //prevent it from going over the end + + + if (r + n > this.length) { + r = this.length - n; + r = r < 0 ? 0 : r; + } + + return this.slice(r, r + n); +}; +/** combine each phrase into a new data-structure */ +// exports.reduce = function(fn, h) { +// let list = this.list.reduce((_h, ts) => { +// let doc = this.buildFrom([ts]) +// doc.from = null //it's not a child/parent +// return fn(_h, doc) +// }, h) +// return this.buildFrom(list) +// } + + +var _05Loops = { + map: map, + forEach: forEach, + filter: filter, + find: find, + some: some, + random: random +}; + +var doesMatch$1 = function doesMatch(term, str) { + if (str === '') { + return false; + } + + return term.reduced === str || term.implicit === str || term.root === str || term.text.toLowerCase() === str; +}; // is this lookup found in these terms? + + +var findStart = function findStart(arr, terms) { + var _loop = function _loop(i) { + if (doesMatch$1(terms[i], arr[0])) { + if (arr.every(function (a, n) { + return doesMatch$1(terms[i + n], a) === true; + })) { + return { + v: terms[i].id + }; + } + } + }; + + //find the start + for (var i = 0; i < terms.length; i++) { + var _ret = _loop(i); + + if (_typeof(_ret) === "object") return _ret.v; + } + + return false; +}; +/** lookup an array of words or phrases */ + + +var lookup = function lookup(arr) { + var _this = this; + + if (typeof arr === 'string') { + arr = [arr]; + } + + var lookups = arr.map(function (str) { + str = str.toLowerCase(); + var words = _02Words(str); + words = words.map(function (s) { + return s.trim(); + }); + return words; + }); + this.cache(); + var found = []; // try each lookup + + lookups.forEach(function (a) { + //try each phrase + _this.list.forEach(function (p) { + // cache-miss, skip. + if (p.cache.words[a[0]] !== true) { + return; + } //we found a potential match + + + var terms = p.terms(); + var id = findStart(a, terms); + + if (id !== false) { + // create the actual phrase + var phrase = p.buildFrom(id, a.length); + found.push(phrase); + return; + } + }); + }); + return this.buildFrom(found); +}; + +var _06Lookup = { + lookup: lookup +}; + +var titleCase$2 = function titleCase(str) { + return str.charAt(0).toUpperCase() + str.substr(1); +}; +/** substitute-in new content */ + + +var replaceWith = function replaceWith(replace, keepTags, keepCase) { + var _this = this; + + if (!replace) { + return this["delete"](); + } // clear the cache + + + this.uncache(); // return this + + this.list.forEach(function (p) { + var input = replace; // accept a function for replace + + if (typeof replace === 'function') { + input = replace(p); + } + + var newPhrases; // accept a Doc object to replace + + if (input && _typeof(input) === 'object' && input.isA === 'Doc') { + newPhrases = input.list; + + _this.pool().merge(input.pool()); + } else if (typeof input === 'string') { + //input is a string + if (keepCase === true && p.terms(0).isTitleCase()) { + input = titleCase$2(input); + } + + newPhrases = _01Tokenizer.fromText(input, _this.world, _this.pool()); //tag the new phrases + + var tmpDoc = _this.buildFrom(newPhrases); + + tmpDoc.tagger(); + } else { + return; //don't even bother + } // try to keep its old tags, if appropriate + + + if (keepTags === true) { + var oldTags = p.json({ + terms: { + tags: true + } + }).terms; + newPhrases[0].terms().forEach(function (t, i) { + if (oldTags[i]) { + t.tagSafe(oldTags[i].tags, 'keptTag', _this.world); + } + }); + } + + p.replace(newPhrases[0], _this); //Oneday: support multi-sentence replacements + }); + return this; +}; +/** search and replace match with new content */ + + +var replace$1 = function replace(match, _replace, keepTags, keepCase) { + // if there's no 2nd param, use replaceWith + if (_replace === undefined) { + return this.replaceWith(match); + } + + this.match(match).replaceWith(_replace, keepTags, keepCase); + return this; +}; + +var _01Replace = { + replaceWith: replaceWith, + replace: replace$1 +}; + +var _02Insert = createCommonjsModule(function (module, exports) { + /** add these new terms to the end*/ + exports.append = function (str) { + var _this = this; + + if (!str) { + return this; + } // clear the cache + + + this.uncache(); //add it to end of every phrase + + this.list.forEach(function (p) { + //build it + var phrase = _01Tokenizer.fromText(str, _this.world, _this.pool())[0]; //assume it's one sentence, for now + //tag it + + var tmpDoc = _this.buildFrom([phrase]); + + tmpDoc.tagger(); // push it onto the end + + p.append(phrase, _this); + }); + return this; + }; + + exports.insertAfter = exports.append; + exports.insertAt = exports.append; + /** add these new terms to the front*/ + + exports.prepend = function (str) { + var _this2 = this; + + if (!str) { + return this; + } // clear the cache + + + this.uncache(); //add it to start of every phrase + + this.list.forEach(function (p) { + //build it + var phrase = _01Tokenizer.fromText(str, _this2.world, _this2.pool())[0]; //assume it's one sentence, for now + //tag it + + var tmpDoc = _this2.buildFrom([phrase]); + + tmpDoc.tagger(); // add it to the start + + p.prepend(phrase, _this2); + }); + return this; + }; + + exports.insertBefore = exports.prepend; + /** add these new things to the end*/ + + exports.concat = function () { + // clear the cache + this.uncache(); + var list = this.list.slice(0); //repeat for any number of params + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; //support a fresh string + + if (typeof arg === 'string') { + var arr = _01Tokenizer.fromText(arg, this.world); //TODO: phrase.tagger()? + + list = list.concat(arr); + } else if (arg.isA === 'Doc') { + list = list.concat(arg.list); + } else if (arg.isA === 'Phrase') { + list.push(arg); + } + } + + return this.buildFrom(list); + }; + /** fully remove these terms from the document */ + + + exports["delete"] = function (match) { + var _this3 = this; + + // clear the cache + this.uncache(); + var toRemove = this; + + if (match) { + toRemove = this.match(match); + } + + toRemove.list.forEach(function (phrase) { + return phrase["delete"](_this3); + }); + return this; + }; // aliases + + + exports.remove = exports["delete"]; +}); +var _02Insert_1 = _02Insert.append; +var _02Insert_2 = _02Insert.insertAfter; +var _02Insert_3 = _02Insert.insertAt; +var _02Insert_4 = _02Insert.prepend; +var _02Insert_5 = _02Insert.insertBefore; +var _02Insert_6 = _02Insert.concat; +var _02Insert_7 = _02Insert.remove; + +/** return the document as text */ +var text$1 = function text(options) { + var _this = this; + + options = options || {}; //are we showing every phrase? + + var showFull = false; + + if (this.parents().length === 0) { + showFull = true; + } // cache roots, if necessary + + + if (options === 'root' || _typeof(options) === 'object' && options.root) { + this.list.forEach(function (p) { + p.terms().forEach(function (t) { + if (t.root === null) { + t.setRoot(_this.world); + } + }); + }); + } + + return this.list.reduce(function (str, p, i) { + var trimPre = !showFull && i === 0; + var trimPost = !showFull && i === _this.list.length - 1; + return str + p.text(options, trimPre, trimPost); + }, ''); +}; + +var _01Text = { + text: text$1 +}; + +var _02Json = createCommonjsModule(function (module, exports) { + var jsonDefaults = { + text: true, + terms: true, + trim: true + }; // get all character startings in doc + + var termOffsets = function termOffsets(doc) { + var elapsed = 0; + var index = 0; + var offsets = {}; + doc.termList().forEach(function (term) { + offsets[term.id] = { + index: index, + start: elapsed + term.pre.length, + length: term.text.length + }; + elapsed += term.pre.length + term.text.length + term.post.length; + index += 1; + }); + return offsets; + }; + /** pull out desired metadata from the document */ + + + exports.json = function () { + var _this = this; + + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + //support json(3) format + if (typeof options === 'number' && this.list[options]) { + return this.list[options].json(jsonDefaults); + } + + options = Object.assign({}, jsonDefaults, options); // cache roots, if necessary + + if (options === 'root' || _typeof(options) === 'object' && options.root) { + this.list.forEach(function (p) { + p.terms().forEach(function (t) { + if (t.root === null) { + t.setRoot(_this.world); + } + }); + }); + } + + if (options.unique) { + options.reduced = true; + } + + if (options.offset) { + options.terms = options.terms === true ? {} : options.terms; + options.terms.offset = true; + } + + if (options.index || options.terms.index) { + options.terms = options.terms === true ? {} : options.terms; + options.terms.id = true; + } + + var result = this.list.map(function (p) { + return p.json(options, _this.world); + }); // add offset and index data for each term + + if (options.terms.offset || options.offset || options.terms.index || options.index) { + // calculate them, (from beginning of doc) + var offsets = termOffsets(this.all()); // add index values + + if (options.terms.index || options.index) { + result.forEach(function (o) { + o.terms.forEach(function (t) { + t.index = offsets[t.id].index; + }); + o.index = o.terms[0].index; + }); + } // add offset values + + + if (options.terms.offset || options.offset) { + result.forEach(function (o) { + o.terms.forEach(function (t) { + t.offset = offsets[t.id] || {}; + }); + var len = o.terms.reduce(function (n, t) { + n += t.offset.length || 0; + return n; + }, 0); + o.offset = o.terms[0].offset; + o.offset.length = len; + }); + } + } // add frequency #s + + + if (options.frequency || options.freq || options.count) { + var obj = {}; + this.list.forEach(function (p) { + var str = p.text('reduced'); + obj[str] = obj[str] || 0; + obj[str] += 1; + }); + this.list.forEach(function (p, i) { + result[i].count = obj[p.text('reduced')]; + }); + } // remove duplicates + + + if (options.unique) { + var already = {}; + result = result.filter(function (o) { + if (already[o.reduced] === true) { + return false; + } + + already[o.reduced] = true; + return true; + }); + } + + return result; + }; //aliases + + + exports.data = exports.json; +}); +var _02Json_1 = _02Json.json; +var _02Json_2 = _02Json.data; + +var entity$1 = ['Person', 'Place', 'Organization']; +var nouns$1 = { + Noun: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + // - singular + Singular: { + isA: 'Noun', + notA: 'Plural' + }, + //a specific thing that's capitalized + ProperNoun: { + isA: 'Noun' + }, + // -- people + Person: { + isA: ['ProperNoun', 'Singular'], + notA: ['Place', 'Organization'] + }, + FirstName: { + isA: 'Person' + }, + MaleName: { + isA: 'FirstName', + notA: ['FemaleName', 'LastName'] + }, + FemaleName: { + isA: 'FirstName', + notA: ['MaleName', 'LastName'] + }, + LastName: { + isA: 'Person', + notA: ['FirstName'] + }, + Honorific: { + isA: 'Noun', + notA: ['FirstName', 'LastName'] + }, + // -- places + Place: { + isA: 'Singular', + notA: ['Person', 'Organization'] + }, + Country: { + isA: ['Place', 'ProperNoun'], + notA: ['City'] + }, + City: { + isA: ['Place', 'ProperNoun'], + notA: ['Country'] + }, + Region: { + isA: ['Place', 'ProperNoun'] + }, + Address: { + isA: 'Place' + }, + //---Orgs--- + Organization: { + isA: ['Singular', 'ProperNoun'], + notA: ['Person', 'Place'] + }, + SportsTeam: { + isA: 'Organization' + }, + School: { + isA: 'Organization' + }, + Company: { + isA: 'Organization' + }, + // - plural + Plural: { + isA: 'Noun', + notA: ['Singular'] + }, + //(not plural or singular) + Uncountable: { + isA: 'Noun' + }, + Pronoun: { + isA: 'Noun', + notA: entity$1 + }, + //a word for someone doing something -'plumber' + Actor: { + isA: 'Noun', + notA: entity$1 + }, + //a gerund-as-noun - 'swimming' + Activity: { + isA: 'Noun', + notA: ['Person', 'Place'] + }, + //'kilograms' + Unit: { + isA: 'Noun', + notA: entity$1 + }, + //'Canadians' + Demonym: { + isA: ['Noun', 'ProperNoun'], + notA: entity$1 + }, + //`john's` + Possessive: { + isA: 'Noun' // notA: 'Pronoun', + + } +}; + +var verbs$1 = { + Verb: { + notA: ['Noun', 'Adjective', 'Adverb', 'Value'] + }, + // walks + PresentTense: { + isA: 'Verb', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // neutral form - 'walk' + Infinitive: { + isA: 'PresentTense', + notA: ['PastTense', 'Gerund'] + }, + // walking + Gerund: { + isA: 'PresentTense', + notA: ['PastTense', 'Copula', 'FutureTense'] + }, + // walked + PastTense: { + isA: 'Verb', + notA: ['FutureTense'] + }, + // will walk + FutureTense: { + isA: 'Verb' + }, + // is + Copula: { + isA: 'Verb' + }, + // would have + Modal: { + isA: 'Verb', + notA: ['Infinitive'] + }, + // had walked + PerfectTense: { + isA: 'Verb', + notA: 'Gerund' + }, + Pluperfect: { + isA: 'Verb' + }, + // shown + Participle: { + isA: 'Verb' + }, + // show up + PhrasalVerb: { + isA: 'Verb' + }, + //'up' part + Particle: { + isA: 'PhrasalVerb' + } +}; + +var values$1 = { + Value: { + notA: ['Verb', 'Adjective', 'Adverb'] + }, + Ordinal: { + isA: 'Value', + notA: ['Cardinal'] + }, + Cardinal: { + isA: 'Value', + notA: ['Ordinal'] + }, + RomanNumeral: { + isA: 'Cardinal', + //can be a person, too + notA: ['Ordinal', 'TextValue'] + }, + TextValue: { + isA: 'Value', + notA: ['NumericValue'] + }, + NumericValue: { + isA: 'Value', + notA: ['TextValue'] + }, + Money: { + isA: 'Cardinal' + }, + Percent: { + isA: 'Value' + } +}; + +var anything$1 = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Value']; +var misc$2 = { + //--Adjectives-- + Adjective: { + notA: ['Noun', 'Verb', 'Adverb', 'Value'] + }, + // adjectives that can conjugate + Comparable: { + isA: ['Adjective'] + }, + // better + Comparative: { + isA: ['Adjective'] + }, + // best + Superlative: { + isA: ['Adjective'], + notA: ['Comparative'] + }, + NumberRange: { + isA: ['Contraction'] + }, + Adverb: { + notA: ['Noun', 'Verb', 'Adjective', 'Value'] + }, + // Dates: + //not a noun, but usually is + Date: { + notA: ['Verb', 'Conjunction', 'Adverb', 'Preposition', 'Adjective'] + }, + Month: { + isA: ['Date', 'Singular'], + notA: ['Year', 'WeekDay', 'Time'] + }, + WeekDay: { + isA: ['Date', 'Noun'] + }, + //glue + Determiner: { + notA: anything$1 + }, + Conjunction: { + notA: anything$1 + }, + Preposition: { + notA: anything$1 + }, + // what, who, why + QuestionWord: { + notA: ['Determiner'] + }, + // peso, euro + Currency: {}, + // ughh + Expression: { + notA: ['Noun', 'Adjective', 'Verb', 'Adverb'] + }, + // dr. + Abbreviation: {}, + // internet tags + Url: { + notA: ['HashTag', 'PhoneNumber', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + PhoneNumber: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'] + }, + HashTag: {}, + AtMention: { + isA: ['Noun'], + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'Email'] + }, + Emoji: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Emoticon: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + Email: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'] + }, + //non-exclusive + Auxiliary: { + notA: ['Noun', 'Adjective', 'Value'] + }, + Acronym: { + notA: ['Plural', 'RomanNumeral'] + }, + Negative: { + notA: ['Noun', 'Adjective', 'Value'] + }, + // if, unless, were + Condition: { + notA: ['Verb', 'Adjective', 'Noun', 'Value'] + } +}; + +// i just made these up +var colorMap$1 = { + Noun: 'blue', + Verb: 'green', + Negative: 'green', + Date: 'red', + Value: 'red', + Adjective: 'magenta', + Preposition: 'cyan', + Conjunction: 'cyan', + Determiner: 'cyan', + Adverb: 'cyan' +}; +/** add a debug color to some tags */ + +var addColors$1 = function addColors(tags) { + Object.keys(tags).forEach(function (k) { + if (colorMap$1[k]) { + tags[k].color = colorMap$1[k]; + return; + } + + tags[k].isA.some(function (t) { + if (colorMap$1[t]) { + tags[k].color = colorMap$1[t]; + return true; + } + + return false; + }); + }); + return tags; +}; + +var _color$1 = addColors$1; + +var unique$4 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); +}; //add 'downward' tags (that immediately depend on this one) + + +var inferIsA$1 = function inferIsA(tags) { + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; + var len = tag.isA.length; + + for (var i = 0; i < len; i++) { + var down = tag.isA[i]; + + if (tags[down]) { + tag.isA = tag.isA.concat(tags[down].isA); + } + } // clean it up + + + tag.isA = unique$4(tag.isA); + }); + return tags; +}; + +var _isA$1 = inferIsA$1; + +var unique$5 = function unique(arr) { + return arr.filter(function (v, i, a) { + return a.indexOf(v) === i; + }); +}; // crawl the tag-graph and infer any conflicts +// faster than doing this at tag-time + + +var inferNotA$1 = function inferNotA(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.notA = tag.notA || []; + tag.isA.forEach(function (down) { + if (tags[down] && tags[down].notA) { + // borrow its conflicts + var notA = typeof tags[down].notA === 'string' ? [tags[down].isA] : tags[down].notA || []; + tag.notA = tag.notA.concat(notA); + } + }); // any tag that lists us as a conflict, we conflict it back. + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + + if (tags[key].notA.indexOf(k) !== -1) { + tag.notA.push(key); + } + } // clean it up + + + tag.notA = unique$5(tag.notA); + }); + return tags; +}; + +var _notA$1 = inferNotA$1; + +// a lineage is all 'incoming' tags that have this as 'isA' +var inferLineage$1 = function inferLineage(tags) { + var keys = Object.keys(tags); + keys.forEach(function (k) { + var tag = tags[k]; + tag.lineage = []; // find all tags with it in their 'isA' set + + for (var i = 0; i < keys.length; i++) { + if (tags[keys[i]].isA.indexOf(k) !== -1) { + tag.lineage.push(keys[i]); + } + } + }); + return tags; +}; + +var _lineage$1 = inferLineage$1; + +var validate$1 = function validate(tags) { + // cleanup format + Object.keys(tags).forEach(function (k) { + var tag = tags[k]; // ensure isA is an array + + tag.isA = tag.isA || []; + + if (typeof tag.isA === 'string') { + tag.isA = [tag.isA]; + } // ensure notA is an array + + + tag.notA = tag.notA || []; + + if (typeof tag.notA === 'string') { + tag.notA = [tag.notA]; + } + }); + return tags; +}; // build-out the tag-graph structure + + +var inferTags$1 = function inferTags(tags) { + // validate data + tags = validate$1(tags); // build its 'down tags' + + tags = _isA$1(tags); // infer the conflicts + + tags = _notA$1(tags); // debug tag color + + tags = _color$1(tags); // find incoming links + + tags = _lineage$1(tags); + return tags; +}; + +var inference$1 = inferTags$1; + +var addIn$1 = function addIn(obj, tags) { + Object.keys(obj).forEach(function (k) { + tags[k] = obj[k]; + }); +}; + +var build$1 = function build() { + var tags = {}; + addIn$1(nouns$1, tags); + addIn$1(verbs$1, tags); + addIn$1(values$1, tags); + addIn$1(misc$2, tags); // do the graph-stuff + + tags = inference$1(tags); + return tags; +}; + +var tags$1 = build$1(); + +var _debug = createCommonjsModule(function (module) { + // https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color + var reset = '\x1b[0m'; + + var padEnd = function padEnd(str, width) { + str = str.toString(); + + while (str.length < width) { + str += ' '; + } + + return str; + }; //cheaper than requiring chalk + + + var cli = { + green: function green(str) { + return '\x1b[32m' + str + reset; + }, + red: function red(str) { + return '\x1b[31m' + str + reset; + }, + blue: function blue(str) { + return '\x1b[34m' + str + reset; + }, + magenta: function magenta(str) { + return '\x1b[35m' + str + reset; + }, + cyan: function cyan(str) { + return '\x1b[36m' + str + reset; + }, + yellow: function yellow(str) { + return '\x1b[33m' + str + reset; + }, + black: function black(str) { + return '\x1b[30m' + str + reset; + } + }; + + var tagString = function tagString(tags) { + tags = tags.map(function (tag) { + if (!tags$1.hasOwnProperty(tag)) { + return tag; + } + + var c = tags$1[tag].color || 'blue'; + return cli[c](tag); + }); + return tags.join(', '); + }; //output some helpful stuff to the console + + + var debug = function debug(doc) { + console.log(cli.blue('=====')); + doc.list.forEach(function (p) { + console.log(cli.blue(' -----')); + p.terms().forEach(function (t) { + var tags = Object.keys(t.tags); + var text = t.text || '-'; + + if (t.implicit) { + text = '[' + t.implicit + ']'; + } + + { + text = cli.yellow(text); + } + + var word = "'" + text + "'"; + word = padEnd(word, 18); + var str = cli.blue(' | ') + word + ' - ' + tagString(tags); + console.log(str); + }); + }); + console.log(''); + return doc; + }; + + module.exports = debug; +}); + +var topk = function topk(doc) { + var list = doc.json({ + text: false, + terms: false, + reduced: true + }); // combine them + + var obj = {}; + list.forEach(function (o) { + if (!obj[o.reduced]) { + o.count = 0; + obj[o.reduced] = o; + } + + obj[o.reduced].count += 1; + }); + var arr = Object.keys(obj).map(function (k) { + return obj[k]; + }); // sort them + + arr.sort(function (a, b) { + if (a.count > b.count) { + return -1; + } else if (a.count < b.count) { + return 1; + } + + return 0; + }); + return arr; +}; + +var _topk = topk; + +/** pretty-print the current document and its tags */ + +var debug_1 = function debug_1() { + _debug(this); + return this; +}; +/** some named output formats */ + + +var out = function out(method) { + if (method === 'text') { + return this.text(); + } + + if (method === 'normal') { + return this.text('normal'); + } + + if (method === 'json') { + return this.json(); + } + + if (method === 'offset' || method === 'offsets') { + return this.json({ + offset: true + }); + } + + if (method === 'array') { + return this.json({ + terms: false + }).map(function (obj) { + return obj.text; + }); + } + + if (method === 'freq' || method === 'frequency') { + return _topk(this); + } + + if (method === 'terms') { + var list = []; + this.json({ + text: false, + terms: { + text: true + } + }).forEach(function (obj) { + var terms = obj.terms.map(function (t) { + return t.text; + }); + terms = terms.filter(function (t) { + return t; + }); + list = list.concat(terms); + }); + return list; + } + + if (method === 'tags') { + return this.list.map(function (p) { + return p.terms().reduce(function (h, t) { + h[t.clean || t.implicit] = Object.keys(t.tags); + return h; + }, {}); + }); + } + + if (method === 'debug') { + _debug(this); + return this; + } + + return this.text(); +}; + +var _03Out = { + debug: debug_1, + out: out +}; + +// compress a list of things by frequency +var topk$1 = function topk(list) { + var counts = {}; + list.forEach(function (a) { + counts[a] = counts[a] || 0; + counts[a] += 1; + }); + var arr = Object.keys(counts); + arr = arr.sort(function (a, b) { + if (counts[a] > counts[b]) { + return -1; + } else { + return 1; + } + }); // arr = arr.filter(a => counts[a] > 1) + + return arr.map(function (a) { + return [a, counts[a]]; + }); +}; // remove implied tags, like 'Noun' when we have 'Plural' + + +var reduceTags = function reduceTags(tags, world) { + var tagset = world.tags; + var implied = []; + tags.forEach(function (tag) { + if (tagset[tag] && tagset[tag].isA) { + implied = implied.concat(tagset[tag].isA); + } + }); + implied = implied.reduce(function (h, tag) { + h[tag] = true; + return h; + }, {}); + tags = tags.filter(function (tag) { + return !implied[tag]; + }); // tags + + return tags; +}; +/** store a parsed document for later use */ + + +var export_1 = function export_1() { + var _this = this; + + var phraseList = this.json({ + text: true, + trim: false, + terms: { + tags: true, + whitespace: true + } + }); // let phraseList = json.map(p => p.terms) + + var allTags = []; + phraseList.forEach(function (p) { + p.terms.forEach(function (t) { + // reduce redundant tags + var tags = reduceTags(t.tags, _this.world); + allTags = allTags.concat(tags); + }); + }); // compress the top tags + + allTags = topk$1(allTags); + var tagMap = {}; + allTags.forEach(function (a, i) { + tagMap[a[0]] = i; + }); //use index numbers instead of redundant tag-names + + phraseList = phraseList.map(function (p) { + var terms = p.terms.map(function (term) { + var tags = term.tags; + tags = reduceTags(tags, _this.world); + tags = tags.map(function (tag) { + return tagMap[tag]; + }); + tags = tags.join(','); + return tags; + }); + terms = terms.join('|'); + return [p.text, terms]; + }); + return { + tags: Object.keys(tagMap), + // words: {}, + list: phraseList + }; +}; + +var _04Export = { + "export": export_1 +}; + +var methods$2 = { + /** alphabetical order */ + alpha: function alpha(a, b) { + var left = a.text('clean'); + var right = b.text('clean'); + + if (left < right) { + return -1; + } + + if (left > right) { + return 1; + } + + return 0; + }, + + /** count the # of characters of each match */ + length: function length(a, b) { + var left = a.text().trim().length; + var right = b.text().trim().length; + + if (left < right) { + return 1; + } + + if (left > right) { + return -1; + } + + return 0; + }, + + /** count the # of terms in each match */ + wordCount: function wordCount(a, b) { + var left = a.wordCount(); + var right = b.wordCount(); + + if (left < right) { + return 1; + } + + if (left > right) { + return -1; + } + + return 0; + } +}; +/** sort by # of duplicates in the document*/ + +var byFreq = function byFreq(doc) { + var counts = {}; + var options = { + "case": true, + punctuation: false, + whitespace: true, + unicode: true + }; + doc.list.forEach(function (p) { + var str = p.text(options); + counts[str] = counts[str] || 0; + counts[str] += 1; + }); // sort by freq + + doc.list.sort(function (a, b) { + var left = counts[a.text(options)]; + var right = counts[b.text(options)]; + + if (left < right) { + return 1; + } + + if (left > right) { + return -1; + } + + return 0; + }); + return doc; +}; // order results 'chronologically', or document-order + + +var sortSequential = function sortSequential(doc) { + var order = {}; + doc.json({ + terms: { + offset: true + } + }).forEach(function (o) { + order[o.terms[0].id] = o.terms[0].offset.start; + }); + doc.list = doc.list.sort(function (a, b) { + if (order[a.start] > order[b.start]) { + return 1; + } else if (order[a.start] < order[b.start]) { + return -1; + } + + return 0; + }); + return doc; +}; //aliases + + +methods$2.alphabetical = methods$2.alpha; +methods$2.wordcount = methods$2.wordCount; // aliases for sequential ordering + +var seqNames = { + index: true, + sequence: true, + seq: true, + sequential: true, + chron: true, + chronological: true +}; +/** re-arrange the order of the matches (in place) */ + +var sort = function sort(input) { + input = input || 'alpha'; //do this one up-front + + if (input === 'freq' || input === 'frequency' || input === 'topk') { + return byFreq(this); + } + + if (seqNames.hasOwnProperty(input)) { + return sortSequential(this); + } + + input = methods$2[input] || input; // apply sort method on each phrase + + if (typeof input === 'function') { + this.list = this.list.sort(input); + return this; + } + + return this; +}; +/** reverse the order of the matches, but not the words */ + + +var reverse = function reverse() { + var list = [].concat(this.list); + list = list.reverse(); + return this.buildFrom(list); +}; +/** remove any duplicate matches */ + + +var unique$6 = function unique() { + var list = [].concat(this.list); + var obj = {}; + list = list.filter(function (p) { + var str = p.text('reduced').trim(); + + if (obj.hasOwnProperty(str) === true) { + return false; + } + + obj[str] = true; + return true; + }); + return this.buildFrom(list); +}; + +var _01Sort = { + sort: sort, + reverse: reverse, + unique: unique$6 +}; + +var isPunct = /[\[\]{}⟨⟩:,،、‒–—―…‹›«»‐\-;\/⁄·*\•^†‡°¡¿※№÷׺ª%‰=‱¶§~|‖¦©℗®℠™¤₳฿]/g; +var quotes = /['‘’“”"′″‴]+/g; +var methods$3 = { + // cleanup newlines and extra spaces + whitespace: function whitespace(doc) { + var termArr = doc.list.map(function (ts) { + return ts.terms(); + }); + termArr.forEach(function (terms, o) { + terms.forEach(function (t, i) { + // keep dashes between words + if (t.hasDash() === true) { + t.post = ' - '; + return; + } // remove existing spaces + + + t.pre = t.pre.replace(/\s/g, ''); + t.post = t.post.replace(/\s/g, ''); //last word? ensure there's a next sentence. + + if (terms.length - 1 === i && !termArr[o + 1]) { + return; + } // no extra spaces for contractions + + + if (t.implicit && Boolean(t.text) === true) { + return; + } // no extra spaces for hyphenated words + + + if (t.hasHyphen() === true) { + return; + } + + t.post += ' '; + }); + }); + }, + punctuation: function punctuation(termList) { + termList.forEach(function (t) { + // space between hyphenated words + if (t.hasHyphen() === true) { + t.post = ' '; + } + + t.pre = t.pre.replace(isPunct, ''); + t.post = t.post.replace(isPunct, ''); // elipses + + t.post = t.post.replace(/\.\.\./, ''); // only allow one exclamation + + if (/!/.test(t.post) === true) { + t.post = t.post.replace(/!/g, ''); + t.post = '!' + t.post; + } // only allow one question mark + + + if (/\?/.test(t.post) === true) { + t.post = t.post.replace(/[\?!]*/, ''); + t.post = '?' + t.post; + } + }); + }, + unicode: function unicode(termList) { + termList.forEach(function (t) { + if (t.isImplicit() === true) { + return; + } + + t.text = unicode_1(t.text); + }); + }, + quotations: function quotations(termList) { + termList.forEach(function (t) { + t.post = t.post.replace(quotes, ''); + t.pre = t.pre.replace(quotes, ''); + }); + }, + adverbs: function adverbs(doc) { + doc.match('#Adverb').not('(not|nary|seldom|never|barely|almost|basically|so)').remove(); + }, + // remove the '.' from 'Mrs.' (safely) + abbreviations: function abbreviations(doc) { + doc.list.forEach(function (ts) { + var terms = ts.terms(); + terms.forEach(function (t, i) { + if (t.tags.Abbreviation === true && terms[i + 1]) { + t.post = t.post.replace(/^\./, ''); + } + }); + }); + } +}; +var _methods = methods$3; + +var defaults = { + // light + whitespace: true, + unicode: true, + punctuation: true, + emoji: true, + acronyms: true, + abbreviations: true, + // medium + "case": false, + contractions: false, + parentheses: false, + quotations: false, + adverbs: false, + // heavy (loose legibility) + possessives: false, + verbs: false, + nouns: false, + honorifics: false // pronouns: true, + +}; +var mapping$1 = { + light: {}, + medium: { + "case": true, + contractions: true, + parentheses: true, + quotations: true, + adverbs: true + } +}; +mapping$1.heavy = Object.assign({}, mapping$1.medium, { + possessives: true, + verbs: true, + nouns: true, + honorifics: true +}); +/** common ways to clean-up the document, and reduce noise */ + +var normalize = function normalize(options) { + options = options || {}; // support named forms + + if (typeof options === 'string') { + options = mapping$1[options] || {}; + } // set defaults + + + options = Object.assign({}, defaults, options); // clear the cache + + this.uncache(); + var termList = this.termList(); // lowercase things + + if (options["case"]) { + this.toLowerCase(); + } //whitespace + + + if (options.whitespace) { + _methods.whitespace(this); + } // unicode: é -> e + + + if (options.unicode) { + _methods.unicode(termList); + } //punctuation - keep sentence punctation, quotes, parenths + + + if (options.punctuation) { + _methods.punctuation(termList); + } // remove ':)' + + + if (options.emoji) { + this.remove('(#Emoji|#Emoticon)'); + } // 'f.b.i.' -> 'FBI' + + + if (options.acronyms) { + this.acronyms().strip(); // .toUpperCase() + } // remove period from abbreviations + + + if (options.abbreviations) { + _methods.abbreviations(this); + } // --Medium methods-- + // `isn't` -> 'is not' + + + if (options.contraction || options.contractions) { + this.contractions().expand(); + } // '(word)' -> 'word' + + + if (options.parentheses) { + this.parentheses().unwrap(); + } // remove "" punctuation + + + if (options.quotations || options.quotes) { + _methods.quotations(termList); + } // remove any un-necessary adverbs + + + if (options.adverbs) { + _methods.adverbs(this); + } // --Heavy methods-- + // `cory hart's -> cory hart' + + + if (options.possessive || options.possessives) { + this.possessives().strip(); + } // 'he walked' -> 'he walk' + + + if (options.verbs) { + this.verbs().toInfinitive(); + } // 'three dogs' -> 'three dog' + + + if (options.nouns || options.plurals) { + this.nouns().toSingular(); + } // remove 'Mr.' from 'Mr John Smith' + + + if (options.honorifics) { + this.remove('#Honorific'); + } + + return this; +}; + +var _02Normalize = { + normalize: normalize +}; + +var _03Split = createCommonjsModule(function (module, exports) { + /** return a Document with three parts for every match + * seperate everything before the word, as a new phrase + */ + exports.splitOn = function (reg) { + // if there's no match, split parent, instead + if (!reg) { + var parent = this.parent(); + return parent.splitOn(this); + } //start looking for a match.. + + + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + var foundEm = p.match(regs); //no match here, add full sentence + + if (foundEm.length === 0) { + matches.push(p); + return; + } // we found something here. + + + var carry = p; + foundEm.forEach(function (found) { + var parts = carry.splitOn(found); // add em in + + if (parts.before) { + matches.push(parts.before); + } + + if (parts.match) { + matches.push(parts.match); + } // start matching now on the end + + + carry = parts.after; + }); // add that last part + + if (carry) { + matches.push(carry); + } + }); + return this.buildFrom(matches); + }; + /** return a Document with two parts for every match + * seperate everything after the word, as a new phrase + */ + + + exports.splitAfter = function (reg) { + // if there's no match, split parent, instead + if (!reg) { + var parent = this.parent(); + return parent.splitAfter(this); + } // start looking for our matches + + + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + var foundEm = p.match(regs); //no match here, add full sentence + + if (foundEm.length === 0) { + matches.push(p); + return; + } // we found something here. + + + var carry = p; + foundEm.forEach(function (found) { + var parts = carry.splitOn(found); // add em in + + if (parts.before && parts.match) { + // merge these two together + parts.before.length += parts.match.length; + matches.push(parts.before); + } else if (parts.match) { + matches.push(parts.match); + } // start matching now on the end + + + carry = parts.after; + }); // add that last part + + if (carry) { + matches.push(carry); + } + }); + return this.buildFrom(matches); + }; + + exports.split = exports.splitAfter; //i guess? + + /** return a Document with two parts for every match */ + + exports.splitBefore = function (reg) { + // if there's no match, split parent, instead + if (!reg) { + var parent = this.parent(); + return parent.splitBefore(this); + } //start looking for a match.. + + + var regs = syntax_1(reg); + var matches = []; + this.list.forEach(function (p) { + var foundEm = p.match(regs); //no match here, add full sentence + + if (foundEm.length === 0) { + matches.push(p); + return; + } // we found something here. + + + var carry = p; + foundEm.forEach(function (found) { + var parts = carry.splitOn(found); // add before part in + + if (parts.before) { + matches.push(parts.before); + } // merge match+after + + + if (parts.match && parts.after) { + parts.match.length += parts.after.length; + } // start matching now on the end + + + carry = parts.match; + }); // add that last part + + if (carry) { + matches.push(carry); + } + }); + return this.buildFrom(matches); + }; + /** split a document into labeled sections */ + + + exports.segment = function (regs, options) { + regs = regs || {}; + options = options || { + text: true + }; + var doc = this; + var keys = Object.keys(regs); // split em + + keys.forEach(function (k) { + doc = doc.splitOn(k); + }); //add labels for each section + + doc.list.forEach(function (p) { + for (var i = 0; i < keys.length; i += 1) { + if (p.has(keys[i])) { + p.segment = regs[keys[i]]; + return; + } + } + }); + return doc.list.map(function (p) { + var res = p.json(options); + res.segment = p.segment || null; + return res; + }); + }; +}); +var _03Split_1 = _03Split.splitOn; +var _03Split_2 = _03Split.splitAfter; +var _03Split_3 = _03Split.split; +var _03Split_4 = _03Split.splitBefore; +var _03Split_5 = _03Split.segment; + +var eachTerm = function eachTerm(doc, fn) { + var world = doc.world; + doc.list.forEach(function (p) { + p.terms().forEach(function (t) { + return t[fn](world); + }); + }); + return doc; +}; +/** turn every letter of every term to lower-cse */ + + +var toLowerCase = function toLowerCase() { + return eachTerm(this, 'toLowerCase'); +}; +/** turn every letter of every term to upper case */ + + +var toUpperCase = function toUpperCase() { + return eachTerm(this, 'toUpperCase'); +}; +/** upper-case the first letter of each term */ + + +var toTitleCase = function toTitleCase() { + this.tag('TitleCase'); + return eachTerm(this, 'toTitleCase'); +}; +/** remove whitespace and title-case each term */ + + +var toCamelCase = function toCamelCase() { + this.list.forEach(function (p) { + //remove whitespace + var terms = p.terms(); + terms.forEach(function (t, i) { + if (i !== 0) { + t.toTitleCase(); + } + + if (i !== terms.length - 1) { + t.post = ''; + } + }); + }); // this.tag('#CamelCase', 'toCamelCase') + + return this; +}; + +var _04Case = { + toLowerCase: toLowerCase, + toUpperCase: toUpperCase, + toTitleCase: toTitleCase, + toCamelCase: toCamelCase +}; + +var _05Whitespace = createCommonjsModule(function (module, exports) { + /** add this punctuation or whitespace before each match: */ + exports.pre = function (str) { + if (str === undefined) { + return this.list[0].terms(0).pre; + } + + this.list.forEach(function (p) { + var term = p.terms(0); + term.pre = str; + }); + return this; + }; + /** add this punctuation or whitespace after each match: */ + + + exports.post = function (str) { + // return array of post strings + if (str === undefined) { + return this.list.map(function (p) { + var terms = p.terms(); + var term = terms[terms.length - 1]; + return term.post; + }); + } // set post string on all ends + + + this.list.forEach(function (p) { + var terms = p.terms(); + var term = terms[terms.length - 1]; + term.post = str; + }); + return this; + }; + /** remove start and end whitespace */ + + + exports.trim = function () { + this.list = this.list.map(function (p) { + return p.trim(); + }); + return this; + }; + /** connect words with hyphen, and remove whitespace */ + + + exports.hyphenate = function () { + this.list.forEach(function (p) { + var terms = p.terms(); //remove whitespace + + terms.forEach(function (t, i) { + if (i !== 0) { + t.pre = ''; + } + + if (terms[i + 1]) { + t.post = '-'; + } + }); + }); + return this; + }; + /** remove hyphens between words, and set whitespace */ + + + exports.dehyphenate = function () { + var hasHyphen = /(-|–|—)/; + this.list.forEach(function (p) { + var terms = p.terms(); //remove whitespace + + terms.forEach(function (t) { + if (hasHyphen.test(t.post)) { + t.post = ' '; + } + }); + }); + return this; + }; + + exports.deHyphenate = exports.dehyphenate; + /** add quotations around these matches */ + + exports.toQuotations = function (start, end) { + start = start || "\""; + end = end || "\""; + this.list.forEach(function (p) { + var terms = p.terms(); + terms[0].pre = start + terms[0].pre; + var last = terms[terms.length - 1]; + last.post = end + last.post; + }); + return this; + }; + + exports.toQuotation = exports.toQuotations; + /** add brackets around these matches */ + + exports.toParentheses = function (start, end) { + start = start || "("; + end = end || ")"; + this.list.forEach(function (p) { + var terms = p.terms(); + terms[0].pre = start + terms[0].pre; + var last = terms[terms.length - 1]; + last.post = end + last.post; + }); + return this; + }; +}); +var _05Whitespace_1 = _05Whitespace.pre; +var _05Whitespace_2 = _05Whitespace.post; +var _05Whitespace_3 = _05Whitespace.trim; +var _05Whitespace_4 = _05Whitespace.hyphenate; +var _05Whitespace_5 = _05Whitespace.dehyphenate; +var _05Whitespace_6 = _05Whitespace.deHyphenate; +var _05Whitespace_7 = _05Whitespace.toQuotations; +var _05Whitespace_8 = _05Whitespace.toQuotation; +var _05Whitespace_9 = _05Whitespace.toParentheses; + +/** make all phrases into one phrase */ +var join = function join(str) { + // clear the cache + this.uncache(); // make one large phrase - 'main' + + var main = this.list[0]; + var before = main.length; + var removed = {}; + + for (var i = 1; i < this.list.length; i++) { + var p = this.list[i]; + removed[p.start] = true; + var term = main.lastTerm(); // add whitespace between them + + if (str) { + term.post += str; + } // main -> p + + + term.next = p.start; // main <- p + + p.terms(0).prev = term.id; + main.length += p.length; + } // parents are bigger than than their children. + // when we increase a child, we increase their parent too. + + + var increase = main.length - before; + this.parents().forEach(function (doc) { + // increase length on each effected phrase + doc.list.forEach(function (p) { + var terms = p.terms(); + + for (var _i = 0; _i < terms.length; _i++) { + if (terms[_i].id === main.start) { + p.length += increase; + break; + } + } + }); // remove redundant phrases now + + doc.list = doc.list.filter(function (p) { + return removed[p.start] !== true; + }); + }); // return one major phrase + + return this.buildFrom([main]); +}; + +var _06Join = { + join: join +}; + +var postPunct = /[,\)"';:\-–—\.…]/; // const irregulars = { +// 'will not': `won't`, +// 'i am': `i'm`, +// } + +var setContraction = function setContraction(m, suffix) { + if (!m.found) { + return; + } + + var terms = m.termList(); //avoid any problematic punctuation + + for (var i = 0; i < terms.length - 1; i++) { + var t = terms[i]; + + if (postPunct.test(t.post)) { + return; + } + } // set them as implict + + + terms.forEach(function (t) { + t.implicit = t.clean; + }); // perform the contraction + + terms[0].text += suffix; // clean-up the others + + terms.slice(1).forEach(function (t) { + t.text = ''; + }); + + for (var _i = 0; _i < terms.length - 1; _i++) { + var _t = terms[_i]; + _t.post = _t.post.replace(/ /, ''); + } +}; +/** turn 'i am' into i'm */ + + +var contract = function contract() { + var doc = this.not('@hasContraction'); // we are -> we're + + var m = doc.match('(we|they|you) are'); + setContraction(m, "'re"); // they will -> they'll + + m = doc.match('(he|she|they|it|we|you) will'); + setContraction(m, "'ll"); // she is -> she's + + m = doc.match('(he|she|they|it|we) is'); + setContraction(m, "'s"); // spencer is -> spencer's + + m = doc.match('#Person is'); + setContraction(m, "'s"); // spencer would -> spencer'd + + m = doc.match('#Person would'); + setContraction(m, "'d"); // would not -> wouldn't + + m = doc.match('(is|was|had|would|should|could|do|does|have|has|can) not'); + setContraction(m, "n't"); // i have -> i've + + m = doc.match('(i|we|they) have'); + setContraction(m, "'ve"); // would have -> would've + + m = doc.match('(would|should|could) have'); + setContraction(m, "'ve"); // i am -> i'm + + m = doc.match('i am'); + setContraction(m, "'m"); // going to -> gonna + + m = doc.match('going to'); + return this; +}; + +var _07Contract = { + contract: contract +}; + +var methods$4 = Object.assign({}, _01Utils$1, _02Accessors, _03Match, _04Tag, _05Loops, _06Lookup, _01Replace, _02Insert, _01Text, _02Json, _03Out, _04Export, _01Sort, _02Normalize, _03Split, _04Case, _05Whitespace, _06Join, _07Contract); + +var methods$5 = {}; // allow helper methods like .adjectives() and .adverbs() + +var arr = [['terms', '.'], ['hyphenated', '@hasHyphen .'], ['adjectives', '#Adjective'], ['hashTags', '#HashTag'], ['emails', '#Email'], ['emoji', '#Emoji'], ['emoticons', '#Emoticon'], ['atMentions', '#AtMention'], ['urls', '#Url'], ['adverbs', '#Adverb'], ['pronouns', '#Pronoun'], ['conjunctions', '#Conjunction'], ['prepositions', '#Preposition']]; +arr.forEach(function (a) { + methods$5[a[0]] = function (n) { + var m = this.match(a[1]); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; + }; +}); // aliases + +methods$5.emojis = methods$5.emoji; +methods$5.atmentions = methods$5.atMentions; +methods$5.words = methods$5.terms; +/** return anything tagged as a phone number */ + +methods$5.phoneNumbers = function (n) { + var m = this.splitAfter('@hasComma'); + m = m.match('#PhoneNumber+'); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; +}; +/** money + currency pair */ + + +methods$5.money = function (n) { + var m = this.match('#Money #Currency?'); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; +}; +/** return all cities, countries, addresses, and regions */ + + +methods$5.places = function (n) { + // don't split 'paris, france' + var keep = this.match('(#City && @hasComma) (#Region|#Country)'); // but split the other commas + + var m = this.not(keep).splitAfter('@hasComma'); // combine them back together + + m = m.concat(keep); + m.sort('index'); + m = m.match('#Place+'); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; +}; +/** return all schools, businesses and institutions */ + + +methods$5.organizations = function (n) { + var m = this.clauses(); + m = m.match('#Organization+'); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; +}; //combine them with .topics() method + + +methods$5.entities = function (n) { + var r = this.clauses(); // Find people, places, and organizations + + var yup = r.people(); + yup = yup.concat(r.places()); + yup = yup.concat(r.organizations()); + var ignore = ['someone', 'man', 'woman', 'mother', 'brother', 'sister', 'father']; + yup = yup.not(ignore); //return them to normal ordering + + yup.sort('sequence'); // yup.unique() //? not sure + + if (typeof n === 'number') { + yup = yup.get(n); + } + + return yup; +}; //aliases + + +methods$5.things = methods$5.entities; +methods$5.topics = methods$5.entities; +/** alias for .all() until it gets overloaded by plugin */ + +methods$5.sentences = function () { + return this.all(); +}; + +var _simple = methods$5; + +/** match a word-sequence, like 'super bowl' in the lexicon */ +var tryMultiple = function tryMultiple(terms, t, world) { + var lex = world.words; //try a two-word version + + var txt = terms[t].reduced + ' ' + terms[t + 1].reduced; + + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-two', world); + terms[t + 1].tag(lex[txt], 'lexicon-two', world); + return 1; + } //try a three-word version? + + + if (t + 2 < terms.length) { + txt += ' ' + terms[t + 2].reduced; + + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-three', world); + terms[t + 1].tag(lex[txt], 'lexicon-three', world); + terms[t + 2].tag(lex[txt], 'lexicon-three', world); + return 2; + } + } //try a four-word version? + + + if (t + 3 < terms.length) { + txt += ' ' + terms[t + 3].reduced; + + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-four', world); + terms[t + 1].tag(lex[txt], 'lexicon-four', world); + terms[t + 2].tag(lex[txt], 'lexicon-four', world); + terms[t + 3].tag(lex[txt], 'lexicon-four', world); + return 3; + } + } + + return 0; +}; +/** look at each word in our list of known-words */ + + +var checkLexicon = function checkLexicon(terms, world) { + var lex = world.words; + var hasCompound = world.hasCompound; // use reduced? + //go through each term, and check the lexicon + + for (var t = 0; t < terms.length; t += 1) { + var str = terms[t].clean; //is it the start of a compound word, like 'super bowl'? + + if (hasCompound[str] === true && t + 1 < terms.length) { + var foundWords = tryMultiple(terms, t, world); + + if (foundWords > 0) { + t += foundWords; //skip any already-found words + + continue; + } + } //try one-word lexicon + + + if (lex[str] !== undefined && lex.hasOwnProperty(str) === true) { + terms[t].tag(lex[str], 'lexicon', world); + } // look at reduced version of term, too + + + if (str !== terms[t].reduced && lex.hasOwnProperty(terms[t].reduced) === true) { + terms[t].tag(lex[terms[t].reduced], 'lexicon', world); + } + } + + return terms; +}; + +var _01Lexicon = checkLexicon; + +var apostrophes = /[\'‘’‛‵′`´]$/; +var oneLetterAcronym$1 = /^[A-Z]('s|,)?$/; +var oneLetterWord = { + I: true, + A: true +}; + +var isAcronym$2 = function isAcronym(term, world) { + var str = term.reduced; // a known acronym like fbi + + if (term.tags.Acronym) { + return true; + } // if (term.tags.Adverb || term.tags.Verb || term.tags.Value || term.tags.Plural) { + // return false + // } + // 'PIZZA' is not an acronym. + + + if (str.length > 4 && world.words[str]) { + return false; + } + + return term.isAcronym(); +}; // + + +var checkPunctuation = function checkPunctuation(terms, i, world) { + var term = terms[i]; //check hyphenation + // if (term.post.indexOf('-') !== -1 && terms[i + 1] && terms[i + 1].pre === '') { + // term.tag('Hyphenated', 'has-hyphen', world) + // } + //an end-tick (trailing apostrophe) - flanders', or Carlos' + + if (apostrophes.test(term.text)) { + if (!apostrophes.test(term.pre) && !apostrophes.test(term.post) && term.clean.length > 2) { + var endChar = term.clean[term.clean.length - 2]; //flanders' + + if (endChar === 's') { + term.tag(['Possessive', 'Noun'], 'end-tick', world); + return; + } //chillin' + + + if (endChar === 'n') { + term.tag(['Gerund'], 'chillin', world); + } + } + } // 'NASA' is, but not 'i REALLY love it.' + + + if (isAcronym$2(term, world)) { + term.tag('Acronym', 'acronym-step', world); + term.tag('Noun', 'acronym-infer', world); + } else if (!oneLetterWord.hasOwnProperty(term.text) && oneLetterAcronym$1.test(term.text)) { + term.tag('Acronym', 'one-letter-acronym', world); + term.tag('Noun', 'one-letter-infer', world); + } +}; + +var _02Punctuation$1 = checkPunctuation; + +//these are regexes applied to t.text, instead of t.clean +// order matters. +var startsWith = [//phone numbers +[/^[0-9]{3}-[0-9]{4}$/, 'PhoneNumber'], //589-3809 +[/^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$/, 'PhoneNumber'], //632-589-3809 +//money +[/^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?([a-z]{1,4})?$/, ['Money', 'Value']], //like $5.30 +[/^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$/, ['Money', 'Value']], //like $5,231.30 +[/^[-+]?[0-9]([0-9,.]+)?(usd|eur|jpy|gbp|cad|aud|chf|cny|hkd|nzd|kr|rub)$/i, ['Money', 'Value']], //like 400usd +//web tags +[/^\w+@\w+\.[a-z]{2,3}$/, 'Email'], //not fancy +[/^#[a-z0-9_\u00C0-\u00FF]{2,}$/, 'HashTag'], [/^@\w{2,}$/, 'AtMention'], [/^(https?:\/\/|www\.)\w+\.[a-z]{2,3}/, 'Url'], //with http/www +[/^[\w\.\/]+\.(com|net|gov|org|ly|edu|info|biz|ru|jp|de|in|uk|br)/, 'Url'], //http://mostpopularwebsites.net/top-level-domain +//dates/times +[/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$/, 'Time'], //4:32:32 +[/^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$/, 'Time'], //4pm +[/^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$/, 'Time'], //4:00pm +[/^[PMCE]ST$/, 'Time'], //PST, time zone abbrevs +[/^utc ?[+-]?[0-9]+?$/, 'Time'], //UTC 8+ +[/^[a-z0-9]*? o\'?clock$/, 'Time'], //3 oclock +[/^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$/, 'Date'], // 03-02-89 +[/^[0-9]{1,4}\/[0-9]{1,2}\/[0-9]{1,4}$/, 'Date'], // 03/02/89 +//names +[/^ma?c\'.*/, 'LastName'], //mc'adams +[/^o\'[drlkn].*/, 'LastName'], //o'douggan +[/^ma?cd[aeiou]/, 'LastName'], //macdonell - Last patterns https://en.wikipedia.org/wiki/List_of_family_name_affixes +//slang things +[/^(lol)+[sz]$/, 'Expression'], //lol +[/^(un|de|re)\\-[a-z\u00C0-\u00FF]{2}/, 'Verb'], [/^[\-\+]?[0-9]+(\.[0-9])*$/, ['Cardinal', 'NumericValue']], [/^(over|under)[a-z]{2,}/, 'Adjective'], [/^[0-9]{1,4}\.[0-9]{1,2}\.[0-9]{1,4}$/, 'Date'], // 03-02-89 +//numbers +[/^[\-\+]?[0-9][0-9,]*(\.[0-9])*$/, ['Cardinal', 'NumericValue']], //like 5 +[/^[-+]?[0-9]+(.[0-9]+)?$/, ['Cardinal', 'NumericValue']], //like +5.0 +[/^[0-9\.]{1,4}(st|nd|rd|th)?[-–][0-9\.]{1,4}(st|nd|rd|th)?$/, 'NumberRange'], //5-7 +[/^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$/, 'NumericValue'], //like 5,999.0 +[/^.?[0-9]+([0-9,.]+)?%$/, ['Percent', 'Cardinal', 'NumericValue']], //7% .. +[/^[0-9]{1,4}\/[0-9]{1,4}$/, 'Fraction'], //3/2ths +[/^[0-9\.]{1,2}[-–][0-9]{1,2}$/, ['Value', 'NumberRange']], //7-8 +[/^[0-9][0-9,\.]*(st|nd|rd|r?th)$/, ['NumericValue', 'Ordinal']], //like 5th +[/[0-9]\+$/, ['Cardinal', 'NumericValue']], //10+ +[/^[0-9]+(st|nd|rd|th)$/, 'Ordinal'], //like 5th +[/^[0-9\.]+([a-z]{1,4})$/, 'Value'] //like 5tbsp +]; + +var romanNumeral = /^[IVXLCDM]{2,}$/; +var romanNumValid = /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/; // https://stackoverflow.com/a/267405/168877 +//try each of the ^regexes in our list + +var checkRegex = function checkRegex(term, world) { + var str = term.text; // do them all! + + for (var r = 0; r < startsWith.length; r += 1) { + if (startsWith[r][0].test(str) === true) { + term.tagSafe(startsWith[r][1], 'regex #' + r, world); + break; + } + } // do some more! + //roman numberals - XVII + + + if (term.text.length >= 2 && romanNumeral.test(str) && romanNumValid.test(str)) { + term.tag('RomanNumeral', 'xvii', world); + } +}; + +var _03Prefixes = checkRegex; + +//regex suffix patterns and their most common parts of speech, +//built using wordnet, by spencer kelly. +//this mapping shrinks-down the uglified build +var Adj = 'Adjective'; +var Inf = 'Infinitive'; +var Pres = 'PresentTense'; +var Sing = 'Singular'; +var Past = 'PastTense'; +var Adverb = 'Adverb'; +var Exp = 'Expression'; +var Actor = 'Actor'; +var Verb = 'Verb'; +var Noun = 'Noun'; +var Last = 'LastName'; //the order here matters. +//regexes indexed by mandated last-character + +var endsWith$1 = { + a: [[/.[aeiou]na$/, Noun], [/.[oau][wvl]ska$/, Last], //polish (female) + [/.[^aeiou]ica$/, Sing], [/^([hyj]a)+$/, Exp] //hahah + ], + c: [[/.[^aeiou]ic$/, Adj]], + d: [[/.[ia]sed$/, Adj], [/.[gt]led$/, Adj], [/.[td]ed$/, Past], [/.[aeiou]red$/, Past], [/.[^aeiou]led$/, Past], //rumbled + [/[^aeiou]ard$/, Sing], [/[aeiou][^aeiou]id$/, Adj], [/[aeiou]c?ked$/, Past], //hooked + [/[^aeiou][aeiou][tvx]ed$/, Past], //boxed + [/.[vrl]id$/, Adj]], + e: [[/.[lnr]ize$/, Inf], [/.[^aeiou]ise$/, Inf], [/.[aeiou]te$/, Inf], [/.[^aeiou][ai]ble$/, Adj], [/.[^aeiou]eable$/, Adj], [/.[ts]ive$/, Adj]], + h: [[/.[^aeiouf]ish$/, Adj], [/.v[iy]ch$/, Last], //east-europe + [/^ug?h+$/, Exp], //uhh + [/^uh[ -]?oh$/, Exp] //uhoh + ], + i: [[/.[oau][wvl]ski$/, Last] //polish (male) + ], + k: [[/^(k)+$/, Exp] //kkkk + ], + l: [[/.[gl]ial$/, Adj], [/.[^aeiou]ful$/, Adj], [/.[nrtumcd]al$/, Adj], [/.[^aeiou][ei]al$/, Adj]], + m: [[/.[^aeiou]ium$/, Sing], [/[^aeiou]ism$/, Sing], [/^h*u*m+$/, Exp], //mmmmmmm / ummmm / huuuuuummmmmm + [/^\d+ ?[ap]m$/, 'Date']], + n: [[/.[lsrnpb]ian$/, Adj], [/[^aeiou]ician$/, Actor]], + o: [[/^no+$/, Exp], //noooo + [/^(yo)+$/, Exp], //yoyo + [/^woo+[pt]?$/, Exp] //woo + ], + r: [[/.[bdfklmst]ler$/, 'Noun'], [/.[ilk]er$/, 'Comparative'], [/[aeiou][pns]er$/, Sing], [/[^i]fer$/, Inf], [/.[^aeiou][ao]pher$/, Actor]], + t: [[/.[di]est$/, 'Superlative'], [/.[icldtgrv]ent$/, Adj], [/[aeiou].*ist$/, Adj], [/^[a-z]et$/, Verb]], + s: [[/.[rln]ates$/, Pres], [/.[^z]ens$/, Verb], [/.[lstrn]us$/, Sing], [/[aeiou][^aeiou]is$/, Sing], [/[a-z]\'s$/, Noun], [/^yes+$/, Exp] //yessss + ], + v: [[/.[^aeiou][ai][kln]ov$/, Last] //east-europe + ], + y: [[/.[cts]hy$/, Adj], [/.[st]ty$/, Adj], [/.[gk]y$/, Adj], [/.[tnl]ary$/, Adj], [/.[oe]ry$/, Sing], [/[rdntkbhs]ly$/, Adverb], [/...lly$/, Adverb], [/[bszmp]{2}y$/, Adj], [/.(gg|bb|zz)ly$/, Adj], [/.[aeiou]my$/, Adj], [/[ea]{2}zy$/, Adj], [/.[^aeiou]ity$/, Sing]] +}; + +//just a foolish lookup of known suffixes +var Adj$1 = 'Adjective'; +var Inf$1 = 'Infinitive'; +var Pres$1 = 'PresentTense'; +var Sing$1 = 'Singular'; +var Past$1 = 'PastTense'; +var Avb = 'Adverb'; +var Plrl = 'Plural'; +var Actor$1 = 'Actor'; +var Vb = 'Verb'; +var Noun$1 = 'Noun'; +var Last$1 = 'LastName'; +var Modal = 'Modal'; // find any issues - https://observablehq.com/@spencermountain/suffix-word-lookup + +var suffixMap = [null, //0 +null, //1 +{ + //2-letter + ea: Sing$1, + ia: Noun$1, + ic: Adj$1, + ly: Avb, + "'n": Vb, + "'t": Vb +}, { + //3-letter + que: Adj$1, + lar: Adj$1, + ffy: Adj$1, + nny: Adj$1, + rmy: Adj$1, + azy: Adj$1, + oid: Adj$1, + mum: Adj$1, + ous: Adj$1, + end: Vb, + sis: Sing$1, + rol: Sing$1, + ize: Inf$1, + ify: Inf$1, + zes: Pres$1, + nes: Pres$1, + ing: 'Gerund', + //likely to be converted to Adj after lexicon pass + ' so': Avb, + "'ll": Modal, + "'re": 'Copula' +}, { + //4-letter + teen: 'Value', + tors: Noun$1, + amed: Past$1, + ched: Past$1, + ends: Vb, + oses: Pres$1, + fies: Pres$1, + ects: Pres$1, + nded: Past$1, + cede: Inf$1, + tage: Inf$1, + gate: Inf$1, + vice: Sing$1, + tion: Sing$1, + cted: Past$1, + ette: Sing$1, + some: Adj$1, + llen: Adj$1, + ried: Adj$1, + gone: Adj$1, + made: Adj$1, + fore: Avb, + less: Avb, + ices: Plrl, + ions: Plrl, + ints: Plrl, + aped: Past$1, + lked: Past$1, + ould: Modal, + tive: Actor$1, + sson: Last$1, + //swedish male + czyk: Last$1, + //polish (male) + chuk: Last$1, + //east-europe + enko: Last$1, + //east-europe + akis: Last$1, + //greek + nsen: Last$1 //norway + +}, { + //5-letter + fully: Avb, + where: Avb, + wards: Avb, + urned: Past$1, + tized: Past$1, + eased: Past$1, + ances: Plrl, + tures: Plrl, + ports: Plrl, + ettes: Plrl, + ities: Plrl, + rough: Adj$1, + ology: Noun$1, + bound: Adj$1, + tieth: 'Ordinal', + ishes: Pres$1, + tches: Pres$1, + nssen: Last$1, + //norway + marek: Last$1 //polish (male) + +}, { + //6-letter + keeper: Actor$1, + logist: Actor$1, + auskas: Last$1, + //lithuania + teenth: 'Value' +}, { + //7-letter + sdottir: Last$1, + //swedish female + opoulos: Last$1 //greek + +}]; + +var endRegexs = function endRegexs(term, world) { + var str = term.clean; + var _char = str[str.length - 1]; + + if (endsWith$1.hasOwnProperty(_char) === true) { + var regs = endsWith$1[_char]; + + for (var r = 0; r < regs.length; r += 1) { + if (regs[r][0].test(str) === true) { + term.tagSafe(regs[r][1], "endReg ".concat(_char, " #").concat(r), world); + break; + } + } + } +}; //sweep-through all suffixes + + +var knownSuffixes = function knownSuffixes(term, world) { + var len = term.clean.length; + var max = 7; + + if (len <= max) { + max = len - 1; + } + + for (var i = max; i > 1; i -= 1) { + var str = term.clean.substr(len - i, len); + + if (suffixMap[str.length].hasOwnProperty(str) === true) { + var tag = suffixMap[str.length][str]; + term.tagSafe(tag, 'suffix -' + str, world); + break; + } + } +}; //all-the-way-down! + + +var checkRegex$1 = function checkRegex(term, world) { + knownSuffixes(term, world); + endRegexs(term, world); +}; + +var _04Suffixes = checkRegex$1; + +//just some of the most common emoticons +//faster than +//http://stackoverflow.com/questions/28077049/regex-matching-emoticons +var emoticons = { + ':(': true, + ':)': true, + ':P': true, + ':p': true, + ':O': true, + ':3': true, + ':|': true, + ':/': true, + ':\\': true, + ':$': true, + ':*': true, + ':@': true, + ':-(': true, + ':-)': true, + ':-P': true, + ':-p': true, + ':-O': true, + ':-3': true, + ':-|': true, + ':-/': true, + ':-\\': true, + ':-$': true, + ':-*': true, + ':-@': true, + ':^(': true, + ':^)': true, + ':^P': true, + ':^p': true, + ':^O': true, + ':^3': true, + ':^|': true, + ':^/': true, + ':^\\': true, + ':^$': true, + ':^*': true, + ':^@': true, + '):': true, + '(:': true, + '$:': true, + '*:': true, + ')-:': true, + '(-:': true, + '$-:': true, + '*-:': true, + ')^:': true, + '(^:': true, + '$^:': true, + '*^:': true, + '<3': true, + ' 35) { + return false; + } + + return true; + } + + return false; +}; //check against emoticon whitelist + + +var isEmoticon = function isEmoticon(str) { + str = str.replace(/^[:;]/, ':'); //normalize the 'eyes' + + return emoticons.hasOwnProperty(str); +}; + +var tagEmoji = function tagEmoji(term, world) { + var raw = term.pre + term.text + term.post; + raw = raw.trim(); //test for :keyword: emojis + + if (isCommaEmoji(raw) === true) { + term.tag('Emoji', 'comma-emoji', world); + term.text = raw; + term.pre = term.pre.replace(':', ''); + term.post = term.post.replace(':', ''); + } //test for unicode emojis + + + if (term.text.match(emojiReg)) { + term.tag('Emoji', 'unicode-emoji', world); + term.text = raw; + } //test for emoticon ':)' emojis + + + if (isEmoticon(raw) === true) { + term.tag('Emoticon', 'emoticon-emoji', world); + term.text = raw; + } +}; + +var _05Emoji = tagEmoji; + +var steps = { + lexicon: _01Lexicon, + punctuation: _02Punctuation$1, + regex: _03Prefixes, + suffix: _04Suffixes, + emoji: _05Emoji +}; //'lookups' look at a term by itself + +var lookups = function lookups(doc) { + var terms = doc.termList(); + var world = doc.world; //our list of known-words + + steps.lexicon(terms, world); //try these other methods + + for (var i = 0; i < terms.length; i += 1) { + var term = terms[i]; //or maybe some helpful punctuation + + steps.punctuation(terms, i, world); //mostly prefix checks + + steps.regex(term, world); //maybe we can guess + + steps.suffix(term, world); //emoji and emoticons + + steps.emoji(term, world); + } + + return doc; +}; + +var _01Init = lookups; + +//markov-like stats about co-occurance, for hints about unknown terms +//basically, a little-bit better than the noun-fallback +//just top n-grams from nlp tags, generated from nlp-corpus +//after this word, here's what happens usually +var afterThisWord = { + i: 'Verb', + //44% //i walk.. + first: 'Noun', + //50% //first principles.. + it: 'Verb', + //33% + there: 'Verb', + //35% + not: 'Verb', + //33% + because: 'Noun', + //31% + "if": 'Noun', + //32% + but: 'Noun', + //26% + who: 'Verb', + //40% + "this": 'Noun', + //37% + his: 'Noun', + //48% + when: 'Noun', + //33% + you: 'Verb', + //35% + very: 'Adjective', + // 39% + old: 'Noun', + //51% + never: 'Verb', + //42% + before: 'Noun' //28% + +}; //in advance of this word, this is what happens usually + +var beforeThisWord = { + there: 'Verb', + //23% // be there + me: 'Verb', + //31% //see me + man: 'Adjective', + // 80% //quiet man + only: 'Verb', + //27% //sees only + him: 'Verb', + //32% //show him + were: 'Noun', + //48% //we were + took: 'Noun', + //38% //he took + himself: 'Verb', + //31% //see himself + went: 'Noun', + //43% //he went + who: 'Noun', + //47% //person who + jr: 'Person' +}; //following this POS, this is likely + +var afterThisPOS = { + Adjective: 'Noun', + //36% //blue dress + Possessive: 'Noun', + //41% //his song + Determiner: 'Noun', + //47% + Adverb: 'Verb', + //20% + Pronoun: 'Verb', + //40% + Value: 'Noun', + //47% + Ordinal: 'Noun', + //53% + Modal: 'Verb', + //35% + Superlative: 'Noun', + //43% + Demonym: 'Noun', + //38% + Honorific: 'Person' // + +}; //in advance of this POS, this is likely + +var beforeThisPOS = { + Copula: 'Noun', + //44% //spencer is + PastTense: 'Noun', + //33% //spencer walked + Conjunction: 'Noun', + //36% + Modal: 'Noun', + //38% + Pluperfect: 'Noun', + //40% + PerfectTense: 'Verb' //32% + +}; +var markov = { + beforeThisWord: beforeThisWord, + afterThisWord: afterThisWord, + beforeThisPos: beforeThisPOS, + afterThisPos: afterThisPOS +}; + +var afterKeys = Object.keys(markov.afterThisPos); +var beforeKeys = Object.keys(markov.beforeThisPos); + +var checkNeighbours = function checkNeighbours(terms, world) { + var _loop = function _loop(i) { + var term = terms[i]; //do we still need a tag? + + if (term.isKnown() === true) { + return "continue"; + } //ok, this term needs a tag. + //look at previous word for clues.. + + + var lastTerm = terms[i - 1]; + + if (lastTerm) { + // 'foobar term' + if (markov.afterThisWord.hasOwnProperty(lastTerm.clean) === true) { + var tag = markov.afterThisWord[lastTerm.clean]; + term.tag(tag, 'after-' + lastTerm.clean, world); + return "continue"; + } // 'Tag term' + // (look at previous POS tags for clues..) + + + var foundTag = afterKeys.find(function (tag) { + return lastTerm.tags[tag]; + }); + + if (foundTag !== undefined) { + var _tag = markov.afterThisPos[foundTag]; + term.tag(_tag, 'after-' + foundTag, world); + return "continue"; + } + } //look at next word for clues.. + + + var nextTerm = terms[i + 1]; + + if (nextTerm) { + // 'term foobar' + if (markov.beforeThisWord.hasOwnProperty(nextTerm.clean) === true) { + var _tag2 = markov.beforeThisWord[nextTerm.clean]; + term.tag(_tag2, 'before-' + nextTerm.clean, world); + return "continue"; + } // 'term Tag' + // (look at next POS tags for clues..) + + + var _foundTag = beforeKeys.find(function (tag) { + return nextTerm.tags[tag]; + }); + + if (_foundTag !== undefined) { + var _tag3 = markov.beforeThisPos[_foundTag]; + term.tag(_tag3, 'before-' + _foundTag, world); + return "continue"; + } + } + }; + + for (var i = 0; i < terms.length; i += 1) { + var _ret = _loop(i); + + if (_ret === "continue") continue; + } +}; + +var _01Neighbours = checkNeighbours; + +var titleCase$3 = /^[A-Z][a-z'\u00C0-\u00FF]/; +var hasNumber = /[0-9]/; +/** look for any grammar signals based on capital/lowercase */ + +var checkCase = function checkCase(terms, world) { + terms.forEach(function (term, i) { + //is it a titlecased word? + if (titleCase$3.test(term.text) === true && hasNumber.test(term.text) === false) { + // tag it as titlecase, if possible + if (i !== 0) { + term.tag('TitleCase', 'case', world); + } else if (term.tags.Person || term.tags.Organization || term.tags.Place) { + term.tag('TitleCase', 'case-person', world); + } // can we call it a noun? + + + if (i !== 0) { + //sure! + term.tag('ProperNoun', 'case-noun', world); + } + } + }); +}; + +var _02Case = checkCase; + +var hasPrefix = /^(re|un)-?[a-z\u00C0-\u00FF]/; +var prefix = /^(re|un)-?/; +/** check 'rewatch' in lexicon as 'watch' */ + +var checkPrefix = function checkPrefix(terms, world) { + var lex = world.words; + terms.forEach(function (term) { + // skip if we have a good tag already + if (term.isKnown() === true) { + return; + } //does it start with 'un|re' + + + if (hasPrefix.test(term.clean) === true) { + // look for the root word in the lexicon: + var stem = term.clean.replace(prefix, ''); + + if (stem && stem.length > 3 && lex[stem] !== undefined && lex.hasOwnProperty(stem) === true) { + term.tag(lex[stem], 'stem-' + stem, world); + } + } + }); +}; + +var _03Stem = checkPrefix; + +//similar to plural/singularize rules, but not the same +var isPlural = [/(^v)ies$/i, /ises$/i, /ives$/i, /(antenn|formul|nebul|vertebr|vit)ae$/i, /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, /(buffal|tomat|tornad)oes$/i, /(analy|ba|diagno|parenthe|progno|synop|the)ses$/i, /(vert|ind|cort)ices$/i, /(matr|append)ices$/i, /(x|ch|ss|sh|s|z|o)es$/i, /is$/i, /men$/i, /news$/i, /.tia$/i, /(^f)ves$/i, /(lr)ves$/i, /(^aeiouy|qu)ies$/i, /(m|l)ice$/i, /(cris|ax|test)es$/i, /(alias|status)es$/i, /ics$/i]; //similar to plural/singularize rules, but not the same + +var isSingular = [/(ax|test)is$/i, /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, /(octop|vir)i$/i, /(rl)f$/i, /(alias|status)$/i, /(bu)s$/i, /(al|ad|at|er|et|ed|ad)o$/i, /(ti)um$/i, /(ti)a$/i, /sis$/i, /(?:(^f)fe|(lr)f)$/i, /hive$/i, /s[aeiou]+ns$/i, // sans, siens +/(^aeiouy|qu)y$/i, /(x|ch|ss|sh|z)$/i, /(matr|vert|ind|cort)(ix|ex)$/i, /(m|l)ouse$/i, /(m|l)ice$/i, /(antenn|formul|nebul|vertebr|vit)a$/i, /.sis$/i, /^(?!talis|.*hu)(.*)man$/i]; +var isPlural_1 = { + isSingular: isSingular, + isPlural: isPlural +}; + +var noPlurals = ['Uncountable', 'Pronoun', 'Place', 'Value', 'Person', 'Month', 'WeekDay', 'Holiday']; +var notPlural = [/ss$/, /sis$/, /[^aeiou][uo]s$/, /'s$/]; +var notSingular = [/i$/, /ae$/]; +/** turn nouns into singular/plural */ + +var checkPlural = function checkPlural(t, world) { + if (t.tags.Noun && !t.tags.Acronym) { + var str = t.clean; //skip existing tags, fast + + if (t.tags.Singular || t.tags.Plural) { + return; + } //too short + + + if (str.length <= 3) { + t.tag('Singular', 'short-singular', world); + return; + } //is it impossible to be plural? + + + if (noPlurals.find(function (tag) { + return t.tags[tag]; + })) { + return; + } // isPlural suffix rules + + + if (isPlural_1.isPlural.find(function (reg) { + return reg.test(str); + })) { + t.tag('Plural', 'plural-rules', world); + return; + } // isSingular suffix rules + + + if (isPlural_1.isSingular.find(function (reg) { + return reg.test(str); + })) { + t.tag('Singular', 'singular-rules', world); + return; + } // finally, fallback 'looks plural' rules.. + + + if (/s$/.test(str) === true) { + //avoid anything too sketchy to be plural + if (notPlural.find(function (reg) { + return reg.test(str); + })) { + return; + } + + t.tag('Plural', 'plural-fallback', world); + return; + } //avoid anything too sketchy to be singular + + + if (notSingular.find(function (reg) { + return reg.test(str); + })) { + return; + } + + t.tag('Singular', 'singular-fallback', world); + } +}; + +var _04Plurals = checkPlural; + +//nouns that also signal the title of an unknown organization +//todo remove/normalize plural forms +var orgWords = ['academy', 'administration', 'agence', 'agences', 'agencies', 'agency', 'airlines', 'airways', 'army', 'assoc', 'associates', 'association', 'assurance', 'authority', 'autorite', 'aviation', 'bank', 'banque', 'board', 'boys', 'brands', 'brewery', 'brotherhood', 'brothers', 'building society', 'bureau', 'cafe', 'caisse', 'capital', 'care', 'cathedral', 'center', 'central bank', 'centre', 'chemicals', 'choir', 'chronicle', 'church', 'circus', 'clinic', 'clinique', 'club', 'co', 'coalition', 'coffee', 'collective', 'college', 'commission', 'committee', 'communications', 'community', 'company', 'comprehensive', 'computers', 'confederation', 'conference', 'conseil', 'consulting', 'containers', 'corporation', 'corps', 'corp', 'council', 'crew', 'daily news', 'data', 'departement', 'department', 'department store', 'departments', 'design', 'development', 'directorate', 'division', 'drilling', 'education', 'eglise', 'electric', 'electricity', 'energy', 'ensemble', 'enterprise', 'enterprises', 'entertainment', 'estate', 'etat', 'evening news', 'faculty', 'federation', 'financial', 'fm', 'foundation', 'fund', 'gas', 'gazette', 'girls', 'government', 'group', 'guild', 'health authority', 'herald', 'holdings', 'hospital', 'hotel', 'hotels', 'inc', 'industries', 'institut', 'institute', 'institute of technology', 'institutes', 'insurance', 'international', 'interstate', 'investment', 'investments', 'investors', 'journal', 'laboratory', 'labs', // 'law', +'liberation army', 'limited', 'local authority', 'local health authority', 'machines', 'magazine', 'management', 'marine', 'marketing', 'markets', 'media', 'memorial', 'mercantile exchange', 'ministere', 'ministry', 'military', 'mobile', 'motor', 'motors', 'musee', 'museum', // 'network', +'news', 'news service', 'observatory', 'office', 'oil', 'optical', 'orchestra', 'organization', 'partners', 'partnership', // 'party', +"people's party", 'petrol', 'petroleum', 'pharmacare', 'pharmaceutical', 'pharmaceuticals', 'pizza', 'plc', 'police', 'polytechnic', 'post', 'power', 'press', 'productions', 'quartet', 'radio', 'regional authority', 'regional health authority', 'reserve', 'resources', 'restaurant', 'restaurants', 'savings', 'school', 'securities', 'service', 'services', 'social club', 'societe', 'society', 'sons', 'standard', 'state police', 'state university', 'stock exchange', 'subcommittee', 'syndicat', 'systems', 'telecommunications', 'telegraph', 'television', 'times', 'tribunal', 'tv', 'union', 'university', 'utilities', 'workers']; +var organizations = orgWords.reduce(function (h, str) { + h[str] = 'Noun'; + return h; +}, {}); + +var maybeOrg = function maybeOrg(t) { + //must be a noun + if (!t.tags.Noun) { + return false; + } //can't be these things + + + if (t.tags.Pronoun || t.tags.Comma || t.tags.Possessive) { + return false; + } //must be one of these + + + if (t.tags.Organization || t.tags.Acronym || t.tags.Place || t.titleCase()) { + return true; + } + + return false; +}; + +var tagOrgs = function tagOrgs(terms, world) { + for (var i = 0; i < terms.length; i += 1) { + var t = terms[i]; + + if (organizations[t.clean] !== undefined && organizations.hasOwnProperty(t.clean) === true) { + // look-backward - eg. 'Toronto University' + var lastTerm = terms[i - 1]; + + if (lastTerm !== undefined && maybeOrg(lastTerm) === true) { + lastTerm.tagSafe('Organization', 'org-word-1', world); + t.tagSafe('Organization', 'org-word-2', world); + continue; + } //look-forward - eg. University of Toronto + + + var nextTerm = terms[i + 1]; + + if (nextTerm !== undefined && nextTerm.clean === 'of') { + if (terms[i + 2] && maybeOrg(terms[i + 2])) { + t.tagSafe('Organization', 'org-of-word-1', world); + nextTerm.tagSafe('Organization', 'org-of-word-2', world); + terms[i + 2].tagSafe('Organization', 'org-of-word-3', world); + continue; + } + } + } + } +}; + +var _05Organizations = tagOrgs; + +var step = { + neighbours: _01Neighbours, + "case": _02Case, + stem: _03Stem, + plural: _04Plurals, + organizations: _05Organizations +}; // + +var fallbacks = function fallbacks(doc) { + var terms = doc.termList(); + var world = doc.world; // if it's empty, consult it's neighbours, first + + step.neighbours(terms, world); // is there a case-sensitive clue? + + step["case"](terms, world); // check 'rewatch' as 'watch' + + step.stem(terms, world); // ... fallback to a noun! + + terms.forEach(function (t) { + if (t.isKnown() === false) { + t.tag('Noun', 'noun-fallback', doc.world); + } + }); // turn 'Foo University' into an Org + + step.organizations(terms, world); //are the nouns singular or plural? + + terms.forEach(function (t) { + step.plural(t, doc.world); + }); + return doc; +}; + +var _02Fallbacks = fallbacks; + +var hasNegative = /n't$/; +var irregulars$3 = { + "won't": ['will', 'not'], + wont: ['will', 'not'], + "can't": ['can', 'not'], + cant: ['can', 'not'], + cannot: ['can', 'not'], + "shan't": ['should', 'not'], + dont: ['do', 'not'], + dun: ['do', 'not'] // "ain't" is ambiguous for is/was + +}; + +var checkNegative = function checkNegative(term) { + //check named-ones + if (irregulars$3.hasOwnProperty(term.clean) === true) { + return irregulars$3[term.clean]; + } //try it normally + + + if (hasNegative.test(term.clean) === true) { + var main = term.clean.replace(hasNegative, ''); + return [main, 'not']; + } + + return null; +}; + +var _01Negative = checkNegative; + +var contraction = /([a-z\u00C0-\u00FF]+)'([a-z]{1,2})$/i; //these ones don't seem to be ambiguous + +var easy = { + ll: 'will', + ve: 'have', + re: 'are', + m: 'am', + "n't": 'not' +}; // + +var checkApostrophe = function checkApostrophe(term) { + var parts = term.text.match(contraction); + + if (parts === null) { + return null; + } + + if (easy.hasOwnProperty(parts[2])) { + return [parts[1], easy[parts[2]]]; + } + + return null; +}; + +var _02Simple = checkApostrophe; + +var irregulars$4 = { + wanna: ['want', 'to'], + gonna: ['going', 'to'], + im: ['i', 'am'], + alot: ['a', 'lot'], + ive: ['i', 'have'], + imma: ['I', 'will'], + "where'd": ['where', 'did'], + whered: ['where', 'did'], + "when'd": ['when', 'did'], + whend: ['when', 'did'], + "how'd": ['how', 'did'], + howd: ['how', 'did'], + "what'd": ['what', 'did'], + whatd: ['what', 'did'], + // "let's": ['let', 'us'], //too weird + //multiple word contractions + dunno: ['do', 'not', 'know'], + brb: ['be', 'right', 'back'], + gtg: ['got', 'to', 'go'], + irl: ['in', 'real', 'life'], + tbh: ['to', 'be', 'honest'], + imo: ['in', 'my', 'opinion'], + til: ['today', 'i', 'learned'], + rn: ['right', 'now'], + twas: ['it', 'was'], + '@': ['at'] +}; // either 'is not' or 'are not' + +var doAint = function doAint(term, phrase) { + var terms = phrase.terms(); + var index = terms.indexOf(term); + var before = terms.slice(0, index); //look for the preceding noun + + var noun = before.find(function (t) { + return t.tags.Noun; + }); + + if (noun && noun.tags.Plural) { + return ['are', 'not']; + } + + return ['is', 'not']; +}; // + + +var checkIrregulars = function checkIrregulars(term, phrase) { + //this word needs it's own logic: + if (term.clean === "ain't" || term.clean === 'aint') { + return doAint(term, phrase); + } //check white-list + + + if (irregulars$4.hasOwnProperty(term.clean)) { + return irregulars$4[term.clean]; + } + + return null; +}; + +var _03Irregulars = checkIrregulars; + +var hasApostropheS = /([a-z\u00C0-\u00FF]+)'s$/i; +var blacklist = { + that: true, + there: true +}; + +var isPossessive = function isPossessive(term, pool) { + // if we already know it + if (term.tags.Possessive) { + return true; + } //a pronoun can't be possessive - "he's house" + + + if (term.tags.Pronoun || term.tags.QuestionWord) { + return false; + } + + if (blacklist.hasOwnProperty(term.clean)) { + return false; + } //if end of sentence, it is possessive - "was spencer's" + + + var nextTerm = pool.get(term.next); + + if (!nextTerm) { + return true; + } //a gerund suggests 'is walking' + + + if (nextTerm.tags.Verb) { + //fix 'jamie's bite' + if (nextTerm.tags.Infinitive) { + return true; + } + + return false; + } //spencer's house + + + if (nextTerm.tags.Noun) { + return true; + } //rocket's red glare + + + var twoTerm = pool.get(nextTerm.next); + + if (twoTerm && twoTerm.tags.Noun && !twoTerm.tags.Pronoun) { + return true; + } //othwerwise, an adjective suggests 'is good' + + + if (nextTerm.tags.Adjective || nextTerm.tags.Adverb || nextTerm.tags.Verb) { + return false; + } + + return false; +}; + +var isHas = function isHas(term, phrase) { + var terms = phrase.terms(); + var index = terms.indexOf(term); + var after = terms.slice(index + 1, index + 3); //look for a past-tense verb + + return after.find(function (t) { + return t.tags.PastTense; + }); +}; + +var checkPossessive = function checkPossessive(term, phrase, world) { + //the rest of 's + var found = term.text.match(hasApostropheS); + + if (found !== null) { + //spencer's thing vs spencer-is + if (isPossessive(term, phrase.pool) === true) { + term.tag('#Possessive', 'isPossessive', world); + return null; + } //'spencer is' + + + if (found !== null) { + if (isHas(term, phrase)) { + return [found[1], 'has']; + } + + return [found[1], 'is']; + } + } + + return null; +}; + +var _04Possessive = checkPossessive; + +var hasPerfect = /[a-z\u00C0-\u00FF]'d$/; +/** split `i'd` into 'i had', or 'i would' */ + +var checkPerfect = function checkPerfect(term, phrase) { + if (hasPerfect.test(term.clean)) { + var root = term.clean.replace(/'d$/, ''); //look at the next few words + + var terms = phrase.terms(); + var index = terms.indexOf(term); + var after = terms.slice(index + 1, index + 4); //is it before a past-tense verb? - 'i'd walked' + + for (var i = 0; i < after.length; i++) { + var t = after[i]; + + if (t.tags.Verb) { + if (t.tags.PastTense) { + return [root, 'had']; + } + + return [root, 'would']; + } + } //otherwise, 'i'd walk' + + + return [root, 'would']; + } + + return null; +}; + +var _05PerfectTense = checkPerfect; + +var isRange = /^([0-9]+)[-–—]([0-9]+)$/i; //split '2-4' into '2 to 4' + +var checkRange = function checkRange(term) { + if (term.tags.PhoneNumber === true) { + return null; + } + + var parts = term.text.match(isRange); + + if (parts !== null) { + return [parts[1], 'to', parts[2]]; + } + + return null; +}; + +var _06Ranges = checkRange; + +var isNumber = /^[0-9]+$/; + +var createPhrase = function createPhrase(found, doc) { + //create phrase from ['would', 'not'] + var phrase = _01Tokenizer.fromText(found.join(' '), doc.world, doc.pool())[0]; //tag it + + var terms = phrase.terms(); + _01Lexicon(terms, doc.world); //make these terms implicit + + terms.forEach(function (t) { + t.implicit = t.text; + t.text = ''; + t.clean = ''; // remove whitespace for implicit terms + + t.pre = ''; + t.post = ''; // tag number-ranges + + if (isNumber.test(t.implicit)) { + t.tags.Number = true; + t.tags.Cardinal = true; + } + }); + return phrase; +}; + +var contractions = function contractions(doc) { + var world = doc.world; + doc.list.forEach(function (p) { + var terms = p.terms(); + + for (var i = 0; i < terms.length; i += 1) { + var term = terms[i]; + var found = _01Negative(term); + found = found || _02Simple(term); + found = found || _03Irregulars(term, p); + found = found || _04Possessive(term, p, world); + found = found || _05PerfectTense(term, p); + found = found || _06Ranges(term); //add them in + + if (found !== null) { + var newPhrase = createPhrase(found, doc); //set text as contraction + + var firstTerm = newPhrase.terms(0); + firstTerm.text = term.text; //grab sub-phrase to remove + + var match = p.buildFrom(term.id, 1, doc.pool()); + match.replace(newPhrase, doc, true); + } + } + }); + return doc; +}; + +var _03Contractions = contractions; + +//mostly pos-corections here +var miscCorrection = function miscCorrection(doc) { + //misc: + //foot/feet + doc.match('(foot|feet)').tag('Noun', 'foot-noun'); // blood, sweat, and tears + + doc.match('(#Noun && @hasComma) #Noun (and|or) [#PresentTense]').tag('#Noun', 'noun-list'); //3 feet + + doc.match('#Value [(foot|feet)]').tag('Unit', 'foot-unit'); //'u' as pronoun + + doc.match('#Conjunction [u]').tag('Pronoun', 'u-pronoun-2'); //6 am + + doc.match('#Holiday (day|eve)').tag('Holiday', 'holiday-day'); // the captain who + + doc.match('#Noun [(who|whom)]').tag('Determiner', 'captain-who'); //timezones + + doc.match('(standard|daylight|summer|eastern|pacific|central|mountain) standard? time').tag('Time', 'timezone'); //Brazilian pesos + + doc.match('#Demonym #Currency').tag('Currency', 'demonym-currency'); //about to go + + doc.match('[about to] #Adverb? #Verb').tag(['Auxiliary', 'Verb'], 'about-to'); //right of way + + doc.match('(right|rights) of .').tag('Noun', 'right-of'); // a bit + + doc.match('[much] #Adjective').tag('Adverb', 'bit-1'); + doc.match('a [bit]').tag('Noun', 'bit-2'); + doc.match('a bit much').tag('Determiner Adverb Adjective', 'bit-3'); + doc.match('too much').tag('Adverb Adjective', 'bit-4'); // u r cool + + doc.match('u r').tag('Pronoun #Copula', 'u r'); // well, ... + + doc.match('^(well|so|okay)').tag('Expression', 'well-'); // some conditional statements + + var m = doc.clauses(); // had he survived, + + m.match('^had #Noun+ #PastTense').firstTerm().tag('Condition', 'had-he'); // were he to survive + + m.match('^were #Noun+ to #Infinitive').firstTerm().tag('Condition', 'were-he'); //swear-words as non-expression POS + //nsfw + + doc.match('holy (shit|fuck|hell)').tag('Expression', 'swears-expression'); + doc.match('#Determiner [(shit|damn|hell)]').tag('Noun', 'swears-noun'); + doc.match('[(shit|damn|fuck)] (#Determiner|#Possessive|them)').tag('Verb', 'swears-verb'); + doc.match('#Copula fucked up?').not('#Copula').tag('Adjective', 'swears-adjective'); //ambig prepositions/conjunctions + + var so = doc["if"]('so'); + + if (so.found === true) { + //so funny + so.match('[so] #Adjective').tag('Adverb', 'so-adv'); //so the + + so.match('[so] #Noun').tag('Conjunction', 'so-conj'); //do so + + so.match('do [so]').tag('Noun', 'so-noun'); + } + + var all = doc["if"]('all'); + + if (all.found === true) { + //all students + all.match('[all] #Determiner? #Noun').tag('Adjective', 'all-noun'); //it all fell apart + + all.match('[all] #Verb').tag('Adverb', 'all-verb'); + } //the ambiguous word 'that' and 'which' + + + var which = doc["if"]('which'); + + if (which.found === true) { + //remind john that + which.match('#Verb #Adverb? #Noun [(that|which)]').tag('Preposition', 'that-prep'); //that car goes + + which.match('that #Noun [#Verb]').tag('Determiner', 'that-determiner'); //work, which has been done. + + which.match('@hasComma [which] (#Pronoun|#Verb)').tag('Preposition', 'which-copula'); + } //like + + + var like = doc["if"]('like'); + + if (like.found === true) { + like.match('just [like]').tag('Preposition', 'like-preposition'); //folks like her + + like.match('#Noun [like] #Noun').tag('Preposition', 'noun-like'); //look like + + like.match('#Verb [like]').tag('Adverb', 'verb-like'); //exactly like + + like.match('#Adverb like').notIf('(really|generally|typically|usually|sometimes|often) [like]').tag('Adverb', 'adverb-like'); + } + + var title = doc["if"]('@titleCase'); + + if (title.found === true) { + //FitBit Inc + title.match('@titleCase (ltd|co|inc|dept|assn|bros)').tag('Organization', 'org-abbrv'); //Foo District + + title.match('@titleCase+ (district|region|province|county|prefecture|municipality|territory|burough|reservation)').tag('Region', 'foo-district'); //District of Foo + + title.match('(district|region|province|municipality|territory|burough|state) of @titleCase').tag('Region', 'district-of-Foo'); + } + + var hyph = doc["if"]('@hasHyphen'); + + if (hyph.found === true) { + //air-flow + hyph.match('@hasHyphen .').match('#Noun #Verb').tag('Noun', 'hyphen-verb'); //connect hyphenated expressions - 'ooh-wee' + + hyph["if"]('#Expression').match('@hasHyphen+').tag('Expression', 'ooh-wee'); + } + + var place = doc["if"]('#Place'); + + if (place.found === true) { + //West Norforlk + place.match('(west|north|south|east|western|northern|southern|eastern)+ #Place').tag('Region', 'west-norfolk'); //some us-state acronyms (exlude: al, in, la, mo, hi, me, md, ok..) + + place.match('#City [#Acronym]').match('(al|ak|az|ar|ca|ct|dc|fl|ga|id|il|nv|nh|nj|ny|oh|or|pa|sc|tn|tx|ut|vt|pr)').tag('Region', 'us-state'); + } + + return doc; +}; + +var fixMisc = miscCorrection; + +//Determiner-signals +var fixThe = function fixThe(doc) { + var det = doc["if"]('#Determiner'); + + if (det.found === true) { + var adj = det["if"]('#Adjective'); + + if (adj.found) { + //the nice swim + adj.match('(the|this|those|these) #Adjective [#Verb]').tag('Noun', 'the-adj-verb'); // the truly nice swim + + adj.match('(the|this|those|these) #Adverb #Adjective [#Verb]').tag('Noun', 'correction-determiner4'); //the orange is + + adj.match('#Determiner [#Adjective] (#Copula|#PastTense|#Auxiliary)').tag('Noun', 'the-adj-2'); //the orange. + + adj.match('#Determiner #Adjective$').notIf('(#Comparative|#Superlative)').terms(1).tag('Noun', 'the-adj-1'); + } + + var inf = det["if"]('#Infinitive'); + + if (inf.found) { + // a stream runs + inf.match('(the|this|a|an) [#Infinitive] #Adverb? #Verb').tag('Noun', 'correction-determiner5'); //the test string + + inf.match('#Determiner [#Infinitive] #Noun').tag('Noun', 'correction-determiner7'); //by a bear. + + inf.match('#Determiner [#Infinitive]$').tag('Noun', 'a-inf'); + } //the wait to vote + + + det.match('(the|this) [#Verb] #Preposition .').tag('Noun', 'correction-determiner1'); //a sense of + + det.match('#Determiner [#Verb] of').tag('Noun', 'the-verb-of'); //the threat of force + + det.match('#Determiner #Noun of [#Verb]').tag('Noun', 'noun-of-noun'); //a close + + det.match('#Determiner #Adverb? [close]').tag('Adjective', 'a-close'); //the western line + + det.match('#Determiner [(western|eastern|northern|southern|central)] #Noun').tag('Noun', 'western-line'); //the swim + + det.match('(the|those|these) [(#Infinitive|#PresentTense|#PastTense)]').tag('Noun', 'correction-determiner2'); + } + + var an = doc["if"]('(a|an)'); + + if (an.found === true) { + //a staggering cost + an.match('(a|an) [#Gerund]').tag('Adjective', 'correction-a|an'); //did a 900, paid a 20 + + an.match('#Verb (a|an) [#Value]').tag('Singular', 'a-value'); //a tv show + + an.match('(a|an) #Noun [#Infinitive]').tag('Noun', 'a-noun-inf'); //a great run + + an.match('(a|an) #Adjective (#Infinitive|#PresentTense)').terms(2).tag('Noun', 'correction-a|an2'); //'a/an' can mean 1 - "a hour" + + an.match('[(a|an)] (#Duration|hundred|thousand|million|billion|trillion)').ifNo('#Plural').tag('Value', 'a-is-one'); + } + + return doc; +}; + +var fixThe_1 = fixThe; + +// +var fixNouns = function fixNouns(doc) { + var noun = doc["if"]('#Noun'); + + if (noun.found === true) { + //'more' is not always an adverb + noun.match('more #Noun').tag('Noun', 'more-noun'); //he quickly foo + + noun.match('#Noun #Adverb [#Noun]').tag('Verb', 'quickly-foo'); //fix for busted-up phrasalVerbs + + noun.match('#Noun [#Particle]').tag('Preposition', 'repair-noPhrasal'); //John & Joe's + + noun.match('#Noun (&|n) #Noun').tag('Organization', 'Noun-&-Noun'); //Aircraft designer + + noun.match('#Noun #Actor').tag('Actor', 'thing-doer'); //j.k Rowling + + doc.match('#Noun van der? #Noun').tagSafe('#Person', 'von der noun'); //king of spain + + doc.match('(king|queen|prince|saint|lady) of? #Noun').tagSafe('#Person', 'king-of-noun'); // addresses + + doc.match('#Value #Noun (st|street|rd|road|crescent|cr|way|tr|terrace|avenue|ave)').tag('Address'); // schools + + doc.match('#Noun+ (public|private) school').tag('School'); //the word 'second' + + noun.match('[second] #Noun').notIf('#Honorific').unTag('Unit').tag('Ordinal', 'second-noun'); //linear algebra + + noun.match('(#Determiner|#Value) [(linear|binary|mobile|lexical|technical|computer|scientific|formal)] #Noun').tag('Noun', 'technical-noun'); //organization + + var org = noun["if"]('#Organization'); + + if (org.found === true) { + org.match('#Organization of the? @titleCase').tagSafe('Organization', 'org-of-place'); + org.match('#Organization #Country').tag('Organization', 'org-country'); + org.match('(world|global|international|national|#Demonym) #Organization').tag('Organization', 'global-org'); + org.match('#TitleCase #Organization').ifNo('@hasComma').tag('Organization', 'titlecase-org'); + } + + var plural = noun["if"]('#Plural'); + + if (plural.found === true) { + //some pressing issues + plural.match('some [#Verb] #Plural').tag('Noun', 'correction-determiner6'); //this rocks + + noun.match('(this|that) [#Plural]').tag('PresentTense', 'this-verbs'); + } + } //acronyms + + + var acronym = doc["if"]('#Acronym'); + + if (acronym.found === true) { + acronym.match('the [#Acronym]').notIf('(iou|fomo|yolo|diy|dui|nimby)').tag('Organization', 'the-acronym'); + acronym.match('#Acronym').match('#Possessive').tag('Organization', 'possessive-acronym'); + } //possessives + + + var poss = doc["if"]('#Possessive'); + + if (poss.found === true) { + //my buddy + poss.match('#Possessive [#FirstName]').unTag('Person', 'possessive-name'); //spencer kelly's + + poss.match('#FirstName #Acronym? #Possessive').ifNo('@hasComma').match('#FirstName #Acronym? #LastName').tag('Possessive'); //Super Corp's fundraiser + + poss.match('#Organization+ #Possessive').ifNo('@hasComma').tag('Possessive'); //Los Angeles's fundraiser + + poss.match('#Place+ #Possessive').ifNo('@hasComma').tag('Possessive'); //her polling + + poss.match('#Possessive [#Verb]').tag('Noun', 'correction-possessive'); + } + + return doc; +}; + +var fixNouns_1 = fixNouns; + +var maybeNoun = '(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)'; +var maybeVerb = '(pat|wade|ollie|will|rob|buck|bob|mark|jack)'; +var maybeAdj = '(misty|rusty|dusty|rich|randy)'; +var maybeDate = '(april|june|may|jan|august|eve)'; +var maybePlace = '(paris|alexandria|houston|kobe|salvador|sydney)'; + +var fixPerson = function fixPerson(doc) { + // clues from honorifics + var hon = doc["if"]('#Honorific'); + + if (hon.found === true) { + //mr Putin + doc.match('(mr|mrs|ms|dr) (#TitleCase|#Possessive)+').tag('#Person', 'mr-putin'); //mr X + + hon.match('#Honorific #Acronym').tag('Person', 'Honorific-TitleCase'); //remove single 'mr' + + hon.match('^#Honorific$').unTag('Person', 'single-honorific'); //first general.. + + hon.match('[(1st|2nd|first|second)] #Honorific').tag('Honorific', 'ordinal-honorific'); + } //methods requiring a titlecase + + + var title = doc["if"]('#TitleCase'); + + if (title.found === true) { + title.match('#Acronym #TitleCase').tagSafe('#Person', 'acronym-titlecase'); //ludwig van beethovan + + title.match('#TitleCase (van|al|bin) #TitleCase').tagSafe('Person', 'titlecase-van-titlecase'); //jose de Sucre + + title.match('#TitleCase (de|du) la? #TitleCase').tagSafe('Person', 'titlecase-van-titlecase'); //pope francis + + title.match('(lady|queen|sister) #TitleCase').ifNo('#Date').ifNo('#Honorific').tag('#FemaleName', 'lady-titlecase'); + title.match('(king|pope|father) #TitleCase').ifNo('#Date').tag('#MaleName', 'poe'); // jean Foobar + + title.match(maybeNoun + ' #Acronym? #TitleCase').tagSafe('Person', 'ray-smith'); // rob Foobar + + title.match(maybeVerb + ' #Acronym? #TitleCase').tag('Person', 'rob-smith'); // rusty Foobar + + title.match(maybeAdj + ' #Acronym? #TitleCase').tag('Person', 'rusty-smith'); // june Foobar + + title.match(maybeDate + ' #Acronym? (#TitleCase && !#Month)').tagSafe('Person', 'june-smith'); + } + + var person = doc["if"]('#Person'); + + if (person.found === true) { + //Frank jr + person.match('#Person (jr|sr|md)').tag('Person', 'person-honorific'); //peter II + + person.match('#Person #Person the? #RomanNumeral').tag('Person', 'roman-numeral'); //'Professor Fink', 'General McCarthy' + + person.match('#Honorific #Person').tag('Person', 'Honorific-Person'); // 'john E rockefeller' + + person.match('#FirstName [/^[^aiurck]$/]').tag(['Acronym', 'Person'], 'john-e'); //Doctor john smith jr + + person.match('#Honorific #Person').tag('Person', 'honorific-person'); //general pearson + + person.match('[(private|general|major|corporal|lord|lady|secretary|premier)] #Honorific? #Person').tag('Honorific', 'ambg-honorifics'); //Morgan Shlkjsfne + + title.match('#Person #TitleCase').match('#TitleCase #Noun').tagSafe('Person', 'person-titlecase'); //a bunch of ambiguous first names + //Nouns: 'viola' or 'sky' + + var ambigNoun = person["if"](maybeNoun); + + if (ambigNoun.found === true) { + // ambigNoun.match('(#Determiner|#Adverb|#Pronoun|#Possessive) [' + maybeNoun + ']').tag('Noun', 'the-ray') + ambigNoun.match(maybeNoun + ' #Person').tagSafe('Person', 'ray-smith'); + } //Verbs: 'pat' or 'wade' + + + var ambigVerb = person["if"](maybeVerb); + + if (ambigVerb === true) { + ambigVerb.match('(#Modal|#Adverb) [' + maybeVerb + ']').tag('Verb', 'would-mark'); + ambigVerb.match(maybeVerb + ' #Person').tag('Person', 'rob-smith'); + } //Adjectives: 'rusty' or 'rich' + + + var ambigAdj = person["if"](maybeAdj); + + if (ambigAdj.found === true) { + ambigAdj.match('#Adverb [' + maybeAdj + ']').tag('Adjective', 'really-rich'); + ambigAdj.match(maybeAdj + ' #Person').tag('Person', 'randy-smith'); + } //Dates: 'june' or 'may' + + + var ambigDate = person["if"](maybeDate); + + if (ambigDate.found === true) { + ambigDate.match(String(maybeDate) + ' #Person').tagSafe('Person', 'june-smith'); + ambigDate.match('(in|during|on|by|before|#Date) [' + maybeDate + ']').tagSafe('Date', 'in-june'); + ambigDate.match(maybeDate + ' (#Date|#Value)').tagSafe('Date', 'june-5th'); + } //Places: paris or syndey + + + var ambigPlace = person["if"](maybePlace); + + if (ambigPlace.found === true) { + ambigPlace.match('(in|near|at|from|to|#Place) [' + maybePlace + ']').tagSafe('Place', 'in-paris'); + ambigPlace.match('[' + maybePlace + '] #Place').tagSafe('Place', 'paris-france'); // ambigPlace.match('[' + maybePlace + '] #Person').tagSafe('Person', 'paris-hilton') + } //this one is tricky + + + var al = person["if"]('al'); + + if (al.found === true) { + al.match('al (#Person|#TitleCase)').tagSafe('#Person', 'al-borlen'); + al.match('#TitleCase al #TitleCase').tagSafe('#Person', 'arabic-al-arabic'); + } + + var firstName = person["if"]('#FirstName'); + + if (firstName.found === true) { + //ferdinand de almar + firstName.match('#FirstName de #Noun').tag('#Person', 'firstname-de-noun'); //Osama bin Laden + + firstName.match('#FirstName (bin|al) #Noun').tag('#Person', 'firstname-al-noun'); //John L. Foo + + firstName.match('#FirstName #Acronym #TitleCase').tag('Person', 'firstname-acronym-titlecase'); //Andrew Lloyd Webber + + firstName.match('#FirstName #FirstName #TitleCase').tag('Person', 'firstname-firstname-titlecase'); //Mr Foo + + firstName.match('#Honorific #FirstName? #TitleCase').tag('Person', 'Honorific-TitleCase'); //peter the great + + firstName.match('#FirstName the #Adjective').tag('Person', 'determiner5'); //very common-but-ambiguous lastnames + + firstName.match('#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)').tag('#Person', 'firstname-maybe'); //John Foo + + firstName.match('#FirstName #TitleCase #TitleCase?').match('#Noun+').tag('Person', 'firstname-titlecase'); //Joe K. Sombrero + + firstName.match('#FirstName #Acronym #Noun').ifNo('#Date').tag('#Person', 'n-acro-noun').lastTerm().tag('#LastName', 'n-acro-noun'); // Dwayne 'the rock' Johnson + + firstName.match('#FirstName [#Determiner #Noun] #LastName').tag('#NickName', 'first-noun-last').tag('#Person', 'first-noun-last'); //john bodego's + + firstName.match('#FirstName (#Singular|#Possessive)').ifNo('(#Date|#Pronoun|#NickName)').tag('#Person', 'first-possessive').lastTerm().tag('#LastName', 'first-possessive'); // Firstname x (dangerous) + + var tmp = firstName.match('#FirstName (#Noun|#TitleCase)').ifNo('^#Possessive').ifNo('#ClauseEnd .').ifNo('#Pronoun'); + tmp.lastTerm().tag('#LastName', 'firstname-noun'); + } + + var lastName = person["if"]('#LastName'); + + if (lastName.found === true) { + //is foo Smith + lastName.match('#Copula [(#Noun|#PresentTense)] #LastName').tag('#FirstName', 'copula-noun-lastname'); // x Lastname + + lastName.match('[#Noun] #LastName').canBe('#FirstName').tag('#FirstName', 'noun-lastname'); //ambiguous-but-common firstnames + + lastName.match('[(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill)] #LastName').tag('#FirstName', 'maybe-lastname'); //Jani K. Smith + + lastName.match('(#TitleCase|#Singular) #Acronym? #LastName').ifNo('#Date').tag('#Person', 'title-acro-noun').lastTerm().tag('#LastName', 'title-acro-noun'); + } + } + + return doc; +}; + +var fixPerson_1 = fixPerson; + +var advb = '(#Adverb|not)+?'; // + +var fixVerb = function fixVerb(doc) { + var vb = doc["if"]('#Verb'); + + if (vb.found) { + vb.match('[(do|does|will|have|had)] (not|#Adverb)? #Verb').tag('Auxiliary', 'have-had'); //still make + + vb.match('[still] #Verb').tag('Adverb', 'still-verb'); //'u' as pronoun + + vb.match('[u] #Verb').tag('Pronoun', 'u-pronoun-1'); //is no walk + + vb.match('is no [#Verb]').tag('Noun', 'is-no-verb'); //different views than + + vb.match('[#Verb] than').tag('Noun', 'correction'); // smoked poutine is + + vb.match('[#PastTense] #Singular is').tag('#Adjective', 'smoked-poutine'); // baked onions are + + vb.match('[#PastTense] #Plural are').tag('#Adjective', 'baked-onions'); // goes to sleep + + vb.match('(go|goes|went) to [#Infinitive]').tag('#Noun', 'goes-to-verb'); //there are reasons + + vb.match('there (are|were) #Adjective? [#PresentTense]').tag('Plural', 'there-are'); //jack seems guarded + + vb.match('#Singular (seems|appears) #Adverb? [#PastTense$]').tag('Adjective', 'seems-filled'); //fall over + + vb.match('#PhrasalVerb [#PhrasalVerb]').tag('Particle', 'phrasal-particle'); //went to sleep + // vb.match('#Verb to #Verb').lastTerm().tag('Noun', 'verb-to-verb'); + //been walking + + vb.match("(be|been) ".concat(advb, " #Gerund")).not('#Verb$').tag('Auxiliary', 'be-walking'); // directive verb - 'use reverse' + + vb.match('(try|use|attempt|build|make) #Verb').ifNo('(@hasComma|#Negative|#Copula|will|be)').lastTerm().tag('#Noun', 'do-verb'); //infinitive verbs suggest plural nouns - 'XYZ walk to the store' + // r.match(`#Singular+ #Infinitive`).match('#Singular+').tag('Plural', 'infinitive-make-plural'); + + var modal = vb["if"]('(#Modal|did|had|has)'); + + if (modal.found === true) { + //support a splattering of auxillaries before a verb + modal.match("(has|had) ".concat(advb, " #PastTense")).not('#Verb$').tag('Auxiliary', 'had-walked'); //would walk + + modal.match("(#Modal|did) ".concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'modal-verb'); //would have had + + modal.match("#Modal ".concat(advb, " have ").concat(advb, " had ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-have'); //would be walking + + modal.match("#Modal ".concat(advb, " be ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-be'); //would been walking + + modal.match("(#Modal|had|has) ".concat(advb, " been ").concat(advb, " #Verb")).not('#Verb$').tag('Auxiliary', 'would-be'); + } + + var copula = vb["if"]('#Copula'); + + if (copula.found === true) { + //was walking + copula.match("#Copula ".concat(advb, " #Gerund")).not('#Verb$').tag('Auxiliary', 'copula-walking'); //is mark hughes + + copula.match('#Copula [#Infinitive] #Noun').tag('Noun', 'is-pres-noun'); // + + copula.match('[#Infinitive] #Copula').tag('Noun', 'inf-copula'); //sometimes not-adverbs + + copula.match('#Copula [(just|alone)]$').tag('Adjective', 'not-adverb'); //jack is guarded + + copula.match('#Singular is #Adverb? [#PastTense$]').tag('Adjective', 'is-filled'); //is eager to go + + copula.match('#Copula [#Adjective to] #Verb').tag('Verb', 'adj-to'); //sometimes adverbs - 'pretty good','well above' + + copula.match('#Copula (pretty|dead|full|well) (#Adjective|#Noun)').ifNo('@hasComma').tag('#Copula #Adverb #Adjective', 'sometimes-adverb'); + } //Gerund - 'walking' + + + var gerund = vb["if"]('#Gerund'); + + if (gerund.found === true) { + //walking is cool + gerund.match('[#Gerund] #Adverb? not? #Copula').tag('Activity', 'gerund-copula'); //walking should be fun + + gerund.match('[#Gerund] #Modal').tag('Activity', 'gerund-modal'); //running-a-show + + gerund.match('#Gerund #Determiner [#Infinitive]').tag('Noun', 'running-a-show'); //setting records + // doc.match('#Gerund [#PresentTense]').tag('Plural', 'setting-records'); + } //'will be' + + + var willBe = vb["if"]('will #Adverb? not? #Adverb? be'); + + if (willBe.found === true) { + //will be running (not copula + if (willBe.has('will #Adverb? not? #Adverb? be #Gerund') === false) { + //tag it all + willBe.match('will not? be').tag('Copula', 'will-be-copula'); //for more complex forms, just tag 'be' + + willBe.match('will #Adverb? not? #Adverb? be #Adjective').match('be').tag('Copula', 'be-copula'); + } + } + } //question words + + + var m = doc["if"]('(who|what|where|why|how|when)'); + + if (m.found) { + //the word 'how' + m.match('^how').tag('QuestionWord', 'how-question'); + m.match('[how] (#Determiner|#Copula|#Modal|#PastTense)').tag('QuestionWord', 'how-is'); // //the word 'which' + + m.match('^which').tag('QuestionWord', 'which-question'); + m.match('[which] . (#Noun)+ #Pronoun').tag('QuestionWord', 'which-question2'); + m.match('which').tag('QuestionWord', 'which-question3'); //how he is driving + + m.match('[#QuestionWord] #Noun #Copula #Adverb? (#Verb|#Adjective)').unTag('QuestionWord').tag('Conjunction', 'how-he-is-x'); //when i go fishing + + m.match('#QuestionWord #Noun #Adverb? #Infinitive not? #Gerund').unTag('QuestionWord').tag('Conjunction', 'when i go fishing'); + } + + return doc; +}; + +var fixVerb_1 = fixVerb; + +// +var fixAdjective = function fixAdjective(doc) { + var adj = doc["if"]('#Adjective'); + + if (adj.found) { + //still good + adj.match('[still] #Adjective').tag('Adverb', 'still-advb'); //barely even walk + + adj.match('(barely|hardly) even').tag('#Adverb', 'barely-even'); //big dreams, critical thinking + + adj.match('#Adjective [#PresentTense]').tag('Noun', 'adj-presentTense'); //will secure our + + adj.match('will [#Adjective]').tag('Verb', 'will-adj'); //cheering hard - dropped -ly's + + adj.match('#PresentTense [(hard|quick|long|bright|slow)]').tag('Adverb', 'lazy-ly'); //his fine + + adj.match('(his|her|its) [#Adjective]').tag('Noun', 'his-fine'); //he left + + adj.match('#Noun #Adverb? [left]').tag('PastTense', 'left-verb'); //he disguised the thing + + adj.match('#Pronoun [#Adjective] #Determiner #Adjective? #Noun').tag('Verb', 'he-adj-the'); + } + + return doc; +}; + +var fixAdjective_1 = fixAdjective; + +var units = '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)'; // + +var fixValue = function fixValue(doc) { + var val = doc["if"]('#Value'); + + if (val.found === true) { + //1 800 PhoneNumber + val.match('1 #Value #PhoneNumber').tag('PhoneNumber', '1-800-Value'); //(454) 232-9873 + + val.match('#NumericValue #PhoneNumber').tag('PhoneNumber', '(800) PhoneNumber'); //three trains + + val.match('#Value [#PresentTense]').tag('Plural', 'value-presentTense'); //money + + var m = val.match('#Value+ #Currency'); + m.lastTerm().tag('Unit', 'money-unit'); + m.match('#Value+').tag('Money', 'value-currency'); + } //5 kg. + + + val.match('#Value #Abbreviation').tag('Value', 'value-abbr'); //seven point five + + val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value'); //minus 7 + + val.match('(minus|negative) #Value').tag('Value', 'minus-value'); // ten grand + + val.match('#Value grand').tag('Value', 'value-grand'); //quarter million + + val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal'); //eg 'trillion' + + var mult = val["if"](units); + + if (mult.found === true) { + mult.match('a #Value').tag('Value', 'a-value'); //? + // mult.match('#Ordinal (half|quarter)').tag('Value', 'ordinal-half');//not ready + + mult.match("".concat(units, " and #Value")).tag('Value', 'magnitude-and-value'); + } + + return doc; +}; + +var fixValue_1 = fixValue; + +var preps = '(in|by|before|during|on|until|after|of|within|all)'; //6 + +var people = '(january|april|may|june|summer|autumn|jan|sep)'; //ambiguous month-names + +var verbs$2 = '(may|march)'; //ambiguous month-verbs + +var fixDates = function fixDates(doc) { + //ambiguous month - person forms + var person = doc["if"](people); + + if (person.found === true) { + //give to april + person.match("#Infinitive #Determiner? #Adjective? #Noun? (to|for) [".concat(people, "]")).tag('Person', 'ambig-person'); //remind june + + person.match("#Infinitive [".concat(people, "]")).tag('Person', 'infinitive-person'); //may waits for + + person.match("[".concat(people, "] #PresentTense (to|for)")).tag('Person', 'ambig-active'); //april will + + person.match("[".concat(people, "] #Modal")).tag('Person', 'ambig-modal'); //would april + + person.match("#Modal [".concat(people, "]")).tag('Person', 'modal-ambig'); //with april + + person.match("(that|with|for) [".concat(people, "]")).tag('Person', 'that-month'); //it is may + + person.match("#Copula [".concat(people, "]")).tag('Person', 'is-may'); //may is + + person.match("[".concat(people, "] #Copula")).tag('Person', 'may-is'); //april the 5th + + person.match("[".concat(people, "] the? #Value")).tag('Month', 'person-value'); //wednesday april + + person.match("#Date [".concat(people, "]")).tag('Month', 'correction-may'); //may 5th + + person.match("[".concat(people, "] the? #Value")).tag('Month', 'may-5th'); //5th of may + + person.match("#Value of [".concat(people, "]")).tag('Month', '5th-of-may'); //by april + + person.match("".concat(preps, " [").concat(people, "]")).ifNo('#Holiday').tag('Month', 'preps-month'); //this april + + person.match("(next|this|last) [".concat(people, "]")).tag('Month', 'correction-may'); //maybe not 'this' + } //ambiguous month - verb-forms + + + var verb = doc["if"](verbs$2); + + if (verb.found === true) { + //quickly march + verb.match("#Adverb [".concat(verbs$2, "]")).tag('Infinitive', 'ambig-verb'); + verb.match("".concat(verbs$2, " [#Adverb]")).tag('Infinitive', 'ambig-verb'); //all march + + verb.match("".concat(preps, " [").concat(verbs$2, "]")).tag('Month', 'in-month'); //this march + + verb.match("(next|this|last) [".concat(verbs$2, "]")).tag('Month', 'this-month'); //with date + + verb.match("[".concat(verbs$2, "] the? #Value")).tag('Month', 'march-5th'); + verb.match("#Value of? [".concat(verbs$2, "]")).tag('Month', '5th-of-march'); //nearby + + verb.match("[".concat(verbs$2, "] .? #Date")).tag('Month', 'march-and-feb'); + verb.match("#Date .? [".concat(verbs$2, "]")).tag('Month', 'feb-and-march'); + var march = doc["if"]('march'); + + if (march.found === true) { + //march to + march.match('[march] (up|down|back|to|toward)').tag('Infinitive', 'march-to'); //must march + + march.match('#Modal [march]').tag('Infinitive', 'must-march'); + } + } //sun 5th + + + var sun = doc["if"]('sun'); + + if (sun.found === true) { + //sun feb 2 + sun.match('[sun] #Date').tag('WeekDay', 'sun-feb'); //sun the 5th + + sun.match('sun the #Ordinal').tag('Date').firstTerm().tag('WeekDay', 'sun-the-5th'); //the sun + + sun.match('#Determiner [sun]').tag('Singular', 'the-sun'); + } //sat, nov 5th + + + var sat = doc["if"]('sat'); + + if (sat.found) { + //sat november + sat.match('[sat] #Date').tag('WeekDay', 'sat-feb'); //this sat + + sat.match("".concat(preps, " [sat]")).tag('WeekDay', 'sat'); + } //months: + + + var month = doc["if"]('#Month'); + + if (month.found === true) { + //June 5-7th + month.match("#Month #DateRange+").tag('Date', 'correction-numberRange'); //5th of March + + month.match('#Value of #Month').tag('Date', 'value-of-month'); //5 March + + month.match('#Cardinal #Month').tag('Date', 'cardinal-month'); //march 5 to 7 + + month.match('#Month #Value to #Value').tag('Date', 'value-to-value'); //march the 12th + + month.match('#Month the #Value').tag('Date', 'month-the-value'); + } //months: + + + var val = doc["if"]('#Value'); + + if (val.found === true) { + //values + val.match('#Value #Abbreviation').tag('Value', 'value-abbr'); //seven point five + + val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value'); //minus 7 + + val.match('(minus|negative) #Value').tag('Value', 'minus-value'); // ten grand + + val.match('#Value grand').tag('Value', 'value-grand'); //quarter million + + val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal'); //june 7 + + val.match('(#WeekDay|#Month) #Value').ifNo('#Money').tag('Date', 'date-value'); //7 june + + val.match('#Value (#WeekDay|#Month)').ifNo('#Money').tag('Date', 'value-date'); //may twenty five + + val.match('#TextValue #TextValue')["if"]('#Date').tag('#Date', 'textvalue-date'); + } + + return doc; +}; + +var fixDates_1 = fixDates; + +// verb: 100.828ms +// dates: 80.874ms +// person: 66.054ms +// nouns: 51.340ms +// adj: 19.760ms +// value: 12.950ms +// misc: 43.359ms +//sequence of match-tag statements to correct mis-tags + +var corrections = function corrections(doc) { + // console.time('det') + fixThe_1(doc); //27 + // console.timeEnd('det') + // console.time('nouns') + + fixNouns_1(doc); //30 + // // console.timeEnd('nouns') + // // console.time('person') + + fixPerson_1(doc); //58 + // // console.timeEnd('person') + // // console.time('verb') + + fixVerb_1(doc); //50 + // // console.timeEnd('verb') + // // console.time('adj') + + fixAdjective_1(doc); //8 + // // console.timeEnd('adj') + // // console.time('value') + + fixValue_1(doc); //12 + // // console.timeEnd('value') + // // console.time('dates') + + fixDates_1(doc); //92 + // // console.timeEnd('dates') + // // console.time('misc') + + fixMisc(doc); //43 + // console.timeEnd('misc') + + return doc; +}; + +var _04Correction = corrections; + +/** POS-tag all terms in this document */ + +var tagger = function tagger(doc) { + var terms = doc.termList(); // check against any known-words + + doc = _01Init(doc); // everything has gotta be something. ¯\_(:/)_/¯ + + doc = _02Fallbacks(doc); // support "didn't" & "spencer's" + + doc = _03Contractions(doc); //set our cache, to speed things up + + doc.cache(); // wiggle-around the results, so they make more sense + + doc = _04Correction(doc); //remove our cache + // doc.uncache() + // run any user-given tagger functions + + doc.world.taggers.forEach(function (fn) { + fn(doc); + }); + return doc; +}; + +var _02Tagger = tagger; + +var addMethod = function addMethod(Doc) { + /** */ + var Abbreviations = + /*#__PURE__*/ + function (_Doc) { + _inherits(Abbreviations, _Doc); + + function Abbreviations() { + _classCallCheck(this, Abbreviations); + + return _possibleConstructorReturn(this, _getPrototypeOf(Abbreviations).apply(this, arguments)); + } + + _createClass(Abbreviations, [{ + key: "stripPeriods", + value: function stripPeriods() { + this.termList().forEach(function (t) { + if (t.tags.Abbreviation === true && t.next) { + t.post = t.post.replace(/^\./, ''); + } + + var str = t.text.replace(/\./, ''); + t.set(str); + }); + return this; + } + }, { + key: "addPeriods", + value: function addPeriods() { + this.termList().forEach(function (t) { + t.post = t.post.replace(/^\./, ''); + t.post = '.' + t.post; + }); + return this; + } + }]); + + return Abbreviations; + }(Doc); + + Abbreviations.prototype.unwrap = Abbreviations.prototype.stripPeriods; + + Doc.prototype.abbreviations = function (n) { + var match = this.match('#Abbreviation'); + + if (typeof n === 'number') { + match = match.get(n); + } + + return new Abbreviations(match.list, this, this.world); + }; + + return Doc; +}; + +var Abbreviations = addMethod; + +var addMethod$1 = function addMethod(Doc) { + /** */ + var Acronyms = + /*#__PURE__*/ + function (_Doc) { + _inherits(Acronyms, _Doc); + + function Acronyms() { + _classCallCheck(this, Acronyms); + + return _possibleConstructorReturn(this, _getPrototypeOf(Acronyms).apply(this, arguments)); + } + + _createClass(Acronyms, [{ + key: "stripPeriods", + value: function stripPeriods() { + this.termList().forEach(function (t) { + var str = t.text.replace(/\./g, ''); + t.set(str); + }); + return this; + } + }, { + key: "addPeriods", + value: function addPeriods() { + this.termList().forEach(function (t) { + var str = t.text.replace(/\./g, ''); + str = str.split('').join('.'); + t.set(str); + }); + return this; + } + }]); + + return Acronyms; + }(Doc); + + Acronyms.prototype.unwrap = Acronyms.prototype.stripPeriods; + Acronyms.prototype.strip = Acronyms.prototype.stripPeriods; + + Doc.prototype.acronyms = function (n) { + var match = this.match('#Acronym'); + + if (typeof n === 'number') { + match = match.get(n); + } + + return new Acronyms(match.list, this, this.world); + }; + + return Doc; +}; + +var Acronyms = addMethod$1; + +var addMethod$2 = function addMethod(Doc) { + /** split into approximate sub-sentence phrases */ + Doc.prototype.clauses = function (n) { + // an awkward way to disambiguate a comma use + var commas = this["if"]('@hasComma').notIf('@hasComma @hasComma') //fun, cool... + .notIf('@hasComma . .? (and|or) .') //cool, and fun + .notIf('(#City && @hasComma) #Country') //'toronto, canada' + .notIf('(#Date && @hasComma) #Year') //'july 6, 1992' + .notIf('@hasComma (too|also)$') //at end of sentence + .match('@hasComma'); + var found = this.splitAfter(commas); + var quotes = found.quotations(); + found = found.splitOn(quotes); + var parentheses = found.parentheses(); + found = found.splitOn(parentheses); // it is cool and it is .. + + var conjunctions = found["if"]('#Copula #Adjective #Conjunction (#Pronoun|#Determiner) #Verb').match('#Conjunction'); + found = found.splitBefore(conjunctions); // if it is this then that + + var condition = found["if"]('if .{2,9} then .').match('then'); + found = found.splitBefore(condition); // misc clause partitions + + found = found.splitBefore('as well as .'); + found = found.splitBefore('such as .'); + found = found.splitBefore('in addition to .'); // semicolons, dashes + + found = found.splitAfter('@hasSemicolon'); + found = found.splitAfter('@hasDash'); // does there appear to have relative/subordinate clause still? + + var tooLong = found.filter(function (d) { + return d.wordCount() > 5 && d.match('#Verb+').length >= 2; + }); + + if (tooLong.found) { + var m = tooLong.splitAfter('#Noun .* #Verb .* #Noun+'); + found = found.splitOn(m.eq(0)); + } + + if (typeof n === 'number') { + found = found.get(n); + } + + return new Doc(found.list, this, this.world); + }; + + return Doc; +}; + +var Clauses = addMethod$2; + +var addMethod$3 = function addMethod(Doc) { + /** */ + var Contractions = + /*#__PURE__*/ + function (_Doc) { + _inherits(Contractions, _Doc); + + function Contractions(list, from, world) { + var _this; + + _classCallCheck(this, Contractions); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Contractions).call(this, list, from, world)); + _this.contracted = null; + return _this; + } + /** turn didn't into 'did not' */ + + + _createClass(Contractions, [{ + key: "expand", + value: function expand() { + this.list.forEach(function (p) { + var terms = p.terms(); //change the case? + + var isTitlecase = terms[0].isTitleCase(); + terms.forEach(function (t, i) { + //use the implicit text + // console.log(t.clean) + t.set(t.implicit || t.text); + t.implicit = undefined; //add whitespace + + if (i < terms.length - 1 && t.post === '') { + t.post += ' '; + } + }); //set titlecase + + if (isTitlecase) { + terms[0].toTitleCase(); + } + }); + return this; + } + }]); + + return Contractions; + }(Doc); //find contractable, expanded-contractions + // const findExpanded = r => { + // let remain = r.not('#Contraction') + // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)') + // m.concat(remain.match('(they|we|you|i) have')) + // m.concat(remain.match('i am')) + // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')) + // return m + // } + + + Doc.prototype.contractions = function (n) { + //find currently-contracted + var found = this.match('@hasContraction+'); //(may want to split these up) + //todo: split consecutive contractions + + if (typeof n === 'number') { + found = found.get(n); + } + + return new Contractions(found.list, this, this.world); + }; //aliases + + + Doc.prototype.expanded = Doc.prototype.isExpanded; + Doc.prototype.contracted = Doc.prototype.isContracted; + return Doc; +}; + +var Contractions = addMethod$3; + +var addMethod$4 = function addMethod(Doc) { + //pull it apart.. + var parse = function parse(doc) { + var things = doc.splitAfter('@hasComma').not('(and|or) not?'); + var beforeLast = doc.match('[.] (and|or)'); + return { + things: things, + conjunction: doc.match('(and|or) not?'), + beforeLast: beforeLast, + hasOxford: beforeLast.has('@hasComma') + }; + }; + /** cool, fun, and nice */ + + + var Lists = + /*#__PURE__*/ + function (_Doc) { + _inherits(Lists, _Doc); + + function Lists() { + _classCallCheck(this, Lists); + + return _possibleConstructorReturn(this, _getPrototypeOf(Lists).apply(this, arguments)); + } + + _createClass(Lists, [{ + key: "conjunctions", + + /** coordinating conjunction */ + value: function conjunctions() { + return this.match('(and|or)'); + } + /** split-up by list object */ + + }, { + key: "parts", + value: function parts() { + return this.splitAfter('(@hasComma|#Conjunction)'); + } + /** remove the conjunction */ + + }, { + key: "items", + value: function items() { + return this.parts().notIf('#Conjunction'); + } + /** add a new unit to the list */ + + }, { + key: "add", + value: function add(str) { + this.forEach(function (p) { + var beforeLast = parse(p).beforeLast; + beforeLast.append(str); //add a comma to it + + beforeLast.termList(0).addPunctuation(','); + }); + return this; + } + /** remove any matching unit from the list */ + + }, { + key: "remove", + value: function remove() { + return this; + } + /** return only lists that use a serial comma */ + + }, { + key: "hasOxfordComma", + value: function hasOxfordComma() { + return this.filter(function (doc) { + return parse(doc).hasOxford; + }); + } + }, { + key: "addOxfordComma", + value: function addOxfordComma() { + return this; + } + }, { + key: "removeOxfordComma", + value: function removeOxfordComma() { + return this; + } + }]); + + return Lists; + }(Doc); // aliases + + + Lists.prototype.things = Lists.prototype.items; + + Doc.prototype.lists = function (n) { + var m = this["if"]('@hasComma+ .? (and|or) not? .'); // person-list + + var nounList = m.match('(#Noun|#Adjective)+ #Conjunction not? #Adjective? #Noun+'); + var adjList = m.match('(#Adjective|#Adverb)+ #Conjunction not? #Adverb? #Adjective+'); + var verbList = m.match('(#Verb|#Adverb)+ #Conjunction not? #Adverb? #Verb+'); + var result = nounList.concat(adjList); + result = result.concat(verbList); + result = result["if"]('@hasComma'); + + if (typeof n === 'number') { + result = m.get(n); + } + + return new Lists(result.list, this, this.world); + }; + + return Doc; +}; + +var Lists = addMethod$4; + +var noPlural = '(#Pronoun|#Place|#Value|#Person|#Uncountable|#Month|#WeekDay|#Holiday|#Possessive)'; //certain words can't be plural, like 'peace' + +var hasPlural = function hasPlural(doc) { + if (doc.has('#Plural') === true) { + return true; + } // these can't be plural + + + if (doc.has(noPlural) === true) { + return false; + } + + return true; +}; + +var hasPlural_1 = hasPlural; + +var irregulars$5 = { + hour: 'an', + heir: 'an', + heirloom: 'an', + honest: 'an', + honour: 'an', + honor: 'an', + uber: 'an' //german u + +}; //pronounced letters of acronyms that get a 'an' + +var an_acronyms = { + a: true, + e: true, + f: true, + h: true, + i: true, + l: true, + m: true, + n: true, + o: true, + r: true, + s: true, + x: true +}; //'a' regexes + +var a_regexs = [/^onc?e/i, //'wu' sound of 'o' +/^u[bcfhjkqrstn][aeiou]/i, // 'yu' sound for hard 'u' +/^eul/i]; + +var makeArticle = function makeArticle(doc) { + //no 'the john smith', but 'a london hotel' + if (doc.has('#Person') || doc.has('#Place')) { + return ''; + } //no a/an if it's plural + + + if (doc.has('#Plural')) { + return 'the'; + } + + var str = doc.text('normal').trim(); //explicit irregular forms + + if (irregulars$5.hasOwnProperty(str)) { + return irregulars$5[str]; + } //spelled-out acronyms + + + var firstLetter = str.substr(0, 1); + + if (doc.has('^@isAcronym') && an_acronyms.hasOwnProperty(firstLetter)) { + return 'an'; + } //'a' regexes + + + for (var i = 0; i < a_regexs.length; i++) { + if (a_regexs[i].test(str)) { + return 'a'; + } + } //basic vowel-startings + + + if (/^[aeiou]/i.test(str)) { + return 'an'; + } + + return 'a'; +}; + +var getArticle = makeArticle; + +//similar to plural/singularize rules, but not the same +var isPlural$1 = [/(antenn|formul|nebul|vertebr|vit)ae$/i, /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, /men$/i, /.tia$/i, /(m|l)ice$/i]; //similar to plural/singularize rules, but not the same + +var isSingular$1 = [/(ax|test)is$/i, /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, /(octop|vir)i$/i, /(rl)f$/i, /(alias|status)$/i, /(bu)s$/i, /(al|ad|at|er|et|ed|ad)o$/i, /(ti)um$/i, /(ti)a$/i, /sis$/i, /(?:(^f)fe|(lr)f)$/i, /hive$/i, /(^aeiouy|qu)y$/i, /(x|ch|ss|sh|z)$/i, /(matr|vert|ind|cort)(ix|ex)$/i, /(m|l)ouse$/i, /(m|l)ice$/i, /(antenn|formul|nebul|vertebr|vit)a$/i, /.sis$/i, /^(?!talis|.*hu)(.*)man$/i]; +var _rules$2 = { + isSingular: isSingular$1, + isPlural: isPlural$1 +}; + +var endS = /s$/; // double-check this term, if it is not plural, or singular. +// (this is a partial copy of ./tagger/fallbacks/plural) +// fallback plural if it ends in an 's'. + +var isPlural$2 = function isPlural(str) { + // isSingular suffix rules + if (_rules$2.isSingular.find(function (reg) { + return reg.test(str); + })) { + return false; + } // does it end in an s? + + + if (endS.test(str) === true) { + return true; + } // is it a plural like 'fungi'? + + + if (_rules$2.isPlural.find(function (reg) { + return reg.test(str); + })) { + return true; + } + + return null; +}; + +var isPlural_1$1 = isPlural$2; + +var exceptions = { + he: 'his', + she: 'hers', + they: 'theirs', + we: 'ours', + i: 'mine', + you: 'yours', + her: 'hers', + their: 'theirs', + our: 'ours', + my: 'mine', + your: 'yours' +}; // turn "David" to "David's" + +var toPossessive = function toPossessive(doc) { + var str = doc.text('text').trim(); // exceptions + + if (exceptions.hasOwnProperty(str)) { + doc.replaceWith(exceptions[str], true, true); + doc.tag('Possessive', 'toPossessive'); + return; + } // flanders' + + + if (/s$/.test(str)) { + str += "'"; + doc.replaceWith(str, true, true); + doc.tag('Possessive', 'toPossessive'); + return; + } //normal form: + + + str += "'s"; + doc.replaceWith(str, true, true); + doc.tag('Possessive', 'toPossessive'); + return; +}; + +var toPossessive_1 = toPossessive; + +// .nouns() supports some noun-phrase-ish groupings +// pull these apart, if necessary +var parse$1 = function parse(doc) { + var res = { + main: doc + }; //support 'mayor of chicago' as one noun-phrase + + if (doc.has('#Noun (of|by|for) .')) { + var m = doc.splitAfter('[#Noun+]'); + res.main = m.eq(0); + res.post = m.eq(1); + } + + return res; +}; + +var parse_1 = parse$1; + +var methods$6 = { + /** overload the original json with noun information */ + json: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + json.article = getArticle(doc); + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + }, + isPlural: function isPlural() { + return this["if"]('#Plural'); //assume tagger has run? + }, + hasPlural: function hasPlural() { + return this.filter(function (d) { + return hasPlural_1(d); + }); + }, + toPlural: function toPlural() { + var _this = this; + + var toPlural = this.world.transforms.toPlural; + this.forEach(function (doc) { + if (doc.has('#Plural') || hasPlural_1(doc) === false) { + return; + } // double-check it isn't an un-tagged plural + + + var main = parse_1(doc).main; + var str = main.text(); + + if (!main.has('#Singular') && isPlural_1$1(str) === true) { + return; + } + + str = toPlural(str, _this.world); + main.replace(str).tag('#Plural'); + }); + return this; + }, + toSingular: function toSingular() { + var _this2 = this; + + var toSingular = this.world.transforms.toSingular; + this.forEach(function (doc) { + if (doc.has('#Singular') || hasPlural_1(doc) === false) { + return; + } // double-check it isn't an un-tagged plural + + + var main = parse_1(doc).main; + var str = main.text(); + + if (!main.has('#Plural') && isPlural_1$1(str) !== true) { + return; + } + + str = toSingular(str, _this2.world); + main.replace(str).tag('#Singular'); + }); + return this; + }, + toPossessive: function toPossessive() { + this.forEach(function (d) { + toPossessive_1(d); + }); + return this; + } +}; +var methods_1 = methods$6; + +var addMethod$5 = function addMethod(Doc) { + /** */ + var Nouns = + /*#__PURE__*/ + function (_Doc) { + _inherits(Nouns, _Doc); + + function Nouns() { + _classCallCheck(this, Nouns); + + return _possibleConstructorReturn(this, _getPrototypeOf(Nouns).apply(this, arguments)); + } + + return Nouns; + }(Doc); // add-in our methods + + + Object.assign(Nouns.prototype, methods_1); + + Doc.prototype.nouns = function (n) { + var match = this.clauses(); + match = match.match('#Noun+ (of|by)? the? #Noun+?'); //nouns that we don't want in these results, for weird reasons + + match = match.not('#Pronoun'); + match = match.not('(there|these)'); + match = match.not('(#Month|#WeekDay)'); //allow Durations, Holidays + // //allow possessives like "spencer's", but not generic ones like, + + match = match.not('(my|our|your|their|her|his)'); + match = match.not('(of|for|by|the)$'); + + if (typeof n === 'number') { + match = match.get(n); + } + + return new Nouns(match.list, this, this.world); + }; + + return Doc; +}; + +var Nouns = addMethod$5; + +var open = /\(/; +var close = /\)/; + +var addMethod$6 = function addMethod(Doc) { + /** anything between (these things) */ + var Parentheses = + /*#__PURE__*/ + function (_Doc) { + _inherits(Parentheses, _Doc); + + function Parentheses() { + _classCallCheck(this, Parentheses); + + return _possibleConstructorReturn(this, _getPrototypeOf(Parentheses).apply(this, arguments)); + } + + _createClass(Parentheses, [{ + key: "unwrap", + + /** remove the parentheses characters */ + value: function unwrap() { + this.list.forEach(function (p) { + var first = p.terms(0); + first.pre = first.pre.replace(open, ''); + var last = p.lastTerm(); + last.post = last.post.replace(close, ''); + }); + return this; + } + }]); + + return Parentheses; + }(Doc); + + Doc.prototype.parentheses = function (n) { + var list = []; + this.list.forEach(function (p) { + var terms = p.terms(); //look for opening brackets + + for (var i = 0; i < terms.length; i += 1) { + var t = terms[i]; + + if (open.test(t.pre)) { + //look for the closing bracket.. + for (var o = i; o < terms.length; o += 1) { + if (close.test(terms[o].post)) { + var len = o - i + 1; + list.push(p.buildFrom(t.id, len)); + i = o; + break; + } + } + } + } + }); //support nth result + + if (typeof n === 'number') { + if (list[n]) { + list = [list[n]]; + } else { + list = []; + } + + return new Parentheses(list, this, this.world); + } + + return new Parentheses(list, this, this.world); + }; + + return Doc; +}; + +var Parentheses = addMethod$6; + +var addMethod$7 = function addMethod(Doc) { + /** */ + var Possessives = + /*#__PURE__*/ + function (_Doc) { + _inherits(Possessives, _Doc); + + function Possessives(list, from, world) { + var _this; + + _classCallCheck(this, Possessives); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Possessives).call(this, list, from, world)); + _this.contracted = null; + return _this; + } + /** turn didn't into 'did not' */ + + + _createClass(Possessives, [{ + key: "strip", + value: function strip() { + this.list.forEach(function (p) { + var terms = p.terms(); + terms.forEach(function (t) { + var str = t.text.replace(/'s$/, ''); + t.set(str || t.text); + }); + }); + return this; + } + }]); + + return Possessives; + }(Doc); //find contractable, expanded-contractions + // const findExpanded = r => { + // let remain = r.not('#Contraction') + // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)') + // m.concat(remain.match('(they|we|you|i) have')) + // m.concat(remain.match('i am')) + // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')) + // return m + // } + + + Doc.prototype.possessives = function (n) { + //find currently-contracted + var found = this.match('#Noun+? #Possessive'); //todo: split consecutive contractions + + if (typeof n === 'number') { + found = found.get(n); + } + + return new Possessives(found.list, this, this.world); + }; + + return Doc; +}; + +var Possessives = addMethod$7; + +var pairs = { + "\"": "\"", + // 'StraightDoubleQuotes' + "\uFF02": "\uFF02", + // 'StraightDoubleQuotesWide' + "'": "'", + // 'StraightSingleQuotes' + "\u201C": "\u201D", + // 'CommaDoubleQuotes' + "\u2018": "\u2019", + // 'CommaSingleQuotes' + "\u201F": "\u201D", + // 'CurlyDoubleQuotesReversed' + "\u201B": "\u2019", + // 'CurlySingleQuotesReversed' + "\u201E": "\u201D", + // 'LowCurlyDoubleQuotes' + "\u2E42": "\u201D", + // 'LowCurlyDoubleQuotesReversed' + "\u201A": "\u2019", + // 'LowCurlySingleQuotes' + "\xAB": "\xBB", + // 'AngleDoubleQuotes' + "\u2039": "\u203A", + // 'AngleSingleQuotes' + // Prime 'non quotation' + "\u2035": "\u2032", + // 'PrimeSingleQuotes' + "\u2036": "\u2033", + // 'PrimeDoubleQuotes' + "\u2037": "\u2034", + // 'PrimeTripleQuotes' + // Prime 'quotation' variation + "\u301D": "\u301E", + // 'PrimeDoubleQuotes' + "`": "\xB4", + // 'PrimeSingleQuotes' + "\u301F": "\u301E" // 'LowPrimeDoubleQuotesReversed' + +}; +var hasOpen = RegExp('(' + Object.keys(pairs).join('|') + ')'); + +var addMethod$8 = function addMethod(Doc) { + /** "these things" */ + var Quotations = + /*#__PURE__*/ + function (_Doc) { + _inherits(Quotations, _Doc); + + function Quotations() { + _classCallCheck(this, Quotations); + + return _possibleConstructorReturn(this, _getPrototypeOf(Quotations).apply(this, arguments)); + } + + _createClass(Quotations, [{ + key: "unwrap", + + /** remove the quote characters */ + value: function unwrap() { + return this; + } + }]); + + return Quotations; + }(Doc); + + Doc.prototype.quotations = function (n) { + var list = []; + this.list.forEach(function (p) { + var terms = p.terms(); //look for opening quotes + + for (var i = 0; i < terms.length; i += 1) { + var t = terms[i]; + + if (hasOpen.test(t.pre)) { + var _char = (t.pre.match(hasOpen) || [])[0]; + var want = pairs[_char]; // if (!want) { + // console.warn('missing quote char ' + char) + // } + //look for the closing bracket.. + + for (var o = i; o < terms.length; o += 1) { + if (terms[o].post.indexOf(want) !== -1) { + var len = o - i + 1; + list.push(p.buildFrom(t.id, len)); + i = o; + break; + } + } + } + } + }); //support nth result + + if (typeof n === 'number') { + if (list[n]) { + list = [list[n]]; + } else { + list = []; + } + + return new Quotations(list, this, this.world); + } + + return new Quotations(list, this, this.world); + }; // alias + + + Doc.prototype.quotes = Doc.prototype.quotations; + return Doc; +}; + +var Quotations = addMethod$8; + +// walked => walk - turn a verb into it's root form +var toInfinitive$1 = function toInfinitive(parsed, world) { + var verb = parsed.verb; //1. if it's already infinitive + + var str = verb.text('normal'); + + if (verb.has('#Infinitive')) { + return str; + } // 2. world transform does the heavy-lifting + + + var tense = null; + + if (verb.has('#PastTense')) { + tense = 'PastTense'; + } else if (verb.has('#Gerund')) { + tense = 'Gerund'; + } else if (verb.has('#PresentTense')) { + tense = 'PresentTense'; + } else if (verb.has('#Participle')) { + tense = 'Participle'; + } else if (verb.has('#Actor')) { + tense = 'Actor'; + } + + return world.transforms.toInfinitive(str, world, tense); +}; + +var toInfinitive_1$1 = toInfinitive$1; + +// spencer walks -> singular +// we walk -> plural +// the most-recent noun-phrase, before this verb. +var findNoun = function findNoun(vb) { + var noun = vb.lookBehind('#Noun+').last(); + return noun; +}; //sometimes you can tell if a verb is plural/singular, just by the verb +// i am / we were +// othertimes you need its subject 'we walk' vs 'i walk' + + +var isPlural$3 = function isPlural(parsed) { + var vb = parsed.verb; + + if (vb.has('(are|were|does)') || parsed.auxiliary.has('(are|were|does)')) { + return true; + } + + if (vb.has('(is|am|do|was)') || parsed.auxiliary.has('(is|am|do|was)')) { + return false; + } //consider its prior noun + + + var noun = findNoun(vb); + + if (noun.has('(we|they|you)')) { + return true; + } + + if (noun.has('#Plural')) { + return true; + } + + if (noun.has('#Singular')) { + return false; + } + + return null; +}; + +var isPlural_1$2 = isPlural$3; + +// #Copula : is -> 'is not' +// #PastTense : walked -> did not walk +// #PresentTense : walks -> does not walk +// #Gerund : walking: -> not walking +// #Infinitive : walk -> do not walk + +var toNegative = function toNegative(parsed, world) { + var vb = parsed.verb; // if it's already negative... + + if (parsed.negative.found) { + return; + } // would walk -> would not walk + + + if (parsed.auxiliary.found) { + parsed.auxiliary.eq(0).append('not'); + return; + } // is walking -> is not walking + + + if (vb.has('(#Copula|will|has|had|do)')) { + vb.append('not'); + return; + } // walked -> did not walk + + + if (vb.has('#PastTense')) { + var inf = toInfinitive_1$1(parsed, world); + vb.replaceWith(inf, true, true); + vb.prepend('did not'); + return; + } // walks -> does not walk + + + if (vb.has('#PresentTense')) { + var _inf = toInfinitive_1$1(parsed, world); + + vb.replaceWith(_inf, true, true); + + if (isPlural_1$2(parsed)) { + vb.prepend('do not'); + } else { + vb.prepend('does not'); + } + + return; + } //walking -> not walking + + + if (vb.has('#Gerund')) { + var _inf2 = toInfinitive_1$1(parsed, world); + + vb.replaceWith(_inf2, true, true); + vb.prepend('not'); + return; + } //fallback 1: walk -> does not walk + + + if (isPlural_1$2(parsed)) { + vb.prepend('does not'); + return; + } //fallback 2: walk -> do not walk + + + vb.prepend('do not'); + return; +}; + +var toNegative_1 = toNegative; + +// turn 'would not really walk up' into parts +var parseVerb = function parseVerb(vb) { + var parsed = { + adverb: vb.match('#Adverb+'), + // 'really' + negative: vb.match('#Negative'), + // 'not' + auxiliary: vb.match('#Auxiliary').not('(#Negative|#Adverb)'), + // 'will' of 'will go' + particle: vb.match('#Particle'), + // 'up' of 'pull up' + verb: vb.match('#Verb').not('(#Adverb|#Negative|#Auxiliary|#Particle)') + }; // fallback, if no verb found + + if (!parsed.verb.found) { + // blank-everything + Object.keys(parsed).forEach(function (k) { + parsed[k] = parsed[k].not('.'); + }); // it's all the verb + + parsed.verb = vb; + return parsed; + } // + + + if (parsed.adverb && parsed.adverb.found) { + var match = parsed.adverb.text('reduced') + '$'; + + if (vb.has(match)) { + parsed.adverbAfter = true; + } + } // console.log(parsed.adverb.json({ index: true })[0]) + + + return parsed; +}; + +var parse$2 = parseVerb; + +/** too many special cases for is/was/will be*/ + +var toBe = function toBe(parsed) { + var isI = false; + var plural = isPlural_1$2(parsed); + var isNegative = parsed.negative.found; //account for 'i is' -> 'i am' irregular + // if (vb.parent && vb.parent.has('i #Adverb? #Copula')) { + // isI = true; + // } + // 'i look', not 'i looks' + + if (parsed.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) { + isI = true; + } + + var obj = { + PastTense: 'was', + PresentTense: 'is', + FutureTense: 'will be', + Infinitive: 'is', + Gerund: 'being', + Actor: '', + PerfectTense: 'been', + Pluperfect: 'been' + }; //"i is" -> "i am" + + if (isI === true) { + obj.PresentTense = 'am'; + obj.Infinitive = 'am'; + } + + if (plural) { + obj.PastTense = 'were'; + obj.PresentTense = 'are'; + obj.Infinitive = 'are'; + } + + if (isNegative) { + obj.PastTense += ' not'; + obj.PresentTense += ' not'; + obj.FutureTense = 'will not be'; + obj.Infinitive += ' not'; + obj.PerfectTense = 'not ' + obj.PerfectTense; + obj.Pluperfect = 'not ' + obj.Pluperfect; + obj.Gerund = 'not ' + obj.Gerund; + } + + return obj; +}; + +var toBe_1 = toBe; + +var conjugate$2 = function conjugate(parsed, world) { + var verb = parsed.verb; //special handling of 'is', 'will be', etc. + + if (verb.has('#Copula') || verb.out('normal') === 'be' && parsed.auxiliary.has('will')) { + return toBe_1(parsed); + } + + var infinitive = toInfinitive_1$1(parsed, world); + + if (!infinitive) { + return {}; + } // console.log(infinitive) + + + var forms = world.transforms.conjugate(infinitive, world); + forms.Infinitive = infinitive; // add particle to phrasal verbs ('fall over') + + if (parsed.particle.found) { + var particle = parsed.particle.text(); + Object.keys(forms).forEach(function (k) { + return forms[k] += ' ' + particle; + }); + } //put the adverb at the end? + + + if (parsed.adverb.found) { + var adverb = parsed.adverb.text(); + + if (parsed.adverbAfter === true) { + Object.keys(forms).forEach(function (k) { + return forms[k] += ' ' + adverb; + }); + } else { + Object.keys(forms).forEach(function (k) { + return forms[k] = adverb + ' ' + forms[k]; + }); + } + } //apply negative + + + var isNegative = parsed.negative.found; + + if (isNegative) { + forms.PastTense = 'did not ' + forms.Infinitive; + forms.PresentTense = 'does not ' + forms.Infinitive; + forms.Gerund = 'not ' + forms.Gerund; + } //future Tense is pretty straightforward + + + if (!forms.FutureTense) { + if (isNegative) { + forms.FutureTense = 'will not ' + forms.Infinitive; + } else { + forms.FutureTense = 'will ' + forms.Infinitive; + } + } + + if (isNegative) { + forms.Infinitive = 'not ' + forms.Infinitive; + } + + return forms; +}; + +var conjugate_1$1 = conjugate$2; + +var methods$7 = { + /** overload the original json with verb information */ + json: function json(options) { + var _this = this; + + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (p) { + var json = p.json(options)[0]; + var parsed = parse$2(p); + json.parts = {}; + Object.keys(parsed).forEach(function (k) { + json.parts[k] = parsed[k].text('normal'); + }); + json.isNegative = p.has('#Negative'); + json.conjugations = conjugate_1$1(parsed, _this.world); + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + }, + + /** grab the adverbs describing these verbs */ + adverbs: function adverbs() { + var list = []; // look at internal adverbs + + this.forEach(function (vb) { + var advb = parse$2(vb).adverb; + + if (advb.found) { + list = list.concat(advb.list); + } + }); // look for leading adverbs + + var m = this.lookBehind('#Adverb$'); + + if (m.found) { + list = m.list.concat(list); + } // look for trailing adverbs + + + m = this.lookAhead('^#Adverb'); + + if (m.found) { + list = list.concat(m.list); + } + + return this.buildFrom(list); + }, + + /**return verbs like 'we walk' and not 'spencer walks' */ + isPlural: function isPlural() { + var _this2 = this; + + var list = []; + this.forEach(function (vb) { + var parsed = parse$2(vb); + + if (isPlural_1$2(parsed, _this2.world) === true) { + list.push(vb.list[0]); + } + }); + return this.buildFrom(list); + }, + + /** return verbs like 'spencer walks' and not 'we walk' */ + isSingular: function isSingular() { + var _this3 = this; + + var list = []; + this.forEach(function (vb) { + var parsed = parse$2(vb); + + if (isPlural_1$2(parsed, _this3.world) === false) { + list.push(vb.list[0]); + } + }); + return this.buildFrom(list); + }, + + /** */ + conjugate: function conjugate() { + var _this4 = this; + + var result = []; + this.forEach(function (vb) { + var parsed = parse$2(vb); + + var forms = conjugate_1$1(parsed, _this4.world); + + result.push(forms); + }); + return result; + }, + + /** */ + toPastTense: function toPastTense() { + var _this5 = this; + + this.forEach(function (vb) { + var parsed = parse$2(vb); + + var str = conjugate_1$1(parsed, _this5.world).PastTense; + + if (str) { + vb.replaceWith(str, false, true); // vb.tag('PastTense') + } + }); + return this; + }, + + /** */ + toPresentTense: function toPresentTense() { + var _this6 = this; + + this.forEach(function (vb) { + var parsed = parse$2(vb); + + var obj = conjugate_1$1(parsed, _this6.world); + + var str = obj.PresentTense; // 'i look', not 'i looks' + + if (vb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) { + str = obj.Infinitive; + } + + if (str) { + vb.replaceWith(str, false, true); + vb.tag('PresentTense'); + } + }); + return this; + }, + + /** */ + toFutureTense: function toFutureTense() { + var _this7 = this; + + this.forEach(function (vb) { + var parsed = parse$2(vb); + + var str = conjugate_1$1(parsed, _this7.world).FutureTense; + + if (str) { + vb.replaceWith(str, false, true); + vb.tag('FutureTense'); + } + }); + return this; + }, + + /** */ + toInfinitive: function toInfinitive() { + var _this8 = this; + + this.forEach(function (vb) { + var parsed = parse$2(vb); + + var str = toInfinitive_1$1(parsed, _this8.world); + + if (str) { + vb.replaceWith(str, false, true); + vb.tag('Infinitive'); + } + }); + return this; + }, + + /** */ + toGerund: function toGerund() { + var _this9 = this; + + this.forEach(function (vb) { + var parsed = parse$2(vb); + + var str = conjugate_1$1(parsed, _this9.world).Gerund; + + if (str) { + vb.replaceWith(str, false, true); + vb.tag('Gerund'); + } + }); + return this; + }, + + /** return only verbs with 'not'*/ + isNegative: function isNegative() { + return this["if"]('#Negative'); + }, + + /** return only verbs without 'not'*/ + isPositive: function isPositive() { + return this.ifNo('#Negative'); + }, + + /** add a 'not' to these verbs */ + toNegative: function toNegative() { + var _this10 = this; + + this.list.forEach(function (p) { + var doc = _this10.buildFrom([p]); + + var parsed = parse$2(doc); + + toNegative_1(parsed, doc.world); + }); + return this; + }, + + /** remove 'not' from these verbs */ + toPositive: function toPositive() { + var m = this.match('do not #Verb'); + + if (m.found) { + m.remove('do not'); + } + + return this.remove('#Negative'); + } +}; + +var addMethod$9 = function addMethod(Doc) { + /** */ + var Verbs = + /*#__PURE__*/ + function (_Doc) { + _inherits(Verbs, _Doc); + + function Verbs() { + _classCallCheck(this, Verbs); + + return _possibleConstructorReturn(this, _getPrototypeOf(Verbs).apply(this, arguments)); + } + + return Verbs; + }(Doc); // add-in our methods + + + Object.assign(Verbs.prototype, methods$7); // aliases + + Verbs.prototype.negate = Verbs.prototype.toNegative; + + Doc.prototype.verbs = function (n) { + var match = this.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); // try to ignore leading and trailing adverbs + + match = match.not('^#Adverb+'); + match = match.not('#Adverb+$'); // handle commas: + // don't split 'really, really' + + var keep = match.match('(#Adverb && @hasComma) #Adverb'); // // but split the other commas + + var m = match.not(keep).splitAfter('@hasComma'); // // combine them back together + + m = m.concat(keep); + m.sort('index'); //handle slashes? + //ensure there's actually a verb + + m = m["if"]('#Verb'); //grab (n)th result + + if (typeof n === 'number') { + m = m.get(n); + } + + var vb = new Verbs(m.list, this, this.world); + return vb; + }; + + return Doc; +}; + +var Verbs = addMethod$9; + +var addMethod$a = function addMethod(Doc) { + /** */ + var People = + /*#__PURE__*/ + function (_Doc) { + _inherits(People, _Doc); + + function People() { + _classCallCheck(this, People); + + return _possibleConstructorReturn(this, _getPrototypeOf(People).apply(this, arguments)); + } + + return People; + }(Doc); + + Doc.prototype.people = function (n) { + var match = this.splitAfter('@hasComma'); + match = match.match('#Person+'); //grab (n)th result + + if (typeof n === 'number') { + match = match.get(n); + } + + return new People(match.list, this, this.world); + }; + + return Doc; +}; + +var People = addMethod$a; + +var subclass = [Abbreviations, Acronyms, Clauses, Contractions, Lists, Nouns, Parentheses, Possessives, Quotations, Verbs, People]; + +var extend = function extend(Doc) { + // add basic methods + Object.keys(_simple).forEach(function (k) { + return Doc.prototype[k] = _simple[k]; + }); // add subclassed methods + + subclass.forEach(function (addFn) { + return addFn(Doc); + }); + return Doc; +}; + +var Subset = extend; + +var methods$8 = { + misc: methods$4, + selections: _simple +}; +/** a parsed text object */ + +var Doc = +/*#__PURE__*/ +function () { + function Doc(list, from, world) { + var _this = this; + + _classCallCheck(this, Doc); + + this.list = list; //quiet these properties in console.logs + + Object.defineProperty(this, 'from', { + enumerable: false, + value: from, + writable: true + }); //borrow some missing data from parent + + if (world === undefined && from !== undefined) { + world = from.world; + } //'world' getter + + + Object.defineProperty(this, 'world', { + enumerable: false, + value: world // writable: true, //todo: add me? + + }); //fast-scans for our data + //'found' getter + + Object.defineProperty(this, 'found', { + get: function get() { + return _this.list.length > 0; + } + }); //'length' getter + + Object.defineProperty(this, 'length', { + get: function get() { + return _this.list.length; + } + }); // this is way easier than .constructor.name... + + Object.defineProperty(this, 'isA', { + get: function get() { + return 'Doc'; + } + }); + } + /** run part-of-speech tagger on all results*/ + + + _createClass(Doc, [{ + key: "tagger", + value: function tagger() { + return _02Tagger(this); + } + /** pool is stored on phrase objects */ + + }, { + key: "pool", + value: function pool() { + if (this.list.length > 0) { + return this.list[0].pool; + } + + return this.all().list[0].pool; + } + }]); + + return Doc; +}(); +/** create a new Document object */ + + +Doc.prototype.buildFrom = function (list) { + list = list.map(function (p) { + return p.clone(true); + }); // new this.constructor() + + var doc = new Doc(list, this, this.world); + return doc; +}; +/** create a new Document from plaintext. */ + + +Doc.prototype.fromText = function (str) { + var list = _01Tokenizer.fromText(str, this.world, this.pool()); + return this.buildFrom(list); +}; + +Object.assign(Doc.prototype, methods$8.misc); +Object.assign(Doc.prototype, methods$8.selections); //add sub-classes + +Subset(Doc); //aliases + +var aliases$1 = { + untag: 'unTag', + and: 'match', + notIf: 'ifNo', + only: 'if', + onlyIf: 'if' +}; +Object.keys(aliases$1).forEach(function (k) { + return Doc.prototype[k] = Doc.prototype[aliases$1[k]]; +}); +var Doc_1 = Doc; + +var world = new World_1(); +/** parse and tag text into a compromise object */ + +var nlp = function nlp() { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var lexicon = arguments.length > 1 ? arguments[1] : undefined; + + if (lexicon) { + world.addWords(lexicon); + } + + var list = _01Tokenizer.fromText(text, world); + var doc = new Doc_1(list, null, world); + doc.tagger(); + return doc; +}; +/** parse text into a compromise object, without running POS-tagging */ + + +nlp.tokenize = function () { + var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var lexicon = arguments.length > 1 ? arguments[1] : undefined; + + if (lexicon) { + world.addWords(lexicon); + } + + var list = _01Tokenizer.fromText(text, world); + var doc = new Doc_1(list, null, world); + return doc; +}; +/** mix in a compromise-plugin */ + + +nlp.extend = function (fn) { + fn(Doc_1, world); + return this; +}; +/** make a deep-copy of the library state */ + + +nlp.clone = function () { + world = world.clone(); + return this; +}; +/** re-generate a Doc object from .json() results */ + + +nlp.load = function (json) { + var list = _01Tokenizer.fromJSON(json, world); + return new Doc_1(list, null, world); +}; +/** log our decision-making for debugging */ + + +nlp.verbose = function () { + var bool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + world.verbose(bool); + return this; +}; +/** current version of the library */ + + +nlp.version = _version; // alias + +nlp["import"] = nlp.load; +var src = nlp; + +export default src; diff --git a/changelog.md b/changelog.md index c2e5f4525..4b689cb85 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,9 @@ compromise uses semver, and pushes to npm frequently * **Minor** is considered a behaviour/performance change. * **Patch** is an obvious, non-controversial bugfix +### v12   :postal_horn: +- [see Release Notes](https://github.com/spencermountain/compromise/wiki/v12-Release-Notes) + ### v11 ##### 11.13.0 - support singular units in `.value()` diff --git a/data/abbreviations/honorifics.js b/data/abbreviations/honorifics.js new file mode 100644 index 000000000..db4e7cf93 --- /dev/null +++ b/data/abbreviations/honorifics.js @@ -0,0 +1,50 @@ +module.exports = [ + 'adj', + 'adm', + 'adv', + 'asst', + 'atty', + 'bldg', + 'brig', + 'capt', + 'cmdr', + 'comdr', + 'cpl', + 'det', + 'dr', + 'esq', + 'gen', + 'gov', + 'hon', + 'jr', + 'llb', + 'lt', + 'maj', + 'messrs', + 'mister', + 'mlle', + 'mme', + 'mr', + 'mrs', + 'ms', + 'mstr', + 'op', + 'ord', + 'phd', + 'prof', + 'pvt', + 'rep', + 'reps', + 'res', + 'rev', + 'sen', + 'sens', + 'sfc', + 'sgt', + 'sir', + 'sr', + 'supt', + 'surg', + //miss + //misses +] diff --git a/data/abbreviations/months.js b/data/abbreviations/months.js new file mode 100644 index 000000000..a409a9f2e --- /dev/null +++ b/data/abbreviations/months.js @@ -0,0 +1 @@ +module.exports = ['jan', 'feb', 'mar', 'apr', 'jun', 'jul', 'aug', 'sep', 'sept', 'oct', 'nov', 'dec'] diff --git a/data/abbreviations/nouns.js b/data/abbreviations/nouns.js new file mode 100644 index 000000000..865ad6f26 --- /dev/null +++ b/data/abbreviations/nouns.js @@ -0,0 +1,28 @@ +module.exports = [ + 'ad', + 'al', + 'arc', + 'ba', + 'bc', + 'bl', + 'ca', + 'cca', + 'col', + 'corp', + 'eg', + 'esp', + 'etc', + 'ex', + 'exp', + 'ft', + 'fy', + 'ie', + 'lit', + 'ma', + 'md', + 'pd', + 'pl', + 'plz', + 'tce', + 'vs', +] diff --git a/data/abbreviations/organizations.js b/data/abbreviations/organizations.js new file mode 100644 index 000000000..da35045b7 --- /dev/null +++ b/data/abbreviations/organizations.js @@ -0,0 +1 @@ +module.exports = ['dept', 'univ', 'assn', 'bros', 'inc', 'ltd', 'co'] diff --git a/data/abbreviations/places.js b/data/abbreviations/places.js new file mode 100644 index 000000000..70712b9d9 --- /dev/null +++ b/data/abbreviations/places.js @@ -0,0 +1,48 @@ +module.exports = [ + 'rd', + 'st', + 'dist', + 'mt', + 'ave', + 'blvd', + 'cl', + 'ct', + 'cres', + 'hwy', + //states + 'ariz', + 'cal', + 'calif', + 'colo', + 'conn', + 'fla', + 'fl', + 'ga', + 'ida', + 'ia', + 'kan', + 'kans', + + 'minn', + 'neb', + 'nebr', + 'okla', + 'penna', + 'penn', + 'pa', + 'dak', + 'tenn', + 'tex', + 'ut', + 'vt', + 'va', + 'wis', + 'wisc', + 'wy', + 'wyo', + 'usafa', + 'alta', + 'ont', + 'que', + 'sask', +] diff --git a/data/words/adjectives/adjectives.js b/data/adjectives/adjectives.js similarity index 99% rename from data/words/adjectives/adjectives.js rename to data/adjectives/adjectives.js index 50282638c..c101ad211 100644 --- a/data/words/adjectives/adjectives.js +++ b/data/adjectives/adjectives.js @@ -29,9 +29,9 @@ module.exports = [ 'ahead', 'alarming', 'alcoholic', - 'all', 'alert', 'alive', + 'all', 'aloof', 'amazing', 'antiquated', @@ -160,6 +160,7 @@ module.exports = [ 'far reaching', 'faux', 'favorite', + 'favourite', 'fed up', 'female', 'feminine', @@ -346,6 +347,7 @@ module.exports = [ 'populist', 'precise', 'premature', + 'premier', 'premium', 'primary', 'prime', @@ -516,5 +518,5 @@ module.exports = [ 'wooden', 'woozy', 'wound', - 'yearly' -]; + 'yearly', +] diff --git a/data/words/adjectives/comparables.js b/data/adjectives/comparables.js similarity index 99% rename from data/words/adjectives/comparables.js rename to data/adjectives/comparables.js index dbeab04ac..c1628913f 100644 --- a/data/words/adjectives/comparables.js +++ b/data/adjectives/comparables.js @@ -36,7 +36,6 @@ module.exports = [ 'clean', 'clear', 'clever', - // 'close', 'cloudy', 'cold', 'common', @@ -50,8 +49,8 @@ module.exports = [ 'curly', 'cute', 'dapper', - 'dear', 'deadly', + 'dear', 'dense', 'dire', 'dirty', @@ -183,16 +182,15 @@ module.exports = [ 'normal', 'nosy', 'odd', + 'official', 'oily', 'old', - 'official', 'orange', - 'pale', 'painful', + 'pale', 'phony', 'pink', 'plain', - 'plant', 'pleasant', 'polite', 'poor', @@ -206,8 +204,8 @@ module.exports = [ 'pure', 'purple', 'quaint', - 'random', 'ragged', + 'random', 'rapid', 'rare', 'raw', @@ -262,13 +260,13 @@ module.exports = [ 'square', 'stale', 'stark', + 'steady', 'stern', 'strange', 'strict', - 'steady', - 'sturdy', 'strong', 'stupid', + 'sturdy', 'substantial', 'subtle', 'sudden', @@ -306,15 +304,15 @@ module.exports = [ 'vulgar', 'wanting', 'warm', - 'wasteful', 'wary', + 'wasteful', 'weary', 'weird', 'wet', 'wicked', 'wild', - 'windy', 'wily', + 'windy', 'wiry', 'wise', 'wrong', @@ -322,6 +320,7 @@ module.exports = [ 'yellow', 'young', 'zany', + // 'close', //these ones can also be verbs, for what it's worth 'bright', @@ -352,16 +351,16 @@ module.exports = [ 'short', 'sick', 'smart', + 'smooth', 'soft', + 'steep', 'stiff', 'straight', 'sweet', 'thick', 'tight', - 'steep', 'tough', 'weak', 'white', 'wide', - 'smooth' -]; +] diff --git a/data/conjugations.js b/data/conjugations.js deleted file mode 100644 index ed7e5421d..000000000 --- a/data/conjugations.js +++ /dev/null @@ -1,661 +0,0 @@ -module.exports = { - 'take': { - 'PerfectTense': 'have taken', - 'PluPerfectTense': 'had taken', - 'PastTense': 'took', - 'Participle': 'taken', - 'FuturePerfect': 'will have taken' - }, - 'can': { - 'Gerund': '', - 'PresentTense': 'can', - 'PastTense': 'could', - 'PerfectTense': 'could', - 'PluPerfectTense': 'could', - 'FuturePerfect': 'can', - 'Actor': '' - }, - 'free': { - 'Gerund': 'freeing', - 'Actor': '' - }, - 'puke': { - 'Gerund': 'puking' - }, - 'arise': { - 'PastTense': 'arose', - 'Participle': 'arisen' - }, - 'babysit': { - 'PastTense': 'babysat', - 'Actor': 'babysitter' - }, - 'be': { - 'PastTense': 'was', - 'Participle': 'been', - 'PresentTense': 'is', - 'Actor': '', - 'Gerund': 'am' - }, - 'is': { - 'PastTense': 'was', - 'PresentTense': 'is', - 'Actor': '', - 'Gerund': 'being' - }, - 'beat': { - 'Gerund': 'beating', - 'Actor': 'beater', - 'Participle': 'beaten' - }, - 'begin': { - 'Gerund': 'beginning', - 'PastTense': 'began', - 'Participle': 'begun' - }, - 'ban': { - 'PastTense': 'banned', - 'Gerund': 'banning', - 'Actor': '' - }, - 'bet': { - 'Actor': 'better', - 'Participle': 'bet' - }, - 'bite': { - 'Gerund': 'biting', - 'PastTense': 'bit', - 'Participle': 'bitten' - }, - 'bleed': { - 'PastTense': 'bled', - 'Participle': 'bled' - }, - 'breed': { - 'PastTense': 'bred' - }, - 'bring': { - 'PastTense': 'brought', - 'Participle': 'brought' - }, - 'broadcast': { - 'PastTense': 'broadcast' - }, - 'build': { - 'PastTense': 'built', - 'Participle': 'built' - }, - 'buy': { - 'PastTense': 'bought', - 'Participle': 'bought' - }, - 'choose': { - 'Gerund': 'choosing', - 'PastTense': 'chose', - 'Participle': 'chosen' - }, - 'cost': { - 'PastTense': 'cost' - }, - 'deal': { - 'PastTense': 'dealt', - 'Participle': 'dealt' - }, - 'die': { - 'PastTense': 'died', - 'Gerund': 'dying' - }, - 'dig': { - 'Gerund': 'digging', - 'PastTense': 'dug', - 'Participle': 'dug' - }, - 'draw': { - 'PastTense': 'drew', - 'Participle': 'drawn' - }, - 'drink': { - 'PastTense': 'drank', - 'Participle': 'drunk' - }, - 'drive': { - 'Gerund': 'driving', - 'PastTense': 'drove', - 'Participle': 'driven' - }, - 'eat': { - 'Gerund': 'eating', - 'PastTense': 'ate', - 'Actor': 'eater', - 'Participle': 'eaten' - }, - 'fall': { - 'PastTense': 'fell', - 'Participle': 'fallen' - }, - 'feed': { - 'PastTense': 'fed', - 'Participle': 'fed' - }, - 'feel': { - 'PastTense': 'felt', - 'Actor': 'feeler' - }, - 'fight': { - 'PastTense': 'fought', - 'Participle': 'fought' - }, - 'find': { - 'PastTense': 'found' - }, - 'fly': { - 'PastTense': 'flew', - 'Participle': 'flown' - }, - 'blow': { - 'PastTense': 'blew', - 'Participle': 'blown' - }, - 'forbid': { - 'PastTense': 'forbade' - }, - 'edit': { - 'Gerund': 'editing' - }, - 'forget': { - 'Gerund': 'forgeting', - 'PastTense': 'forgot', - 'Participle': 'forgotten' - }, - 'forgive': { - 'Gerund': 'forgiving', - 'PastTense': 'forgave', - 'Participle': 'forgiven' - }, - 'freeze': { - 'Gerund': 'freezing', - 'PastTense': 'froze', - 'Participle': 'frozen' - }, - 'get': { - 'PastTense': 'got' - }, - 'give': { - 'Gerund': 'giving', - 'PastTense': 'gave', - 'Participle': 'given' - }, - 'go': { - 'PastTense': 'went', - 'PresentTense': 'goes', - 'Participle': 'gone' - }, - 'hang': { - 'PastTense': 'hung', - 'Participle': 'hung' - }, - 'have': { - 'Gerund': 'having', - 'PastTense': 'had', - 'PresentTense': 'has', - 'Participle': 'had' - }, - 'hear': { - 'PastTense': 'heard', - 'Participle': 'heard' - }, - 'hide': { - 'PastTense': 'hid', - 'Participle': 'hidden' - }, - 'hold': { - 'PastTense': 'held', - 'Participle': 'held' - }, - 'hurt': { - 'PastTense': 'hurt', - 'Participle': 'hurt' - }, - 'lay': { - 'PastTense': 'laid', - 'Participle': 'laid' - }, - 'lead': { - 'PastTense': 'led', - 'Participle': 'led' - }, - 'leave': { - 'PastTense': 'left', - 'Participle': 'left' - }, - 'lie': { - 'Gerund': 'lying', - 'PastTense': 'lay' - }, - 'light': { - 'PastTense': 'lit', - 'Participle': 'lit' - }, - 'lose': { - 'Gerund': 'losing', - 'PastTense': 'lost' - }, - 'make': { - 'PastTense': 'made', - 'Participle': 'made' - }, - 'mean': { - 'PastTense': 'meant', - 'Participle': 'meant' - }, - 'meet': { - 'Gerund': 'meeting', - 'PastTense': 'met', - 'Actor': 'meeter', - 'Participle': 'met' - }, - 'pay': { - 'PastTense': 'paid', - 'Participle': 'paid' - }, - 'read': { - 'PastTense': 'read', - 'Participle': 'read' - }, - 'ring': { - 'PastTense': 'rang', - 'Participle': 'rung' - }, - 'rise': { - 'PastTense': 'rose', - 'Gerund': 'rising', - 'PluPerfectTense': 'had risen', - 'FuturePerfect': 'will have risen', - 'Participle': 'risen' - }, - 'run': { - 'Gerund': 'running', - 'PastTense': 'ran', - 'Participle': 'run' - }, - 'say': { - 'PastTense': 'said', - 'Participle': 'said', - 'PresentTense': 'says' - }, - 'see': { - 'PastTense': 'saw', - 'Participle': 'seen', - 'Gerund': 'seeing' - }, - 'sell': { - 'PastTense': 'sold', - 'Participle': 'sold' - }, - 'shine': { - 'PastTense': 'shone', - 'Participle': 'shone' - }, - 'shoot': { - 'PastTense': 'shot', - 'Participle': 'shot' - }, - 'show': { - 'PastTense': 'showed' - }, - 'sing': { - 'PastTense': 'sang', - 'Participle': 'sung' - }, - 'sink': { - 'PastTense': 'sank', - 'PluPerfectTense': 'had sunk' - }, - 'sit': { - 'PastTense': 'sat' - }, - 'slide': { - 'PastTense': 'slid', - 'Participle': 'slid' - }, - 'speak': { - 'PastTense': 'spoke', - 'PerfectTense': 'have spoken', - 'PluPerfectTense': 'had spoken', - 'FuturePerfect': 'will have spoken', - 'Participle': 'spoken' - }, - 'spin': { - 'Gerund': 'spinning', - 'PastTense': 'spun', - 'Participle': 'spun' - }, - 'stand': { - 'PastTense': 'stood' - }, - 'steal': { - 'PastTense': 'stole', - 'Actor': 'stealer' - }, - 'stick': { - 'PastTense': 'stuck' - }, - 'sting': { - 'PastTense': 'stung' - }, - 'stream': { - 'Actor': 'streamer' - }, - 'strike': { - 'Gerund': 'striking', - 'PastTense': 'struck' - }, - 'swear': { - 'PastTense': 'swore' - }, - 'swim': { - 'PastTense': 'swam', - 'Gerund': 'swimming' - }, - 'swing': { - 'PastTense': 'swung' - }, - 'teach': { - 'PastTense': 'taught', - 'PresentTense': 'teaches' - }, - 'tear': { - 'PastTense': 'tore' - }, - 'tell': { - 'PastTense': 'told' - }, - 'think': { - 'PastTense': 'thought' - }, - 'understand': { - 'PastTense': 'understood' - }, - 'wake': { - 'PastTense': 'woke' - }, - 'wear': { - 'PastTense': 'wore' - }, - 'win': { - 'Gerund': 'winning', - 'PastTense': 'won' - }, - 'withdraw': { - 'PastTense': 'withdrew' - }, - 'write': { - 'Gerund': 'writing', - 'PastTense': 'wrote', - 'Participle': 'written' - }, - 'tie': { - 'Gerund': 'tying', - 'PastTense': 'tied' - }, - 'ski': { - 'PastTense': 'skiied' - }, - 'boil': { - 'Actor': 'boiler' - }, - 'miss': { - 'PresentTense': 'miss' - }, - 'act': { - 'Actor': 'actor' - }, - 'compete': { - 'Gerund': 'competing', - 'PastTense': 'competed', - 'Actor': 'competitor' - }, - 'being': { - 'Gerund': 'are', - 'PastTense': 'were', - 'PresentTense': 'are' - }, - 'imply': { - 'PastTense': 'implied', - 'PresentTense': 'implies' - }, - 'ice': { - 'Gerund': 'icing', - 'PastTense': 'iced' - }, - 'develop': { - 'PastTense': 'developed', - 'Actor': 'developer', - 'Gerund': 'developing' - }, - 'wait': { - 'Gerund': 'waiting', - 'PastTense': 'waited', - 'Actor': 'waiter' - }, - 'aim': { - 'Actor': 'aimer', - 'Gerund': 'aiming', - 'PastTense': 'aimed' - }, - 'spill': { - 'PastTense': 'spilt', - 'Participle': 'spilled' - }, - 'drop': { - 'Gerund': 'dropping', - 'PastTense': 'dropped' - }, - 'log': { - 'Gerund': 'logging', - 'PastTense': 'logged' - }, - 'rub': { - 'Gerund': 'rubbing', - 'PastTense': 'rubbed' - }, - 'smash': { - 'PresentTense': 'smashes' - }, - 'egg': { - 'PastTense': 'egged' - }, - 'suit': { - 'Gerund': 'suiting', - 'PastTense': 'suited', - 'Actor': 'suiter' - }, - 'age': { - 'PresentTense': 'ages', - 'PastTense': 'aged', - 'Gerund': 'ageing' - }, - 'shed': { - 'PresentTense': 'sheds', - 'PastTense': 'shed', - 'Gerund': 'shedding' - }, - 'break': { - 'PastTense': 'broke' - }, - 'catch': { - 'PastTense': 'caught' - }, - 'do': { - 'PastTense': 'did', - 'PresentTense': 'does' - }, - 'bind': { - 'PastTense': 'bound' - }, - 'spread': { - 'PastTense': 'spread' - }, - 'become': { - 'Participle': 'become' - }, - 'bend': { - 'Participle': 'bent' - }, - 'brake': { - 'Participle': 'broken' - }, - 'burn': { - 'Participle': 'burned' - }, - 'burst': { - 'Participle': 'burst' - }, - 'cling': { - 'Participle': 'clung' - }, - 'come': { - 'Participle': 'come', - 'PastTense': 'came' - }, - 'creep': { - 'Participle': 'crept' - }, - 'cut': { - 'Participle': 'cut' - }, - 'dive': { - 'Participle': 'dived' - }, - 'dream': { - 'Participle': 'dreamt' - }, - 'flee': { - 'Participle': 'fled', - 'Gerund': 'fleeing', - }, - 'fling': { - 'Participle': 'flung' - }, - 'got': { - 'Participle': 'gotten' - }, - 'grow': { - 'Participle': 'grown' - }, - 'hit': { - 'Participle': 'hit' - }, - 'keep': { - 'Participle': 'kept' - }, - 'kneel': { - 'Participle': 'knelt' - }, - 'know': { - 'Participle': 'known' - }, - 'leap': { - 'Participle': 'leapt' - }, - 'lend': { - 'Participle': 'lent' - }, - 'loose': { - 'Participle': 'lost' - }, - 'prove': { - 'Participle': 'proven' - }, - 'put': { - 'Participle': 'put' - }, - 'quit': { - 'Participle': 'quit' - }, - 'ride': { - 'Participle': 'ridden' - }, - 'seek': { - 'Participle': 'sought' - }, - 'send': { - 'Participle': 'sent' - }, - 'set': { - 'Participle': 'set' - }, - 'sew': { - 'Participle': 'sewn' - }, - 'shake': { - 'Participle': 'shaken' - }, - 'shave': { - 'Participle': 'shaved' - }, - 'shut': { - 'Participle': 'shut' - }, - 'seat': { - 'Participle': 'sat' - }, - 'slay': { - 'Participle': 'slain' - }, - 'sleep': { - 'Participle': 'slept' - }, - 'sneak': { - 'Participle': 'snuck' - }, - 'speed': { - 'Participle': 'sped' - }, - 'spend': { - 'Participle': 'spent' - }, - 'spit': { - 'Participle': 'spat' - }, - 'split': { - 'Participle': 'split' - }, - 'spring': { - 'Participle': 'sprung' - }, - 'stink': { - 'Participle': 'stunk', - 'PastTense': 'stunk' - }, - 'strew': { - 'Participle': 'strewn' - }, - 'sware': { - 'Participle': 'sworn' - }, - 'sweep': { - 'Participle': 'swept' - }, - 'thrive': { - 'Participle': 'thrived' - }, - 'undergo': { - 'Participle': 'undergone' - }, - 'upset': { - 'Participle': 'upset' - }, - 'weave': { - 'Participle': 'woven' - }, - 'weep': { - 'Participle': 'wept' - }, - 'wind': { - 'Participle': 'wound' - }, - 'wring': { - 'Participle': 'wrung' - } -}; diff --git a/data/dates/months.js b/data/dates/months.js new file mode 100644 index 000000000..2515897e5 --- /dev/null +++ b/data/dates/months.js @@ -0,0 +1,13 @@ +module.exports = [ + 'january', + 'february', + 'april', + 'june', + 'july', + 'august', + 'september', + 'october', + 'november', + 'december', + //abbreviations are elsewhere +] diff --git a/data/dates/weekdays.js b/data/dates/weekdays.js new file mode 100644 index 000000000..5543eb997 --- /dev/null +++ b/data/dates/weekdays.js @@ -0,0 +1,23 @@ +module.exports = [ + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', + 'sunday', + 'mon', + 'tues', + 'wed', + 'thurs', + 'fri', + 'sat', + 'sun', + 'mondays', + 'tuesdays', + 'wednesdays', + 'thursdays', + 'fridays', + 'saturdays', + 'sundays', +] diff --git a/data/index.js b/data/index.js index 2de3e19e6..e05f4313a 100644 --- a/data/index.js +++ b/data/index.js @@ -1,10 +1,71 @@ -//this is our default data in the same form as a plugin -// it is compressed, like a plugin, and written into ./src/world -// when you change it, do `npm run pack` - to see it applied -module.exports = { - words: require('./words'), - conjugations: require('./conjugations'), - plurals: require('./plurals'), - patterns: require('./patterns'), - regex: require('./regex'), -}; +//directory of files to pack with `node scripts/pack.js` +//they are stored in compressed form +const lex = require('./misc') + +//add-in the generic, flat word-lists +const data = [ + //nouns + [require('./nouns/singulars'), 'Singular'], + [require('./nouns/professions'), 'Actor'], + [require('./nouns/sportsTeams'), 'SportsTeam'], + [require('./nouns/uncountables'), 'Uncountable'], + [require('./nouns/pronouns'), 'Pronoun'], + // [require('./nouns/relative-prounoun'), 'Noun'], + [require('./nouns/organizations'), 'Organization'], + [require('./nouns/demonyms'), 'Demonym'], + [require('./nouns/possessives'), 'Possessive'], //+pronoun? + [require('./misc/currencies'), 'Currency'], + [require('./numbers/units'), 'Unit'], + + [require('./places/countries'), 'Country'], + [require('./places/regions'), 'Region'], + [require('./places/places'), 'Place'], + [require('./places/cities'), 'City'], + //dates + [require('./dates/weekdays'), 'WeekDay'], + [require('./dates/months'), 'Month'], + //people + [require('./people/firstnames'), 'FirstName'], + [require('./people/lastnames'), 'LastName'], + [require('./people/maleNames'), 'MaleName'], + [require('./people/femaleNames'), 'FemaleName'], + [require('./people/honorifics'), 'Honorific'], + [require('./people/people'), 'Person'], + //verbs + [require('./verbs/infinitives'), 'Infinitive'], + [require('./verbs/verbs'), 'Verb'], + [require('./verbs/phrasals'), 'PhrasalVerb'], + [require('./verbs/modals'), 'Modal'], + //adjectives + [require('./adjectives/adjectives'), 'Adjective'], + [require('./adjectives/comparables'), 'Comparable'], + //numbers + [require('./numbers/ordinals'), ['TextValue', 'Ordinal']], + [require('./numbers/cardinals'), ['TextValue', 'Cardinal']], + //abbreviations + [require('./abbreviations/nouns'), ['Abbreviation', 'Noun']], + [require('./abbreviations/honorifics'), ['Abbreviation', 'Honorific']], + [require('./abbreviations/months'), ['Abbreviation', 'Month']], + [require('./abbreviations/organizations'), ['Abbreviation', 'Organization']], + [require('./abbreviations/places'), ['Abbreviation', 'Place']], + //misc + [require('./misc/adverbs'), 'Adverb'], + [require('./misc/expressions'), 'Expression'], + [require('./misc/prepositions'), 'Preposition'], + [require('./misc/determiners'), 'Determiner'], + [require('./misc/conjunctions'), 'Conjunction'], +] +for (let i = 0; i < data.length; i++) { + const list = data[i][0] + for (let o = 0; o < list.length; o++) { + //log duplicates + // if (lex[list[o]]) { + // console.log(list[o] + ' ' + lex[list[o]] + ' ' + data[i][1]) + // } + lex[list[o]] = data[i][1] + } +} + +module.exports = lex +// console.log(Object.keys(lex).length); +// console.log(lex['zero']) diff --git a/data/misc.js b/data/misc.js new file mode 100644 index 000000000..cc61a7fd4 --- /dev/null +++ b/data/misc.js @@ -0,0 +1,64 @@ +module.exports = { + better: 'Comparative', + earlier: 'Superlative', + sounds: 'PresentTense', + + 'a few': 'Value', + + here: 'Noun', + 'no doubt': 'Noun', + + was: ['Copula', 'PastTense'], + is: ['Copula', 'PresentTense'], + were: ['Copula', 'PastTense'], + am: 'Copula', + are: 'Copula', + + if: 'Condition', + unless: 'Condition', + + said: 'PastTense', + had: 'PastTense', + been: 'PastTense', + began: 'PastTense', + came: 'PastTense', + did: 'PastTense', + meant: 'PastTense', + went: 'PastTense', + taken: 'PastTense', + + going: 'Gerund', + being: 'Gerund', + according: 'Gerund', + resulting: 'Gerund', + developing: 'Gerund', + staining: 'Gerund', + + no: 'Negative', + non: 'Negative', + never: 'Negative', + not: ['Negative'], //, 'Verb' + + where: 'QuestionWord', + why: 'QuestionWord', + when: 'QuestionWord', + who: 'QuestionWord', + whom: 'QuestionWord', + whose: 'QuestionWord', + what: 'QuestionWord', + which: 'QuestionWord', + "how's": 'QuestionWord', + 'how come': 'QuestionWord', + + //misc + records: 'Plural', + '&': 'Conjunction', + + //pronouns + i: ['Pronoun', 'Singular'], + he: ['Pronoun', 'Singular'], + she: ['Pronoun', 'Singular'], + it: ['Pronoun', 'Singular'], + they: ['Pronoun', 'Plural'], + we: ['Pronoun', 'Plural'], +} diff --git a/data/words/adverbs.js b/data/misc/adverbs.js similarity index 96% rename from data/words/adverbs.js rename to data/misc/adverbs.js index 278a23414..3ac7dff68 100644 --- a/data/words/adverbs.js +++ b/data/misc/adverbs.js @@ -1,5 +1,4 @@ module.exports = [ - // 'now', 'a lot', 'a posteriori', 'abroad', @@ -34,14 +33,14 @@ module.exports = [ 'for good', 'for sure', 'forever', - 'further', 'fully', + 'further', 'furthermore', 'hence', 'indeed', 'instead', - 'just', 'just about', + 'just', 'kinda', 'maybe', 'meanwhile', @@ -49,12 +48,13 @@ module.exports = [ 'moreover', 'newly', 'no longer', + 'not only', 'not withstanding', 'of course', 'often', - 'once', 'once again', 'once more', + 'once', 'only', 'par excellence', 'per se', @@ -81,8 +81,6 @@ module.exports = [ 'upwards of', 'very', 'way', - // 'well', - 'yes', 'yep', - 'not only' -]; + 'yes', +] diff --git a/data/words/conjunctions.js b/data/misc/conjunctions.js similarity index 93% rename from data/words/conjunctions.js rename to data/misc/conjunctions.js index 23ff65c32..ddf7d2d19 100644 --- a/data/words/conjunctions.js +++ b/data/misc/conjunctions.js @@ -7,7 +7,6 @@ module.exports = [ 'before', 'but', 'cuz', - //'for', 'how', 'however', 'in case', @@ -19,11 +18,11 @@ module.exports = [ 'provided that', 'supposing', 'therefore', - 'to', 'tho', 'though', + 'to', 'versus', 'whether', 'while', - 'yet' -]; + 'yet', +] diff --git a/data/words/currencies.js b/data/misc/currencies.js similarity index 96% rename from data/words/currencies.js rename to data/misc/currencies.js index 678266ecf..1ec8a9d4c 100644 --- a/data/words/currencies.js +++ b/data/misc/currencies.js @@ -1,97 +1,96 @@ module.exports = [ - 'usd', - 'cad', - 'nis', - 'ils' - 'aud', - 'gbp', - 'krw', - 'inr', - 'hkd', - 'dkk', - 'cny', - 'xaf', - 'xof', - 'eur', - 'jpy', - '€', + '¢', '$', - '¥', '£', - 'лв', + '¥', + '฿', '₡', - 'kn', - 'kr', - '¢', - 'Ft', - 'Rp', - '﷼', + '€', '₭', - 'ден', '₨', - 'zł', - 'lei', - 'руб', - '฿', - 'denar', - 'dobra', - 'forint', - 'kwanza', - 'kyat', - 'lempira', - 'pound sterling', - 'riel', - 'yen', - 'zloty', - 'dollar', + '﷼', + 'aud', + 'baht', + 'bitcoin', + 'bitcoins', + 'cad', 'cent', - 'penny', + 'cents', + 'cny', + 'denar', + 'denars', 'dime', + 'dimes', 'dinar', - 'euro', - 'lira', - 'pound', - 'pence', - 'peso', - 'baht', - 'sterling', - 'rouble', - 'shekel', - 'sheqel', - 'yuan', - 'franc', - 'rupee', - 'shilling', - 'krona', + 'dinars', 'dirham', - 'bitcoin', - 'denars', + 'dirhams', + 'dkk', + 'dobra', 'dobras', + 'dollar', + 'dollars', + 'eur', + 'euro', + 'euros', + 'forint', 'forints', + 'franc', + 'francs', + 'gbp', + 'hkd', + 'inr', + 'jpy', + 'kn', + 'kr', + 'nis', + 'ils', + 'krona', + 'kronas', + 'krw', + 'kwanza', 'kwanzas', + 'kyat', 'kyats', + 'lei', + 'lempira', 'lempiras', - 'pound sterlings', - 'zlotys', - 'dollars', - 'cents', - 'pennies', - 'dimes', - 'dinars', - 'euros', + 'lira', 'liras', - 'pounds', + 'pence', 'pences', + 'pennies', + 'penny', + 'peso', 'pesos', - 'sterlings', + 'pound sterling', + 'pound sterlings', + 'pound', + 'pounds', + 'riel', + 'rouble', 'roubles', + 'rp', + 'rupee', + 'rupees', + 'shekel', 'shekels', + 'sheqel', 'sheqels', - 'yuans', - 'francs', - 'rupees', + 'shilling', 'shillings', - 'kronas', - 'dirhams', - 'bitcoins' -]; + 'sterling', + 'sterlings', + 'usd', + 'xaf', + 'xof', + 'yen', + 'yuan', + 'yuans', + 'zł', + 'zloty', + 'zlotys', + 'ден', + 'лв', + 'руб', +] diff --git a/data/words/determiners.js b/data/misc/determiners.js similarity index 97% rename from data/words/determiners.js rename to data/misc/determiners.js index 4c0262b0c..b06753c79 100644 --- a/data/words/determiners.js +++ b/data/misc/determiners.js @@ -1,29 +1,29 @@ module.exports = [ - 'this', + 'a', + 'an', + 'another', 'any', - 'enough', + 'both', 'each', - 'whatever', + 'either', + 'else', + 'enough', 'every', - 'these', - 'another', - 'plenty', - 'whichever', - 'neither', - 'an', - 'a', + 'few', 'least', + 'much', + 'neither', 'own', - 'few', - 'both', - 'those', - 'the', + 'plenty', + 'some', 'that', + 'the', + 'these', + 'this', + 'those', 'various', - 'either', - 'much', - 'some', - 'else', + 'whatever', + 'whichever', //some other languages (what could go wrong?) 'la', 'le', @@ -31,5 +31,5 @@ module.exports = [ 'des', 'de', 'du', - 'el' -]; + 'el', +] diff --git a/data/words/expressions.js b/data/misc/expressions.js similarity index 96% rename from data/words/expressions.js rename to data/misc/expressions.js index 288013fc8..74e7626da 100644 --- a/data/words/expressions.js +++ b/data/misc/expressions.js @@ -18,8 +18,8 @@ module.exports = [ 'eww', 'fuck', 'gah', - 'golly', 'gee', + 'golly', 'goodbye', 'grr', 'haha', @@ -31,6 +31,8 @@ module.exports = [ 'hey', 'hi', 'hmm', + 'holy moly', + 'holy', 'hurrah', 'lmao', 'lmfao', @@ -75,7 +77,5 @@ module.exports = [ 'yeah', 'yuck', 'yup', - 'd\'oh', - 'holy', - 'holy moly' -]; + "d'oh", +] diff --git a/data/words/prepositions.js b/data/misc/prepositions.js similarity index 89% rename from data/words/prepositions.js rename to data/misc/prepositions.js index 9098bb7b9..95949c582 100644 --- a/data/words/prepositions.js +++ b/data/misc/prepositions.js @@ -1,8 +1,6 @@ module.exports = [ - '\'o', - 'a\'', + '-', //june - july 'about', - 'bout', 'across', 'after', 'along', @@ -12,14 +10,15 @@ module.exports = [ 'amongst', 'apropos', 'around', - 'as', 'as long as', + 'as', 'at', 'atop', 'barring', 'below', 'besides', 'between', + 'bout', 'by', 'chez', 'circa', @@ -27,15 +26,13 @@ module.exports = [ 'down', 'during', 'except', - 'from', 'for', + 'from', 'in', 'into', - // 'just like', 'mid', 'midst', 'notwithstanding', - 'o\'', 'of', 'off', 'on', @@ -51,7 +48,6 @@ module.exports = [ 'throughout', 'thru', 'till', - // 'to', 'towards', 'unlike', 'until', @@ -65,5 +61,7 @@ module.exports = [ 'with', 'within', 'without', - '-' //june - july -]; + "'o", + "a'", + "o'", +] diff --git a/data/words/nouns/demonyms.js b/data/nouns/demonyms.js similarity index 98% rename from data/words/nouns/demonyms.js rename to data/nouns/demonyms.js index 506f36dfc..01dc6454d 100644 --- a/data/words/nouns/demonyms.js +++ b/data/nouns/demonyms.js @@ -1,22 +1,26 @@ //adjectival forms of place names, as adjectives. module.exports = [ 'afghan', + 'african', 'albanian', 'algerian', + 'american', 'angolan', 'argentine', 'armenian', - 'australian', + 'asian', 'aussie', + 'australian', 'austrian', 'bangladeshi', - 'basque', // of Basque Country 'belarusian', 'belgian', 'bolivian', 'bosnian', 'brazilian', + 'british', 'bulgarian', + 'californian', 'cambodian', 'cameroonian', 'canadian', @@ -28,24 +32,28 @@ module.exports = [ 'croatian', 'cuban', 'czech', - 'dominican', 'danish', + 'dominican', + 'dutch', + 'ecuadorian', 'egyptian', - 'british', + 'english', 'estonian', 'ethiopian', - 'ecuadorian', + 'european', + 'filipino', 'finnish', 'french', 'gambian', 'georgian', 'german', - 'greek', 'ghanaian', + 'greek', 'guatemalan', 'haitian', - 'hungarian', + 'hindi', 'honduran', + 'hungarian', 'icelandic', 'indian', 'indonesian', @@ -68,26 +76,24 @@ module.exports = [ 'liberian', 'libyan', 'lithuanian', - 'namibian', - 'malagasy', // of Madagascar 'macedonian', + 'malagasy', // of Madagascar 'malaysian', 'mexican', 'mongolian', 'moroccan', - 'dutch', + 'namibian', 'nicaraguan', 'nigerian', // of Nigeria 'nigerien', // of Niger 'norwegian', 'omani', - 'panamanian', - 'paraguayan', 'pakistani', 'palestinian', + 'panamanian', + 'paraguayan', 'peruvian', 'philippine', - 'filipino', 'polish', 'portuguese', 'qatari', @@ -102,28 +108,21 @@ module.exports = [ 'singaporean', 'slovak', 'somalian', + 'spanish', 'sudanese', 'swedish', 'swiss', 'syrian', 'taiwanese', - 'trinidadian', 'thai', + 'trinidadian', 'tunisian', 'turkmen', 'ugandan', 'ukrainian', - 'american', - 'hindi', - 'spanish', 'venezuelan', 'vietnamese', 'welsh', 'zambian', 'zimbabwean', - 'english', - 'african', - 'european', - 'asian', - 'californian', -]; +] diff --git a/data/nouns/organizations.js b/data/nouns/organizations.js new file mode 100644 index 000000000..351afb441 --- /dev/null +++ b/data/nouns/organizations.js @@ -0,0 +1,317 @@ +//just a few named-organizations +//no acronyms needed. no product/brand pollution. +module.exports = [ + 'abc', + 'academy of sciences', + 'acer', + 'activision', + 'adidas', + 'aig', + 'al jazeera', + 'al qaeda', + 'alcatel-lucent', + 'alcatel', + 'altair', + 'amc', + 'amd', + 'american express', + 'amt', + 'amtrak', + 'anheuser-busch', + 'aol', + 'apple computers', + 'argos', + 'armco', + 'ashland oil', + 'associated press', + 'at&t', + 'avis', + 'avon', + 'ayer', + 'banana republic', + 'basf', + 'baskin robbins', + 'baxter', + 'bayer', + 'bbc', + 'bechtel', + 'berkshire hathaway', + 'bf goodrich', + 'bfgoodrich', + 'black & decker', + 'blockbuster video', + 'bloomingdale', + 'blue cross', + 'bmw', + 'bni', + 'boeing', + 'bombardier', + 'boston globe', + 'boston pizza', + 'bp', + 'cadbury', + 'capital one', + 'cbc', + 'chevron', + 'chevy', + 'chick fil-a', + 'china daily', + 'cia', + 'cisco systems', + 'cisco', + 'citigroup', + 'cnn', + 'coca cola', + 'colgate', + 'comcast', + 'compaq', + 'coors', + 'costco', + 'craigslist', + 'crossrail', + 'daimler', + 'dea', + 'dell', + 'der spiegel', + 'disney', + 'doj', + 'dow jones', + 'dunkin donuts', + 'dupont', + 'ebay', + 'esa', + 'eu', + 'exxon mobil', + 'exxonmobil', + 'facebook', + 'fannie mae', + 'fbi', + 'fda', + 'fedex', + 'fiat', + 'financial times', + 'firestone', + 'ford', + 'frito-lay', + 'general electric', + 'general motors', + 'gmb', + 'ghq', + 'glaxo smith kline', + 'glencore', + 'goldman sachs', + 'goodyear', + 'google', + 'gucci', + 'h & m', + 'hasbro', + 'hewlett-packard', + 'hitachi', + 'hizbollah', + 'home depot', + 'honda', + 'hsbc', + 'hyundai', + 'ibm', + 'ihop', + 'ing', + 'intel', + 'interpol', + 'itv', + 'jiffy lube', + 'johnson & johnson', + 'jpmorgan chase', + 'jpmorgan', + 'jsa', + 'katv', + 'kfc', + 'kkk', + 'kmart', + 'kodak', + 'la presse', + 'la-z-boy', + 'labour party', + 'lenovo', + 'lexis', + 'lexmark', + 'lg', + 'little caesars', + 'mattel', + 'mazda', + 'mcdonalds', + 'medicaid', + 'medicare', + 'mercedes-benz', + 'mercedes', + 'microsoft', + 'mitas', + 'mitsubishi', + 'mlb', + 'mobil', + 'monsanto', + 'motorola', + 'mtv', + 'myspace', + 'nandos', + 'nasa', + 'nascar', + 'nasdaq', + 'national academy of sciences', + 'nato', + 'natwest', + 'nba', + 'nbc', + 'nec', + 'nestle', + 'netflix', + 'new york times', + 'newsweek', + 'nfl', + 'nhl', + 'nhs', + 'nike', + 'nintendo', + 'nissan', + 'nokia', + 'notre dame', + 'novartis', + 'nsa', + 'nwa', + 'old navy', + 'opec', + 'orange julius', + 'oxfam', + 'pan am', + 'panasonic', + 'panda express', + 'pbs', + 'pepsico', + 'petrobras', + 'petrochina', + 'petronas', + 'peugeot', + 'pfizer', + 'philip morris', + 'pizza hut', + 'premier oil', + 'procter & gamble', + 'prudential', + 'quantas', + 'rbc', + 'rbs', + 're/max', + 'readers digest', + 'red bull', + 'red cross', + 'red lobster', + 'revlon', + 'royal bank', + 'royal dutch shell', + 'ryanair', + 'safeway', + 'samsung', + 'sears', + 'siemens', + 'snp', + 'sony', + 'starbucks', + 'statoil', + 'subaru', + 't mobile', + 'taco bell', + 'td bank', + 'telefonica', + 'telus', + 'tesco', + 'tesla motors', + 'tgi fridays', + 'the daily mail', + 'tim hortons', + 'tmz', + 'toshiba', + 'toyota', + 'toys r us', + 'twitter', + 'ubs', + 'ukip', + 'unesco', + 'unilever', + 'united nations', + 'ups', + 'usa today', + 'usps', + 'verizon', + 'visa', + 'vodafone', + 'volkswagen', + 'volvo', + 'wal-mart', + 'walgreens', + 'wall street journal', + 'walmart', + 'warner bros', + 'wells fargo', + 'westfield', + 'westinghouse', + 'world trade organization', + 'yahoo!', + 'yamaha', + 'ymca', + 'yougov', + 'youtube', + 'ywca', + "applebee's", + "arby's", + "ben & jerry's", + "carl's jr", + "l'oreal", + "mac's milk", + "mcdonald's", + "quizno's", + "sainsbury's", + + //some bands + 'abba', + 'ac/dc', + 'aerosmith', + 'bee gees', + 'coldplay', + 'creedence clearwater revival', + 'def leppard', + 'depeche mode', + 'duran duran', + 'fleetwood mac', + 'green day', + 'guns n roses', + 'joy division', + 'metallica', + 'moody blues', + 'motley crue', + 'new kids on the block', + 'pink floyd', + 'r.e.m.', + 'radiohead', + 'red hot chili peppers', + 'sex pistols', + 'soundgarden', + 'spice girls', + 'the beach boys', + 'the beatles', + 'the black eyed peas', + 'the byrds', + 'the carpenters', + 'the guess who', + 'the hollies', + 'the rolling stones', + 'the smashing pumpkins', + 'the supremes', + 'the who', + 'thin lizzy', + 'u2', + 'van halen', + "destiny's child", + + // other groups + 'eurosceptics', + 'brexiteers', +] diff --git a/data/nouns/possessives.js b/data/nouns/possessives.js new file mode 100644 index 000000000..1f5b22b9a --- /dev/null +++ b/data/nouns/possessives.js @@ -0,0 +1,22 @@ +module.exports = [ + 'anyone', + 'anything', + 'her', //this one is check ambiguous + 'hers', + 'herself', + 'himself', + 'his', + 'its', + 'mine', + 'my', + 'myself', + 'none', + 'our', + 'ours', + 'something', + 'their', + 'theirs', + 'themselves', + 'your', + 'yours', +] diff --git a/data/words/nouns/professions.js b/data/nouns/professions.js similarity index 97% rename from data/words/nouns/professions.js rename to data/nouns/professions.js index 3c8183ca6..ffdb63751 100644 --- a/data/words/nouns/professions.js +++ b/data/nouns/professions.js @@ -49,5 +49,5 @@ module.exports = [ 'supervisor', 'surgeon', 'technician', - 'therapist' -]; + 'therapist', +] diff --git a/data/words/nouns/pronouns.js b/data/nouns/pronouns.js similarity index 93% rename from data/words/nouns/pronouns.js rename to data/nouns/pronouns.js index 63d9fa66e..f81e04da2 100644 --- a/data/words/nouns/pronouns.js +++ b/data/nouns/pronouns.js @@ -17,5 +17,5 @@ module.exports = [ 'yourself', "'em", "he's", - "she's" -]; + "she's", +] diff --git a/data/nouns/relative-prounoun.js b/data/nouns/relative-prounoun.js new file mode 100644 index 000000000..feddeee7c --- /dev/null +++ b/data/nouns/relative-prounoun.js @@ -0,0 +1,17 @@ +module.exports = [ + 'whatever', + 'whatsoever', + 'whichever', + 'whichsoever', + 'whoever', + 'whom', + 'whomever', + 'whomsoever', + 'whose', + 'whosesoever', + 'whosoever', + // 'that', + // 'when', + // 'which', + // 'who', +] diff --git a/data/nouns/singulars.js b/data/nouns/singulars.js new file mode 100644 index 000000000..fa07a43d3 --- /dev/null +++ b/data/nouns/singulars.js @@ -0,0 +1,143 @@ +//most nouns do not nead to be listed +//for whatever reasons, these look like not-nouns +// //so we make sure that they become nouns +// const toPlural = require('../../text/subset/nouns/methods/pluralize'); + +module.exports = [ + 'ad hominem', + 'banking', + 'body', + 'boyfriend', + 'breakfast', + 'canary', + 'ceiling', + 'chocolate', + 'city', + 'civil war', + 'credit card', + 'death', + 'dinner', + 'documentary', + 'door', + 'economy', + 'energy', + 'event', + 'example', + 'friend', + 'girlfriend', + 'glacier', + 'god', + 'grand slam', + 'head start', + 'home run', + 'home', + 'house', + 'lunch', + 'meeting', + 'model', + 'nothing', + 'number', + 'ocean', + 'others', + 'part', + 'patent', + 'problem', + 'purpose', + 'question mark', + 'room', + 'rose', + 'sky', + 'student', + 'stuff', + 'string', + 'super bowl', + 'system', + 't rex', + 'tax return', + 'there', + 'thing', + 'tic', + 'tragedy', + 'tv show', + 'us dollar', + 'us state', + + //double-consonant rule + 'bottle', + 'cottage', + 'doggy', + 'egg', + 'kitty', + + //.ing + 'advertising', + 'blessing', + 'bunting', + 'frosting', + 'funding', + 'icing', + 'pudding', + 'ring', + + //..ly rule + 'ally', + 'anomaly', + 'belly', + 'butterfly', + 'doily', + 'dolly', + 'dragonfly', + 'family', + 'fly', + 'folly', + 'gadfly', + 'gully', + 'holly', + 'jelly', + 'lily', + 'mayfly', + 'monopoly', + 'rally', + 'tally', + + //...ier + 'barrier', + 'carrier', + 'chandelier', + 'courier', + 'frontier', + 'pier', + + //..tive + 'detective', + 'executive', + 'prerogative', + 'objective', + + //family-words are notpeople + 'aunt', + 'boy', + 'bro', + 'brother', + 'cousin', + 'dad', + 'daddy', + 'dude', + 'father', + 'fella', + 'gentleman', + 'girl', + 'grandfather', + 'grandmother', + 'guy', + 'man', + 'mom', + 'mommy', + 'mother', + 'sister', + 'someone', + 'stepfather', + 'stepmother', + 'uncle', + 'woman', +] diff --git a/data/words/nouns/sportsTeams.js b/data/nouns/sportsTeams.js similarity index 95% rename from data/words/nouns/sportsTeams.js rename to data/nouns/sportsTeams.js index 7b283f375..cf97a4006 100644 --- a/data/words/nouns/sportsTeams.js +++ b/data/nouns/sportsTeams.js @@ -1,51 +1,42 @@ module.exports = [ //mlb - 'washington nationals', - 'toronto blue jays', - 'texas rangers', - 'tampa bay rays', - 'st. louis cardinals', - 'seattle mariners', - 'san francisco giants', - 'san diego padres', - 'pittsburgh pirates', - 'philadelphia phillies', - 'oakland athletics', - 'new york yankees', - 'new york mets', - 'minnesota twins', - 'milwaukee brewers', - 'miami marlins', - 'los angeles dodgers', - 'kansas city royals', - 'houston astros', - 'detroit tigers', - 'colorado rockies', - 'cleveland indians', - 'cincinnati reds', - 'chicago white sox', - 'chicago cubs', - 'boston red sox', - 'baltimore orioles', - 'atlanta braves', 'arizona diamondbacks', + 'atlanta braves', + 'baltimore orioles', + 'boston red sox', + 'chicago cubs', + 'chicago white sox', + 'cincinnati reds', + 'cleveland indians', + 'colorado rockies', + 'detroit tigers', + 'houston astros', + 'kansas city royals', + 'los angeles dodgers', + 'miami marlins', + 'milwaukee brewers', + 'minnesota twins', + 'new york mets', + 'new york yankees', + 'oakland athletics', + 'philadelphia phillies', + 'pittsburgh pirates', + 'san diego padres', + 'san francisco giants', + 'seattle mariners', + 'st. louis cardinals', + 'tampa bay rays', + 'texas rangers', + 'toronto blue jays', + 'washington nationals', 'diamondbacks', - 'braves', - 'orioles', 'white sox', 'astros', - 'royals', 'dodgers', - 'marlins', - 'brewers', 'mets', 'yankees', 'phillies', 'padres', - 'giants', - 'mariners', - 'cardinals', - 'blue jays', //nba 'boston celtics', @@ -78,78 +69,76 @@ module.exports = [ 'los angeles lakers', 'phoenix suns', 'sacramento kings', - '76ers', 'knicks', - 'mavericks', 'lakers', 'celtics', //nfl - 'buffalo bills', - 'miami dolphins', - 'new england patriots', - 'new york jets', + 'arizona cardinals', + 'atlanta falcons', 'baltimore ravens', + 'buffalo bills', + 'carolina panthers', + 'chicago bears', 'cincinnati bengals', 'cleveland browns', - 'pittsburgh steelers', + 'dallas cowboys', + 'denver broncos', + 'detroit lions', + 'green bay packers', 'houston texans', 'indianapolis colts', 'jacksonville jaguars', - 'tennessee titans', - 'denver broncos', 'kansas city chiefs', - 'oakland raiders', - 'san diego chargers', - 'dallas cowboys', - 'new york giants', - 'philadelphia eagles', - 'washington redskins', - 'chicago bears', - 'detroit lions', - 'green bay packers', + 'miami dolphins', 'minnesota vikings', - 'atlanta falcons', - 'carolina panthers', + 'new england patriots', 'new orleans saints', - 'tampa bay buccaneers', - 'arizona cardinals', - 'st. louis rams', + 'new york giants', + 'new york jets', + 'oakland raiders', + 'philadelphia eagles', + 'pittsburgh steelers', + 'san diego chargers', 'san francisco 49ers', 'seattle seahawks', + 'st. louis rams', + 'tampa bay buccaneers', + 'tennessee titans', + 'washington redskins', //mls + 'atlanta united', 'chicago fire', + 'colorado rapids', 'columbus crew sc', 'd.c. united', + 'fc dallas', + 'houston dynamo', + 'la galaxy', + 'minnesota united', 'montreal impact', 'new england revolution', 'new york city fc', 'new york red bulls', 'philadelphia union', - 'colorado rapids', - 'fc dallas', - 'houston dynamo', - 'la galaxy', 'portland timbers', 'real salt lake', 'san jose earthquakes', 'seattle sounders', 'sporting kansas city', 'vancouver whitecaps', - 'atlanta united', - 'minnesota united', //premier league soccer (mostly city+fc) + 'aston villa', 'blackburn rovers', + 'cardiff city', 'leicester city', 'manchester city', 'manchester united', - 'aston villa', - 'cardiff city', 'newcastle united', 'queens park rangers', 'sheffield united', 'stoke city', 'tottenham hotspur', 'west ham united', -]; +] diff --git a/data/words/nouns/uncountables.js b/data/nouns/uncountables.js similarity index 82% rename from data/words/nouns/uncountables.js rename to data/nouns/uncountables.js index b277e6af2..a5ce216dc 100644 --- a/data/words/nouns/uncountables.js +++ b/data/nouns/uncountables.js @@ -2,35 +2,46 @@ //used in noun.inflect(), and added as nouns in lexicon module.exports = [ 'acid', + 'acoustics', 'advice', + 'aerobics', + 'aerodynamics', + 'aeronautics', 'aircraft', 'amnesty', 'art', + 'athletics', 'baggage', 'bass', 'beef', + 'billiards', 'bison', 'blood', + 'bowls', 'bread', 'butter', - 'cake', + 'cards', 'cash', 'celcius', 'chaos', 'cheese', 'chewing', 'civics', + 'classics', 'clothing', 'coal', - 'coffee', 'conduct', 'confusion', 'cotton', 'cold war', 'currency', + 'darts', + 'diabetes', + 'draughts', 'economics', 'education', 'electricity', + 'electronics', 'enjoyment', 'entertainment', 'equipment', @@ -44,9 +55,10 @@ module.exports = [ 'flour', 'food', 'forgiveness', + 'fourier', 'fowl', - 'fruit', 'furniture', + 'genetics', 'gold', 'golf', 'gossip', @@ -75,45 +87,47 @@ module.exports = [ 'laughter', 'leather', 'leisure', + 'lice', 'lightning', - 'liquid', + 'linguistics', 'literature', + 'logistics', 'luck', 'luggage', + 'machine learning', 'machinery', 'mail', - 'machine learning', 'mathematics', 'measles', 'meat', + 'mechanics', 'milk', - 'mist', 'money', 'moose', 'mumps', 'music', 'news', - 'noise', + 'obstetrics', 'oil', 'oxygen', - 'paper', 'patience', 'peace', - 'peanut', - 'pepper', 'petrol', 'physics', 'plastic', + 'politics', 'pork', 'power', 'pressure', 'progress', + 'rabies', 'rain', 'recognition', 'recreation', 'relaxation', 'research', 'rice', + 'rickets', 'sadness', 'safety', 'salmon', @@ -122,25 +136,25 @@ module.exports = [ 'scenery', 'series', 'sheep', - 'shopping', + 'shingles', 'silk', 'silver', + 'skittles', 'snow', 'soap', 'soccer', - 'softness', - 'space', 'spacecraft', 'species', 'speed', + 'statistics', 'steam', 'steel', 'sugar', 'sunshine', 'tea', 'tennis', + 'thermodynamics', 'thunder', - 'time', 'toothpaste', 'traffic', 'trouble', @@ -149,6 +163,7 @@ module.exports = [ 'tuna', 'vinegar', 'violence', + 'vitae', 'warmth', 'water', 'weather', @@ -156,7 +171,4 @@ module.exports = [ 'wine', 'wood', 'wool', - 'world series', - 'world' -// 'fun', -]; +] diff --git a/data/numbers/cardinals.js b/data/numbers/cardinals.js new file mode 100644 index 000000000..5013e1d94 --- /dev/null +++ b/data/numbers/cardinals.js @@ -0,0 +1,40 @@ +module.exports = [ + 'zero', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'ten', + 'eleven', + 'twelve', + 'thirteen', + 'fourteen', + 'fifteen', + 'sixteen', + 'seventeen', + 'eighteen', + 'nineteen', + 'twenty', + 'thirty', + 'forty', + 'fourty', + 'fifty', + 'sixty', + 'seventy', + 'eighty', + 'ninety', + 'hundred', + 'thousand', + 'million', + 'billion', + 'trillion', + 'quadrillion', + 'quintillion', + 'sextillion', + 'septillion', +] diff --git a/data/numbers/ordinals.js b/data/numbers/ordinals.js new file mode 100644 index 000000000..51dc4448b --- /dev/null +++ b/data/numbers/ordinals.js @@ -0,0 +1,40 @@ +module.exports = [ + 'zeroth', + 'first', + 'second', + 'third', + 'fourth', + 'fifth', + 'sixth', + 'seventh', + 'eighth', + 'ninth', + 'tenth', + 'eleventh', + 'twelfth', + 'thirteenth', + 'fourteenth', + 'fifteenth', + 'sixteenth', + 'seventeenth', + 'eighteenth', + 'nineteenth', + 'twentieth', + 'thirtieth', + 'fortieth', + 'fourtieth', + 'fiftieth', + 'sixtieth', + 'seventieth', + 'eightieth', + 'ninetieth', + 'hundredth', + 'thousandth', + 'millionth', + 'billionth', + 'trillionth', + 'quadrillionth', + 'quintillionth', + 'sextillionth', + 'septillionth', +] diff --git a/data/words/units.js b/data/numbers/units.js similarity index 98% rename from data/words/units.js rename to data/numbers/units.js index 357a267bf..3171b6e3e 100644 --- a/data/words/units.js +++ b/data/numbers/units.js @@ -27,7 +27,7 @@ module.exports = [ 'dl', 'deciliter', 'deciliters', - 'cl', + // 'cl', 'centiliter', 'centiliters', 'ml', @@ -84,7 +84,7 @@ module.exports = [ 'mi', 'mile', 'miles', - 'ft', + 'ft', //ambiguous 'yd', 'yard', 'yards', @@ -237,5 +237,5 @@ module.exports = [ 'attosecond', 'attoseconds', 'percent', - 'years old' -]; + 'years old', +] diff --git a/data/patterns.js b/data/patterns.js deleted file mode 100644 index d7e21e5e2..000000000 --- a/data/patterns.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - 'master of #Noun': 'Person', - 'captain of the #Noun': 'Person', -}; diff --git a/data/words/people/femaleNames.js b/data/people/femaleNames.js similarity index 99% rename from data/words/people/femaleNames.js rename to data/people/femaleNames.js index 06f725536..31c7b8ee6 100644 --- a/data/words/people/femaleNames.js +++ b/data/people/femaleNames.js @@ -1,39 +1,95 @@ //names with a distinctive signal that they identify as a female, internationally module.exports = [ + 'aaliyah', + 'abagail', + 'abbey', + 'abbi', + 'abbie', + 'abby', + 'abi', 'abigail', 'ada', + 'adaline', + 'adalyn', + 'addie', + 'addilyn', + 'addison', + 'adela', + 'adelaide', 'adele', + 'adelene', 'adelia', 'adelina', 'adeline', + 'adelynn', + 'adreanna', 'adriana', + 'adrianna', + 'adrianne', 'adriena', 'adriene', + 'adrienne', + 'agatha', + 'aggie', 'agnes', 'aicha', 'aida', 'aileen', 'aimee', + 'ainsley', 'aisha', 'aishah', + 'aisling', + 'aislinn', + 'aislynn', + 'alaina', + 'alana', + 'alanis', + 'alanna', + 'alannah', + 'alayah', + 'alayna', + 'alba', + 'alecia', + 'aleisha', + 'alejandra', + 'alena', + 'alessandra', + 'alexa', 'alexandra', + 'alexia', + 'alia', 'alice', 'alicia', + 'alina', 'alisa', 'alisha', 'alison', + 'alissa', + 'aliza', + 'allie', + 'allison', + 'allyson', 'alma', 'alta', 'alya', + 'alycia', 'alysa', + 'alyson', 'alyssa', + 'amalia', 'amanda', 'amber', + 'amberly', 'amelia', + 'amie', 'amina', 'amy', 'ana', + 'anabel', + 'anamaria', + 'anastasia', 'andjela', 'andrea', 'ane', @@ -43,134 +99,303 @@ module.exports = [ 'angelica', 'angelina', 'angeline', + 'angelique', + 'angie', 'anika', + 'anisa', + 'anissa', 'anita', 'anja', 'ann', 'anna', + 'annabel', + 'annabelle', + 'annalisa', + 'annamaria', 'anne', + 'annemarie', 'annette', + 'annie', 'annika', + 'annmarie', 'antoinette', 'antonia', + 'anya', + 'ariana', + 'arianna', + 'arianne', + 'arielle', + 'arleen', 'arlena', 'arlene', + 'arlette', 'arpita', + 'asha', + 'ashanti', + 'ashlee', + 'ashleigh', 'ashley', 'ashli', + 'ashlie', 'ashly', + 'ashlyn', + 'ashton', + 'astrid', + 'athena', 'audra', 'audrey', 'audri', 'audry', + 'augustina', + 'aurelia', 'ava', + 'avril', + 'ayana', + 'ayanna', + 'ayesha', 'barbara', + 'barbie', 'barbra', + 'bea', 'beatrice', 'beatriz', 'becky', 'belinda', + 'benita', 'bernadette', + 'bernadine', 'bernice', 'bertha', + 'beryl', + 'bess', + 'bessie', 'beth', + 'bethanie', + 'bethany', + 'betsy', 'bette', + 'bettie', + 'bettina', 'betty', 'bettye', 'beula', 'beulah', + 'bev', + 'beverley', 'beverly', 'bianca', 'blanca', + 'blanche', + 'blossom', + 'blythe', + 'bobbi', + 'bobbie', 'bonita', + 'bonnie', 'brandi', + 'brandie', + 'brandy', + 'breanna', + 'bree', 'brenda', + 'brenna', + 'briana', + 'brianna', + 'brianne', 'bridget', + 'bridgett', 'bridgette', + 'brigid', + 'britney', + 'britt', + 'brittany', 'brittney', 'brittni', 'brittny', + 'bronwyn', + 'brook', 'brooke', + 'bryanna', + 'brynn', 'caitlin', + 'caitlyn', + 'calista', + 'callie', + 'camila', 'camile', + 'camilla', 'camille', 'candace', 'candice', 'cara', + 'carina', + 'carissa', 'carla', + 'carlene', + 'carley', + 'carlie', + 'carly', + 'carmel', 'carmela', + 'carmella', 'carmen', 'carol', 'carole', 'carolina', 'caroline', 'carolyn', + 'carrie', + 'carrol', 'casandra', 'cassandra', + 'cassie', 'catalina', + 'catarina', + 'caterina', 'catherina', 'catherine', 'cathleen', + 'cathryn', 'cathy', + 'catrina', + 'cayla', 'cecelia', 'cecile', 'cecilia', + 'cecily', 'celeste', 'celia', 'celina', 'celine', + 'chandra', + 'chanelle', + 'chantal', + 'chantelle', + 'charis', + 'charissa', + 'charla', 'charlena', 'charlene', + 'charlette', + 'charlotte', + 'charmaine', 'chelsea', + 'chelsey', + 'cher', + 'cheri', + 'cherie', 'cheryl', 'chloe', + 'chrissy', 'christa', + 'christal', + 'christen', + 'christi', + 'christiana', + 'christiane', + 'christie', 'christina', 'christine', + 'christy', + 'chrystal', + 'ciara', + 'cierra', + 'cindi', + 'cindy', + 'clair', 'claire', 'clara', + 'clare', 'clarice', + 'claris', + 'clarissa', 'claudette', 'claudia', + 'claudine', 'cleo', + 'cleopatra', + 'clotilde', 'coleen', + 'colette', 'colleen', + 'connie', 'constance', 'constanza', 'consuelo', 'cora', + 'coral', + 'coralie', + 'cordelia', + 'cori', 'corina', 'corine', 'corinna', 'corinne', 'cornelia', + 'corrine', 'courtney', 'courtni', 'courtny', + 'cristal', 'cristina', 'crystal', + 'cyndi', 'cynthia', + 'dahlia', + 'daina', + 'damaris', 'damia', 'dana', + 'danette', + 'dani', + 'danica', + 'daniela', 'daniele', + 'daniella', 'danielle', + 'danika', 'daphna', 'daphne', + 'dara', + 'darby', + 'darcey', + 'darcie', + 'daria', 'darla', 'darlena', 'darlene', + 'davida', + 'davina', + 'dayle', + 'dayna', 'deana', + 'deandra', + 'deann', 'deanna', + 'deanne', + 'deb', + 'debbie', + 'debby', 'debora', 'deborah', 'debra', + 'dede', 'dee', + 'deedee', + 'deena', + 'deidre', + 'deirdre', + 'deja', 'dela', 'delia', + 'delilah', 'della', 'delores', 'deloris', + 'delphine', + 'demetria', 'dena', + 'denice', 'denise', 'desiree', 'diana', @@ -178,6 +403,9 @@ module.exports = [ 'dianna', 'dianne', 'dina', + 'dinah', + 'dionne', + 'dixie', 'dolores', 'dominique', 'dona', @@ -185,149 +413,281 @@ module.exports = [ 'dora', 'doreen', 'doris', + 'dorla', 'dorothea', 'dorothy', + 'dorthy', + 'dottie', + 'dulce', + 'eden', + 'edie', 'edith', 'edna', + 'edwina', 'eileen', 'ekta', 'elaina', 'elaine', + 'elana', 'eleanor', 'elen', 'elena', + 'eliana', + 'elicia', + 'elida', + 'elin', + 'elina', + 'elinor', 'elisa', 'elisabeth', 'elise', 'eliza', 'elizabeth', + 'ella', 'ellen', + 'ellie', + 'elly', 'elma', + 'elnora', 'eloise', + 'elouise', 'elsa', + 'elsie', 'elva', + 'elvina', 'elvira', + 'emelda', + 'emely', + 'emerald', + 'emilee', + 'emilia', + 'emilie', + 'emily', 'emma', + 'emmaline', + 'emmie', + 'emmy', + 'enid', 'erica', + 'ericka', 'erika', 'erin', 'erma', 'ernestina', 'ernestine', + 'eryn', + 'esmeralda', + 'esperanza', 'estela', 'estele', 'estella', 'estelle', 'ester', 'esther', + 'estrella', 'ethel', 'etta', 'eugenia', + 'eugenie', 'eula', 'eunice', 'eva', + 'evangelina', + 'evangeline', + 'evelin', + 'evelina', 'evelyn', + 'evie', + 'evita', + 'farah', + 'farrah', 'fatima', 'fay', 'faye', + 'felecia', 'felicia', 'fern', + 'fernanda', + 'fiona', + 'flo', 'flora', 'florence', + 'fran', 'frances', + 'francesca', 'francina', 'francine', 'francisca', + 'francoise', 'freda', + 'frida', 'frieda', 'gabriela', 'gabriele', + 'gabriella', 'gabrielle', 'gail', 'gale', + 'garnet', 'gayle', + 'gemma', + 'gena', + 'genesis', 'genevieve', + 'genna', + 'georgette', + 'georgie', 'georgina', 'geraldina', 'geraldine', + 'geri', + 'germaine', 'gertrude', + 'gia', + 'gianna', + 'gigi', + 'gilda', + 'gillian', 'gina', + 'giovanna', + 'gisela', 'gisele', + 'giselle', 'gladys', 'glena', 'glenda', 'glenna', 'gloria', + 'glynis', + 'golda', + 'goldie', 'grace', + 'gracie', 'graciela', + 'greta', 'gretchen', + 'griselda', 'gwen', 'gwendolyn', + 'gwyneth', + 'hailey', + 'haley', + 'hallie', 'hana', 'hanah', 'hanna', 'hannah', 'hariet', 'hariette', + 'harmony', 'harriet', + 'harriett', 'harriette', + 'hattie', + 'hayley', + 'hazel', 'heather', 'heidi', 'helen', 'helena', 'helene', + 'helga', 'henrietta', + 'hermine', + 'hester', 'hilary', 'hilda', + 'hildegard', 'hillary', + 'hollie', + 'hortense', + 'hyacinth', 'ida', + 'ila', + 'ilene', + 'iliana', + 'ilona', + 'ilse', + 'imelda', 'imogena', 'imogene', + 'ina', + 'indira', + 'ines', 'ingrid', + 'iona', 'irena', 'irene', + 'irina', 'irma', + 'isa', 'isabel', 'isabela', 'isabele', + 'isabell', 'isabella', 'isabelle', + 'isadora', 'isidora', + 'isobel', 'iva', + 'ivana', + 'jacinda', + 'jacinta', + 'jackie', 'jaclyn', 'jacquelina', 'jacqueline', 'jacquelyn', + 'jada', 'jade', + 'jami', 'jana', + 'janae', 'jane', 'janele', 'janelle', + 'janessa', 'janet', 'janette', 'janice', + 'janie', 'janina', 'janine', 'janis', + 'jaqueline', + 'jasmin', 'jasmina', 'jasmine', 'javiera', + 'jayne', + 'jazmin', + 'jazmine', 'jeana', 'jeane', 'jeanette', + 'jeanie', 'jeanina', 'jeanine', 'jeanna', 'jeanne', 'jeannette', + 'jeannie', 'jeannina', 'jeannine', 'jelena', + 'jen', 'jena', + 'jenelle', 'jenifer', 'jenna', + 'jennette', + 'jenni', + 'jennie', 'jennifer', + 'jenny', 'jeri', + 'jerri', 'jesica', 'jessica', 'jil', @@ -345,70 +705,140 @@ module.exports = [ 'jodi', 'jodie', 'jody', + 'joelle', 'johana', 'johanna', + 'joleen', 'jolena', 'jolene', + 'jolie', 'joni', 'josefina', + 'joselyn', 'josephina', 'josephine', + 'josie', 'jovana', + 'joya', 'joyce', 'juana', 'juanita', 'judith', + 'judy', 'julia', + 'juliana', + 'julianna', + 'julianne', + 'julie', + 'julienne', + 'juliet', + 'juliette', + 'julissa', 'justina', 'justine', + 'kacey', + 'kaitlin', + 'kaitlyn', + 'kaleigh', + 'kali', + 'kallie', + 'kamala', 'kanyakumari', 'kara', 'karen', 'kari', 'karima', 'karin', + 'karina', + 'karissa', 'karla', + 'karly', + 'karyn', + 'kassandra', + 'kassie', 'katarina', 'kate', + 'katelyn', + 'katelynn', 'katharina', 'katharine', 'katherina', 'katherine', + 'kathie', 'kathleen', + 'kathrine', 'kathryn', + 'kathy', 'kati', + 'katia', 'katie', + 'katlyn', 'katrina', 'katy', 'kavita', 'kay', + 'kaye', 'kayla', + 'kaylee', + 'kayleigh', + 'keeley', + 'keely', + 'keira', 'keisha', 'keley', 'keli', 'kelley', 'kelli', + 'kellie', 'kelly', + 'kelsie', 'kely', 'kendra', + 'kenna', + 'kera', 'keri', 'kerri', 'khadija', + 'kia', + 'kiana', + 'kiara', + 'kiera', + 'kiersten', + 'kiley', 'kim', + 'kimberlee', 'kimberley', 'kimberli', 'kimberly', + 'kira', 'kirsten', + 'kirstin', + 'kizzy', + 'kori', + 'kourtney', 'krista', 'kristen', + 'kristi', + 'kristie', 'kristin', 'kristina', 'kristine', + 'kristy', 'krystal', + 'kyla', + 'kylee', + 'kylie', + 'kyra', + 'lacey', + 'lacie', + 'lacy', 'ladona', 'ladonna', + 'laila', + 'lakesha', 'lana', 'lara', + 'larissa', 'latasha', 'latisha', 'latonya', @@ -416,1085 +846,643 @@ module.exports = [ 'laura', 'laurel', 'lauren', + 'laurie', + 'lauryn', 'laverna', 'laverne', + 'lavinia', 'laxmi', + 'layla', 'lea', 'leah', 'leana', + 'leandra', 'leane', 'leann', 'leanna', 'leanne', + 'leda', + 'leena', + 'leia', 'leigh', 'leila', + 'leilani', 'lela', 'lena', 'lenora', + 'lenore', 'leola', 'leona', + 'leonie', + 'leonora', + 'leora', 'lesley', 'lesli', + 'leslie', 'lesly', 'leticia', + 'letitia', + 'lettie', + 'lexie', + 'lia', + 'liana', + 'lianne', + 'libbie', + 'libby', + 'liberty', + 'lidia', 'lila', + 'lilia', 'lilian', + 'liliana', + 'lillia', 'lillian', + 'lillie', + 'lilly', + 'lina', 'linda', 'lindsay', 'lindsey', 'lindsi', 'lindsy', + 'lindy', 'lisa', + 'lisette', + 'livia', + 'liz', + 'liza', + 'lizbeth', + 'lizette', + 'lizzie', 'lois', 'lola', + 'lolita', 'lora', 'loraina', 'loraine', + 'lorelei', 'lorena', 'lorene', 'loretta', + 'lori', + 'lorie', 'lorna', 'lorraina', 'lorraine', + 'lorri', + 'lorrie', + 'lottie', + 'louella', + 'louisa', 'louise', + 'luann', 'lucia', + 'luciana', + 'lucie', 'lucile', 'lucille', 'lucinda', + 'lucy', 'luela', 'luella', 'luisa', + 'lula', + 'lulu', + 'luna', 'lupe', + 'lupita', + 'luz', 'lydia', + 'lyla', 'lyn', 'lyna', 'lynda', + 'lyndsey', 'lyne', 'lynette', 'lynn', 'lynna', 'lynne', + 'lynnette', + 'lynsey', 'mabel', 'mable', + 'macie', + 'macy', + 'madalyn', + 'maddie', + 'madeleine', 'madelina', 'madeline', + 'madelyn', + 'madge', + 'madison', + 'madonna', 'mae', + 'magda', 'magdalena', + 'magdalene', + 'maggie', + 'maia', + 'maire', + 'maisie', + 'malia', 'malika', + 'malinda', + 'mallory', 'mandakranta', + 'mandy', 'manon', 'manuela', + 'mara', 'marcela', 'marcella', + 'marcelle', + 'marci', 'marcia', + 'marcie', + 'marcy', 'margaret', 'margarette', 'margarita', + 'marge', + 'margery', + 'margie', 'margo', + 'margot', 'margret', 'margrette', 'marguerite', + 'mari', 'maria', + 'mariah', + 'mariam', 'marian', 'mariana', 'mariane', 'marianna', 'marianne', 'maribel', + 'marie', + 'mariela', + 'mariella', 'marija', 'marilyn', 'marina', + 'maris', 'marisa', 'marisol', 'marissa', 'maritza', + 'marjorie', 'marla', 'marlena', 'marlene', + 'marnie', 'marsha', 'marta', 'martha', 'martina', 'mary', + 'maryam', 'maryan', 'maryann', + 'marybeth', + 'maryjane', + 'marylou', + 'mathilde', 'matilda', + 'mattie', 'maude', + 'maura', 'maureen', 'mavis', 'maxina', 'maxine', 'maya', + 'maybell', 'mayra', + 'mazie', + 'mckenzie', 'meagan', + 'meg', 'megan', 'meghan', + 'mei', + 'melanie', + 'melina', 'melinda', 'melisa', 'melissa', + 'mellisa', 'meredith', + 'merissa', + 'meryl', + 'mia', + 'mya', + 'michaela', 'michele', 'michelle', + 'mika', + 'mikaela', + 'mila', 'mildred', 'milica', + 'millicent', + 'millie', + 'milly', + 'mimi', + 'mina', + 'mindy', + 'minerva', + 'minh', + 'minnie', + 'mira', 'miranda', 'miriam', - 'mona', + 'mitzi', + 'moira', + 'mollie', 'molly', + 'mona', 'monica', + 'monika', 'monique', 'mrignayani', 'muriel', 'myra', 'myrna', 'myrtle', + 'nadene', 'nadia', 'nadina', 'nadine', 'naima', - 'naomi', 'nancy', + 'nanette', + 'naomi', + 'natalia', + 'natalie', 'natasha', 'nel', 'nell', + 'nellie', + 'nena', + 'nerissa', + 'nia', 'niamh', 'nichole', + 'nicki', + 'nicky', + 'nicola', 'nicole', + 'nicolette', + 'niki', + 'nikita', 'nikki', + 'nila', 'nina', + 'nisha', + 'nita', + 'noella', + 'noelle', + 'noemi', 'nora', + 'norah', + 'noreen', 'norma', + 'nyla', + 'octavia', + 'odelia', + 'odette', 'ofelia', + 'ola', 'olga', 'olivia', + 'ophelia', 'paige', 'pam', 'pamela', + 'pandora', + 'paola', 'parvati', 'patrica', 'patrice', 'patricia', + 'patsy', + 'patti', + 'pattie', + 'patty', 'paula', 'paulette', 'paulina', 'pauline', 'pearl', + 'peggy', + 'penelope', + 'perla', 'petra', + 'philomena', + 'phoebe', 'phylis', 'phyllis', + 'polly', + 'portia', 'priscila', 'priscilla', 'priyamvada', + 'prudence', + 'queenie', + 'quiana', 'rachael', 'rachel', 'rachele', 'rachelle', 'rachida', + 'rae', + 'raina', 'ramona', + 'randi', 'raquel', + 'raven', + 'rayna', + 'reanna', 'reba', 'rebecca', 'rebeka', 'rebekah', + 'regina', + 'reina', 'rena', + 'renae', + 'renata', 'renee', + 'reta', + 'reyna', + 'rhea', + 'rhiannon', + 'rhoda', + 'rhona', 'rhonda', + 'ria', + 'richelle', + 'ricki', + 'rikki', + 'rina', 'rita', + 'robbin', 'roberta', 'robyn', 'rochele', 'rochelle', + 'rocio', + 'rolanda', 'ronda', + 'roni', + 'ronna', 'rosa', + 'rosalie', + 'rosalina', 'rosalind', + 'rosalinda', + 'rosalyn', + 'rosanna', + 'rosanne', + 'roseann', + 'roseanne', + 'rosella', + 'roselle', + 'rosemarie', 'rosemary', 'rosetta', + 'rosie', + 'roslyn', + 'rowena', 'roxana', 'roxane', 'roxanna', 'roxanne', + 'roxie', + 'roxy', 'ruby', 'ruth', + 'ruthie', + 'sabina', + 'sabine', 'sabrina', + 'sade', + 'sadie', 'saida', + 'sallie', 'sally', + 'salome', 'samantha', + 'samara', + 'samira', 'sandra', + 'sandy', 'sara', 'sarah', - 'siobhan', + 'sarina', + 'sasha', + 'savanna', + 'savannah', + 'scarlet', + 'scarlett', + 'selena', + 'selene', + 'selina', 'selma', + 'serena', + 'shakira', 'shana', + 'shanda', 'shania', 'shanna', 'shannon', 'shanon', 'shari', + 'sharlene', 'sharon', + 'sharron', 'shauna', 'shawna', + 'shayla', + 'shayna', + 'sheba', 'sheena', 'sheila', 'shelia', + 'shelley', 'shelly', 'sheri', + 'sheridan', + 'sherri', + 'sherrie', + 'sherry', 'sheryl', 'shirley', 'shirli', 'shirly', + 'shona', + 'shyla', + 'sierra', 'silvia', 'simona', 'simone', + 'sindy', + 'siobhan', + 'skye', 'sofia', 'sondra', 'sonia', 'sonja', 'sonya', 'sophia', + 'sophie', 'stacey', 'staci', + 'stacie', 'stacy', + 'starla', + 'stefanie', 'stela', 'stella', + 'stephanie', 'sue', 'susan', 'susana', 'susane', 'susanna', + 'susannah', 'susanne', 'susi', + 'susie', + 'suzan', 'suzana', 'suzane', 'suzanna', 'suzanne', + 'suzette', + 'suzie', + 'suzy', 'sybil', 'sylvia', 'sylvie', + 'tabatha', 'tabitha', + 'talia', + 'talitha', 'tamara', + 'tamera', 'tami', 'tamika', + 'tammi', + 'tammie', 'tammy', + 'tamra', + 'tania', + 'tanika', + 'tanisha', 'tanya', 'tara', + 'taryn', 'tasha', + 'tatiana', + 'tatum', + 'tawana', + 'tegan', 'teodora', 'teresa', 'teri', 'terri', + 'terrie', + 'tess', + 'tessa', + 'tessie', + 'thalia', + 'thea', 'thelma', + 'theodora', 'theresa', 'therese', + 'thomasina', + 'tia', + 'tiana', + 'tiara', + 'tiffany', 'tina', + 'tisha', 'toni', 'tonia', 'tonya', + 'tora', + 'tori', 'tracey', 'traci', + 'tracie', 'tracy', 'tricia', 'trina', + 'trish', 'trisha', + 'trista', 'trudy', + 'tula', + 'tyra', 'ursula', 'valentina', + 'valeria', + 'valerie', + 'valery', 'vanesa', 'vanessa', + 'veda', 'velma', + 'venus', 'vera', 'verna', + 'vernice', 'veronica', + 'vicki', + 'vickie', + 'vicky', 'victoria', 'vivian', + 'viviana', + 'vivien', + 'vivienne', 'wanda', + 'wendi', 'wendy', 'whitney', 'whitni', 'whitny', 'wila', + 'wilhelmina', 'willa', + 'willow', 'wilma', + 'winifred', + 'winnie', + 'winnifred', + 'winona', + 'yasmin', + 'yasmine', + 'yelena', + 'yesenia', 'yolanda', 'yvette', 'yvona', 'yvone', 'yvonna', 'yvonne', + 'zada', 'zara', - - 'abagail', - 'abbey', - 'abbi', - 'abbie', - 'abby', - 'abi', - 'adaline', - 'adalyn', - 'addie', - 'addilyn', - 'addison', - 'adelaide', - 'adelene', - 'adelynn', - 'adreanna', - 'adrianna', - 'adrianne', - 'adrienne', - 'agatha', - 'aggie', - 'ainsley', - 'aisling', - 'aislinn', - 'aislynn', - 'alaina', - 'alana', - 'alanis', - 'alanna', - 'alannah', - 'alayah', - 'alayna', - 'aaliyah', - 'alba', - 'alecia', - 'aleisha', - 'alejandra', - 'alena', - 'alessandra', - 'alexa', - 'alexia', - 'alia', - 'alina', - 'alissa', - 'aliza', - 'allie', - 'allison', - 'allyson', - 'alycia', - 'alyson', - 'amalia', - 'amberly', - 'amie', - 'anabel', - 'anamaria', - 'anastasia', - 'angelique', - 'angie', - 'anisa', - 'anissa', - 'annabel', - 'annabelle', - 'annalisa', - 'annamaria', - 'annemarie', - 'annie', - 'annmarie', - 'anya', - 'ariana', - 'arianna', - 'arianne', - 'arielle', - 'arleen', - 'arlette', - 'asha', - 'ashanti', - 'ashlee', - 'ashleigh', - 'ashlie', - 'ashlyn', - 'ashton', - 'astrid', - 'athena', - 'augustina', - 'aurelia', - 'aurora', - 'avery', - 'avril', - 'ayana', - 'ayanna', - 'ayesha', - 'barbie', - 'bea', - 'benita', - 'beryl', - 'bess', - 'bessie', - 'bethanie', - 'bethany', - 'betsy', - 'bettina', - 'bev', - 'blanche', - 'blossom', - 'blythe', - 'bobbi', - 'bobbie', - 'bonnie', - 'brandy', - 'breanna', - 'bree', - 'brenna', - 'briana', - 'brianna', - 'brianne', - 'brigid', - 'britney', - 'britt', - 'brittany', - 'bronwyn', - 'brook', - 'bryanna', - 'brynn', - 'caitlyn', - 'calista', - 'callie', - 'camila', - 'camilla', - 'carina', - 'carissa', - 'carlene', - 'carley', - 'carlie', - 'carly', - 'carmel', - 'carrie', - 'cassie', - 'catarina', - 'caterina', - 'cathryn', - 'catrina', - 'cayla', - 'cecily', - 'chanelle', - 'chantal', - 'chantelle', - 'charis', - 'charissa', - 'charla', - 'charlette', - 'charlotte', - 'charmaine', - 'chelsey', - 'cher', - 'cheri', - 'cherie', - 'chrissy', - 'christal', - 'christen', - 'christi', - 'christiana', - 'christiane', - 'christie', - 'christy', - 'chrystal', - 'ciara', - 'cierra', - 'cindy', - 'clair', - 'clare', - 'claris', - 'clarissa', - 'claudine', - 'cleopatra', - 'clotilde', - 'colette', - 'connie', - 'coral', - 'coralie', - 'cordelia', - 'cori', - 'cristal', - 'cyndi', - 'dahlia', - 'daina', - 'damaris', - 'danette', - 'dani', - 'danica', - 'daniela', - 'daniella', - 'danika', - 'dara', - 'darby', - 'darcey', - 'darcie', - 'daria', - 'davida', - 'davina', - 'dayle', - 'dayna', - 'deandra', - 'deann', - 'deanne', - 'deb', - 'debbie', - 'debby', - 'dede', - 'deedee', - 'deena', - 'deidre', - 'deirdre', - 'deja', - 'delilah', - 'delphine', - 'demetria', - 'denice', - 'dinah', - 'dionne', - 'dixie', - 'dorla', - 'dottie', - 'dulce', - 'eden', - 'edie', - 'edwina', - 'elana', - 'eliana', - 'elicia', - 'elida', - 'elin', - 'elina', - 'elinor', - 'ella', - 'ellie', - 'elly', - 'elouise', - 'elsie', - 'elvina', - 'emelda', - 'emely', - 'emerald', - 'emilee', - 'emilia', - 'emilie', - 'emily', - 'emmaline', - 'emmie', - 'emmy', - 'enid', - 'eryn', - 'esmeralda', - 'esperanza', - 'estrella', - 'eugenie', - 'evangelina', - 'evangeline', - 'evelin', - 'evelina', - 'evie', - 'evita', - 'farah', - 'farrah', - 'fernanda', - 'fiona', - 'flo', - 'fran', - 'francesca', - 'francoise', - 'frida', - 'gabriella', - 'garnet', - 'gemma', - 'gena', - 'genesis', - 'genna', - 'georgette', - 'georgie', - 'germaine', - 'gia', - 'gianna', - 'gigi', - 'gilda', - 'gillian', - 'giovanna', - 'gisela', - 'giselle', - 'glynis', - 'golda', - 'goldie', - 'gracie', - 'greta', - 'griselda', - 'gwyneth', - 'hailey', - 'haley', - 'hallie', - 'harmony', - 'hattie', - 'hayley', - 'hazel', - 'helga', - 'hermine', - 'hester', - 'hildegard', - 'hollie', - 'hortense', - 'hyacinth', - 'ila', - 'ilene', - 'iliana', - 'ilona', - 'ilse', - 'imelda', - 'indira', - 'ines', - 'iona', - 'irina', - 'isa', - 'isabell', - 'isadora', - 'isobel', - 'ivana', - 'jacinda', - 'jacinta', - 'jackie', - 'jada', - 'janae', - 'janessa', - 'janie', - 'jaqueline', - 'jasmin', - 'jayne', - 'jazmin', - 'jazmine', - 'jeannie', - 'jen', - 'jenelle', - 'jennette', - 'jenni', - 'jennie', - 'jenny', - 'jerri', - 'joelle', - 'joleen', - 'jolie', - 'joselyn', - 'josie', - 'joya', - 'jude', - 'judy', - 'juliana', - 'julianna', - 'julianne', - 'julie', - 'julienne', - 'juliet', - 'juliette', - 'julissa', - 'kacey', - 'kaitlin', - 'kaitlyn', - 'kaleigh', - 'kali', - 'kallie', - 'kamala', - 'karina', - 'karissa', - 'karly', - 'karyn', - 'kassandra', - 'kassie', - 'katelyn', - 'katelynn', - 'kathy', - 'katia', - 'katlyn', - 'kaye', - 'kaylee', - 'kayleigh', - 'keeley', - 'keely', - 'keira', - 'kellie', - 'kelsie', - 'kenna', - 'kera', - 'kia', - 'kiana', - 'kiara', - 'kiera', - 'kiersten', - 'kiley', - 'kimberlee', - 'kira', - 'kirstin', - 'kizzy', - 'kori', - 'kourtney', - 'kris', - 'kristi', - 'kristie', - 'kristy', - 'kyla', - 'kylee', - 'kylie', - 'kyra', - 'lacey', - 'lacie', - 'lacy', - 'laila', - 'larissa', - 'laurie', - 'lauryn', - 'lavinia', - 'layla', - 'leandra', - 'leda', - 'leena', - 'leia', - 'leilani', - 'lenore', - 'leonie', - 'leonora', - 'leora', - 'leslie', - 'letitia', - 'lettie', - 'lexie', - 'lia', - 'liana', - 'lianne', - 'libbie', - 'libby', - 'liberty', - 'lidia', - 'liliana', - 'lillia', - 'lillie', - 'lilly', - 'lina', - 'lindy', - 'lisette', - 'livia', - 'liz', - 'liza', - 'lizbeth', - 'lizette', - 'lizzie', - 'lolita', - 'lorelei', - 'lori', - 'lorie', - 'lorri', - 'lorrie', - 'lottie', - 'louella', - 'louisa', - 'luann', - 'luciana', - 'lucie', - 'lucy', - 'lulu', - 'luna', - 'lupita', - 'luz', - 'lyla', - 'lyndsey', - 'lynnette', - 'lynsey', - 'macie', - 'macy', - 'madalyn', - 'maddie', - 'madeleine', - 'madelyn', - 'madison', - 'madonna', - 'magda', - 'magdalene', - 'maggie', - 'maia', - 'maire', - 'maisie', - 'malia', - 'malinda', - 'mallory', - 'mandy', - 'mara', - 'marcelle', - 'marci', - 'marcie', - 'marcy', - 'marge', - 'margie', - 'margot', - 'mariah', - 'mariam', - 'marie', - 'mariela', - 'mariella', - 'maris', - 'marjorie', - 'marnie', - 'maryam', - 'marybeth', - 'maryjane', - 'mathilde', - 'mattie', - 'maura', - 'maybell', - 'mazie', - 'mckenzie', - 'meg', - 'mei', - 'melanie', - 'melina', - 'merissa', - 'meryl', - 'michaela', - 'mika', - 'mikaela', - 'mila', - 'millicent', - 'millie', - 'milly', - 'mimi', - 'mina', - 'mindy', - 'minerva', - 'minnie', - 'mira', - 'mitzi', - 'moira', - 'mollie', - 'monika', - 'nadene', - 'nanette', - 'natalia', - 'natalie', - 'nellie', - 'nena', - 'nerissa', - 'nia', - 'nicki', - 'nicky', - 'nicola', - 'nicolette', - 'niki', - 'nikita', - 'nila', - 'nisha', - 'nita', - 'noella', - 'noelle', - 'noemi', - 'norah', - 'noreen', - 'nyla', - 'octavia', - 'odelia', - 'odette', - 'ophelia', - 'pandora', - 'paola', - 'patsy', - 'patti', - 'patty', - 'peggy', - 'penelope', - 'perla', - 'philomena', - 'phoebe', - 'polly', - 'portia', - 'prudence', - 'queenie', - 'quiana', - 'quinn', - 'rae', - 'raina', - 'randi', - 'raven', - 'rayna', - 'reanna', - 'regina', - 'reina', - 'renae', - 'renata', - 'reyna', - 'rhea', - 'rhiannon', - 'rhoda', - 'rhona', - 'ria', - 'richelle', - 'ricki', - 'rikki', - 'rina', - 'rocio', - 'rolanda', - 'roni', - 'ronna', - 'rosalie', - 'rosalina', - 'rosalinda', - 'rosanna', - 'roseanne', - 'rosella', - 'roselle', - 'rosemarie', - 'rosie', - 'rowena', - 'roxie', - 'roxy', - 'ruthie', - 'sabina', - 'sabine', - 'sade', - 'sadie', - 'salome', - 'samara', - 'samira', - 'sandy', - 'sarina', - 'sasha', - 'savanna', - 'savannah', - 'scarlet', - 'scarlett', - 'selena', - 'selene', - 'selina', - 'serena', - 'shakira', - 'shayla', - 'shayna', - 'sheba', - 'shelley', - 'sheridan', - 'sherri', - 'sherrie', - 'sherry', - 'shona', - 'shyla', - 'sierra', - 'sindy', - 'skye', - 'sophie', - 'stacie', - 'star', - 'starla', - 'stefanie', - 'stephanie', - 'susannah', - 'susie', - 'suzette', - 'suzie', - 'suzy', - 'tabatha', - 'talia', - 'talitha', - 'tamera', - 'tammi', - 'tammie', - 'tamra', - 'tania', - 'tanika', - 'tanisha', - 'taryn', - 'tatiana', - 'tatum', - 'tawana', - 'tegan', - 'terrie', - 'tess', - 'tessa', - 'thalia', - 'thea', - 'theodora', - 'thomasina', - 'tia', - 'tiana', - 'tiara', - 'tiffany', - 'tisha', - 'tora', - 'tori', - 'tracie', - 'trish', - 'trista', - 'tula', - 'tyra', - 'valeria', - 'valerie', - 'valery', - 'veda', - 'venus', - 'vicki', - 'vickie', - 'vicky', - 'viviana', - 'vivien', - 'vivienne', - 'wendi', - 'wilhelmina', - 'willow', - 'winifred', - 'winnie', - 'winnifred', - 'winona', - 'yasmin', - 'yasmine', - 'yelena', - 'yesenia', - 'zada', 'zelda', + 'zelma', 'zena', 'zoe', 'zola', 'zora', - - - 'ida', - 'lula', - 'dorthy', - 'sallie', - 'ina', - 'bettie', - 'ola', - 'sharron', - 'rosalyn', - 'mia', - 'jami', - 'ericka', - 'elnora', - 'corrine', - 'bernadine', - 'chandra', - 'adela', - 'zelma', - 'marylou', - 'jeanie', - 'harriett', - 'lilia', - 'carmella', - 'roslyn', - 'mari', - 'margery', - 'madge', - 'kathrine', - 'kathie', - 'roseann', - 'rosanne', - - 'mellisa', - 'sharlene', - 'lakesha', - 'bridgett', - 'carrol', - 'geri', - 'felecia', - 'brandie', - 'beverley', - 'vernice', - 'tessie', - 'robbin', - 'pattie', - 'minh', - 'cindi', - 'reta', - 'shanda', - 'suzan', - - -]; +] diff --git a/data/words/people/firstnames.js b/data/people/firstnames.js similarity index 89% rename from data/words/people/firstnames.js rename to data/people/firstnames.js index 249a6c817..ecf0d48cd 100644 --- a/data/words/people/firstnames.js +++ b/data/people/firstnames.js @@ -13,22 +13,23 @@ module.exports = [ 'jamie', 'jammie', 'jessie', + 'jude', 'kasey', 'kelsey', 'kenyatta', 'kerry', + 'kris', 'lashawn', - 'lee', 'marion', 'marlo', 'mel', 'morgan', 'nelly', - 'nicky', + 'quinn', 'regan', 'rene', 'shay', 'shea', 'shelby', - 'shiloh' -]; + 'shiloh', +] diff --git a/data/people/honorifics.js b/data/people/honorifics.js new file mode 100644 index 000000000..6b896e1f9 --- /dev/null +++ b/data/people/honorifics.js @@ -0,0 +1,44 @@ +//extend to person-names if infront of a name - 'Professor Frink' +module.exports = [ + 'admiral', + 'ayatullah', + 'brigadier', + 'captain', + 'captain', + 'chancellor', + 'colonel', + 'commander', + 'congressman', + 'congresswoman', + 'councillor', + 'count', + 'doctor', + 'dutchess', + 'excellency', + 'field marshal', + 'first lady', + 'first lieutenant', + 'judge', + 'king', + 'lieutenant', + 'magistrate', + 'marshal', + 'mayor', + 'officer', + 'pastor', + 'president', + 'prime minister', + 'prince', + 'princess', + 'professor', + 'queen', + 'rabbi', + 'rear admiral', + 'reverend', + 'second lieutenant', + 'secretary', + 'sergeant', + 'sultan', + 'taoiseach', + 'vice admiral', +] diff --git a/data/words/people/lastnames.js b/data/people/lastnames.js similarity index 99% rename from data/words/people/lastnames.js rename to data/people/lastnames.js index dfa20ae3a..3030e4e3c 100644 --- a/data/words/people/lastnames.js +++ b/data/people/lastnames.js @@ -97,7 +97,6 @@ module.exports = [ 'henderson', 'hernandez', 'hitchcock', - 'hitler', 'hoang', 'hoffmann', 'horvat', @@ -160,6 +159,7 @@ module.exports = [ 'matsumoto', 'mercier', 'messi', + 'messier', 'meyer', 'mihhailov', 'miller', @@ -172,9 +172,9 @@ module.exports = [ 'mozart', 'muller', 'munoz', + 'muñoz', 'murray', 'mussolini', - 'muñoz', 'nagy', 'nakajima', 'nakamura', @@ -295,5 +295,5 @@ module.exports = [ 'zhang', 'zhao', 'zhou', - 'zhu' -]; + 'zhu', +] diff --git a/data/words/people/maleNames.js b/data/people/maleNames.js similarity index 99% rename from data/words/people/maleNames.js rename to data/people/maleNames.js index d6fbc48b2..9ed87fa97 100644 --- a/data/words/people/maleNames.js +++ b/data/people/maleNames.js @@ -5,20 +5,26 @@ module.exports = [ 'abdallah', 'abdel', 'abdoulaye', + 'abdul', 'abdullah', 'abdullo', 'abdulrahman', + 'abe', 'abel', 'abraham', + 'abram', 'abu', 'abubakr', 'abulfazl', 'adam', 'adama', + 'adan', 'adolfo', + 'adolf', 'adrian', 'advik', 'agustin', + 'ahmad', 'ahmed', 'ahmet', 'aiden', @@ -26,6 +32,8 @@ module.exports = [ 'alan', 'albert', 'alberto', + 'alden', + 'alec', 'alejandro', 'aleksandar', 'aleksander', @@ -40,6 +48,7 @@ module.exports = [ 'allen', 'alonso', 'alonzo', + 'alphonso', 'alton', 'alvaro', 'alvin', @@ -47,6 +56,7 @@ module.exports = [ 'ammar', 'amos', 'andre', + 'andreas', 'andres', 'andrew', 'andy', @@ -57,6 +67,7 @@ module.exports = [ 'anton', 'antoni', 'antonio', + 'antony', 'aputsiaq', 'arata', 'archie', @@ -72,12 +83,17 @@ module.exports = [ 'arturo', 'aryan', 'asahi', + 'augustus', 'austin', + 'avery', 'ayaan', 'aziz', + 'barney', + 'barrett', 'barry', 'bart', 'ben', + 'benedict', 'benito', 'benjamin', 'bennie', @@ -85,7 +101,9 @@ module.exports = [ 'berat', 'bernard', 'bernardo', + 'bernie', 'bert', + 'bertram', 'beshoi', 'bilal', 'billie', @@ -94,22 +112,29 @@ module.exports = [ 'blake', 'bob', 'bobby', + 'boris', + 'boyd', 'brad', 'bradford', 'bradley', 'brady', + 'branden', 'brandon', 'brendan', + 'brendon', 'brent', + 'brenton', 'bret', 'brett', 'brian', + 'brice', 'bruce', 'bruno', 'bryan', 'bryce', 'bryon', 'buddy', + 'burt', 'burton', 'byron', 'caleb', @@ -120,13 +145,15 @@ module.exports = [ 'carlos', 'carlton', 'carroll', + 'cary', 'cecil', 'cedric', 'cesar', 'chad', 'charles', + 'charley', 'charlie', - // 'chase', + 'chas', 'chester', 'chris', 'christian', @@ -137,31 +164,43 @@ module.exports = [ 'claude', 'clay', 'clayton', + 'clement', + 'cletus', 'cleveland', 'clifford', 'clifton', 'clint', 'clyde', 'cody', + 'colby', + 'cole', 'colin', + 'collin', + 'colton', 'conor', 'conrad', 'corey', 'cornelius', 'cory', 'craig', + 'cristobal', 'curt', 'curtis', + 'cyril', + 'cyrus', 'dale', 'dallas', 'damian', 'damien', + 'damion', 'damon', 'dan', 'dane', 'daniel', 'danny', + 'daren', 'darin', + 'dario', 'darius', 'darnell', 'darrel', @@ -174,13 +213,18 @@ module.exports = [ 'davi', 'david', 'dean', + 'deandre', 'dejan', 'delbert', 'demetrius', 'denis', 'dennis', + 'denny', + 'denver', + 'deon', 'derek', 'derrick', + 'deshawn', 'desmond', 'deven', 'devin', @@ -189,17 +233,27 @@ module.exports = [ 'dexter', 'diarmuid', 'diego', + 'dillon', + 'dion', + 'dirk', 'domingo', 'dominic', 'dominick', 'don', 'donald', + 'donnell', 'donnie', + 'donny', + 'donovan', + 'dorian', 'doug', 'douglas', 'doyle', 'dragan', + 'drew', 'duane', + 'dudley', + 'duncan', 'dustin', 'dwayne', 'dwight', @@ -208,33 +262,42 @@ module.exports = [ 'earnest', 'ed', 'eddie', + 'eddy', 'edgar', 'edmond', 'edmund', 'eduardo', 'edward', + 'edwardo', 'edwin', 'efrain', + 'efren', 'eitan', 'elbert', 'eldon', 'eli', 'elias', 'elijah', + 'elisha', 'elliot', 'elliott', 'ellis', 'elmer', + 'elmo', 'elton', 'elvin', + 'elvis', 'elwood', 'emanuel', + 'emerson', + 'emery', 'emil', 'emilio', 'emir', 'emirhan', 'emmanuel', 'emmett', + 'enoch', 'enrique', 'enzo', 'eoin', @@ -245,6 +308,7 @@ module.exports = [ 'ernest', 'ernesto', 'ernie', + 'errol', 'ervin', 'erwin', 'esteban', @@ -253,8 +317,10 @@ module.exports = [ 'evan', 'everett', 'eymen', + 'ezra', 'fabian', 'fadi', + 'federico', 'felipe', 'felix', 'feng', @@ -262,6 +328,7 @@ module.exports = [ 'fidel', 'filip', 'fionn', + 'fletcher', 'floyd', 'forrest', 'francesco', @@ -271,26 +338,35 @@ module.exports = [ 'frank', 'frankie', 'franklin', + 'franklyn', 'fred', 'freddie', 'freddy', 'frederick', 'fredrick', + 'fritz', 'gabriel', + 'galen', 'garland', 'garrett', 'garry', + 'garth', 'gary', + 'gavin', 'gene', 'geoffrey', 'george', 'gerald', 'gerard', 'gerardo', + 'gerry', 'gilbert', 'gilberto', + 'gino', + 'giovanni', 'glen', 'glenn', + 'gonzalo', 'gordon', 'grady', 'graham', @@ -301,11 +377,13 @@ module.exports = [ 'gregory', 'grover', 'guillermo', + 'gus', 'gustavo', 'habib', 'hal', 'halim', 'hamza', + 'hank', 'hans', 'hao', 'harlan', @@ -321,6 +399,7 @@ module.exports = [ 'hasan', 'hassan', 'hayato', + 'hayden', 'heath', 'hector', 'heitor', @@ -338,12 +417,13 @@ module.exports = [ 'humberto', 'hussein', 'hydar', - 'ian', 'iain', + 'ian', 'ibrahim', 'ichika', 'ignacio', 'igor', + 'ike', 'iker', 'ilija', 'inuk', @@ -351,27 +431,39 @@ module.exports = [ 'ira', 'irvin', 'irving', + 'irwin', 'isaac', + 'isaiah', + 'isaias', 'ishaan', + 'isiah', 'ismael', + 'issac', 'itai', 'itsuki', 'ivan', 'jack', 'jacob', + 'jacques', 'jaden', 'jake', 'jakob', 'jakub', 'jamal', 'james', + 'jamison', 'jared', + 'jarod', + 'jarrett', 'jarrod', + 'jarvis', 'jason', 'jasper', 'javier', 'jay', 'jayden', + 'jayson', + 'jed', 'jeff', 'jeffery', 'jeffrey', @@ -398,20 +490,26 @@ module.exports = [ 'joey', 'john', 'johnathan', + 'johnathon', + 'johnie', 'johnnie', 'johnny', 'jon', + 'jonah', 'jonas', 'jonathan', 'jonathon', 'jonny', 'jordan', //v country 'jordi', + 'jordon', 'jorge', 'jose', 'joseph', 'josh', 'joshua', + 'josiah', + 'josue', 'juan', 'julian', 'julio', @@ -421,37 +519,46 @@ module.exports = [ 'karim', 'karl', 'kathem', - 'keith', + 'keenan', 'keir', + 'keith', 'ken', 'kendall', 'kendrick', 'kenneth', 'kenny', 'kent', + 'kenton', 'kermit', 'kevin', 'khaled', 'kieran', + 'kip', + 'kirby', 'kirk', 'kirollos', 'kristian', 'kristopher', 'kurt', + 'kurtis', 'kyle', 'lamar', 'lamont', 'lance', + 'landon', 'larry', 'laurence', 'lawrence', + 'leandro', 'leevi', 'leland', + 'len', + 'lenny', 'leo', 'leon', - 'lenny', 'leonard', 'leonardo', + 'leonel', 'lester', 'levi', 'liam', @@ -466,12 +573,15 @@ module.exports = [ 'louis', 'lowell', 'lucas', + 'luciano', + 'luigi', 'luis', 'luka', 'lukas', 'luke', 'luther', 'lyle', + 'lyndon', 'mack', 'mahamadou', 'mahdi', @@ -492,6 +602,7 @@ module.exports = [ 'marko', 'marlin', 'marlon', + 'marquis', 'marshall', 'marti', 'martin', @@ -508,13 +619,17 @@ module.exports = [ 'matthew', 'mattia', 'maurice', + 'mauricio', 'max', 'maximilian', 'maximiliano', + 'maxwell', 'mehdi', 'mehmet', 'melvin', 'merle', + 'merrill', + 'mervin', 'micah', 'michael', 'micheal', @@ -523,10 +638,13 @@ module.exports = [ 'miguel', 'mike', 'mikolaj', + 'milhouse', + 'milo', 'milos', 'milton', 'minato', 'minik', + 'mitch', 'mitchell', 'modibo', 'moe', @@ -534,6 +652,7 @@ module.exports = [ 'mohamed', 'mohammad', 'mohammed', + 'moises', 'monte', 'monty', 'moses', @@ -545,17 +664,22 @@ module.exports = [ 'murad', 'mustafa', 'mustapha', + 'myles', 'myron', 'nathan', + 'nathanael', 'nathaniel', 'nathy', 'neal', 'ned', 'neil', 'nelson', + 'neville', 'nicholas', 'nick', + 'nickolas', 'nicolas', + 'nigel', 'niilo', 'nikhil', 'nikola', @@ -566,6 +690,7 @@ module.exports = [ 'nomaan', 'norbert', 'norman', + 'octavio', 'oliver', 'omar', 'omer', @@ -574,6 +699,7 @@ module.exports = [ 'orville', 'osama', 'oscar', + 'osvaldo', 'otis', 'otto', 'oumar', @@ -594,37 +720,48 @@ module.exports = [ 'pol', 'preston', 'quentin', + 'quincy', 'quinton', 'rachid', 'rafael', + 'ralf', 'ralph', 'ramiro', 'ramon', 'randal', - 'ralf', 'randall', 'randolph', + 'randy', 'raphael', + 'rashad', 'raul', 'raymond', 'reggie', 'reginald', 'regis', + 'reid', 'reuben', 'rex', 'reyansh', 'reynaldo', 'reza', + 'rhett', 'ricardo', 'riccardo', 'richard', + 'richie', 'rick', 'rickey', + 'rickie', 'ricky', + 'rico', + 'riley', 'roan', 'robbie', + 'robby', 'robert', 'roberto', + 'rocco', 'rocky', 'roderick', 'rodger', @@ -638,18 +775,23 @@ module.exports = [ 'roland', 'rolando', 'roman', + 'romeo', 'ron', 'ronald', 'ronnie', + 'ronny', 'rory', 'roscoe', 'ross', 'roy', 'royce', 'ruben', + 'rubin', 'rudolph', 'rudy', 'rufus', + 'rupert', + 'russ', 'russel', 'russell', 'ryan', @@ -663,25 +805,33 @@ module.exports = [ 'santino', 'saqib', 'saul', + 'scot', 'scott', + 'scottie', 'scotty', - 'sean', 'seamus', + 'sean', 'sebastian', 'sekou', 'selim', 'sergio', 'seth', + 'seymour', 'shahid', 'shane', 'shaquille', 'shaun', 'shawn', + 'shayne', 'sheldon', + 'shelton', 'sherman', + 'sid', 'sidney', + 'silas', 'simon', 'solomon', + 'sonny', 'souleymane', 'souta', 'spencer', @@ -693,6 +843,7 @@ module.exports = [ 'stephen', 'steve', 'steven', + 'stevie', 'stewart', 'stuart', 'suraj', @@ -700,6 +851,7 @@ module.exports = [ 'szymon', 'tadgh', 'taichi', + 'tanner', 'tareq', 'tatsuki', 'ted', @@ -709,14 +861,20 @@ module.exports = [ 'terrell', 'terrence', 'terry', + 'thad', + 'thaddeus', + 'theo', 'theodore', 'thiago', + 'thom', 'thomas', 'tim', 'timmy', 'timothy', + 'titus', 'tobias', 'toby', + 'tod', 'todd', 'tom', 'tomas', @@ -727,30 +885,45 @@ module.exports = [ 'tony', 'travis', 'trent', + 'trenton', 'trevor', + 'trey', + 'tristan', 'troy', + 'truman', 'ty', 'tyler', 'tyrone', 'tyson', + 'ulysses', 'usman', + 'valentin', + 'valentine', 'vance', + 'vaughn', 'vernon', 'vicente', 'victor', 'vihaan', + 'vince', 'vincent', 'virgil', 'vivaan', + 'wade', 'wallace', + 'wally', 'walter', 'warren', + 'waylon', 'wayne', 'wei', 'wendell', + 'wes', 'wesley', + 'weston', 'wilbert', 'wilbur', + 'wiley', 'wilfred', 'wilfredo', 'willard', @@ -760,6 +933,7 @@ module.exports = [ 'winston', 'wolfgang', 'woodrow', + 'wyatt', 'xavier', 'yassin', 'yi', @@ -770,191 +944,13 @@ module.exports = [ 'youssef', 'yusuf', 'yuuma', - 'zachary', - 'zahid', - 'zoran', - - 'abdul', - 'abe', - 'abram', - 'adan', - 'ahmad', - 'alden', - 'alec', - 'alphonso', - 'andreas', - 'antony', - 'augustus', - 'avery', - 'barney', - 'barrett', - 'benedict', - 'bernie', - 'bertram', - 'boris', - 'boyd', - 'branden', - 'brendon', - 'brenton', - 'brice', - 'burt', - 'cary', - 'charley', - 'chas', - 'clement', - 'cletus', - 'colby', - 'cole', - 'collin', - 'colton', - 'cristobal', - 'cyril', - 'cyrus', - 'damion', - 'daren', - 'dario', - 'deandre', - 'denny', - 'denver', - 'deon', - 'deshawn', - 'dillon', - 'dion', - 'dirk', - 'donovan', - 'dorian', - 'drew', - 'dudley', - 'duncan', - 'eddy', - 'edwardo', - 'efren', - 'elisha', - 'elmo', - 'elvis', - 'emerson', - 'emery', - 'enoch', - 'errol', - 'ezra', - 'fletcher', - 'franklyn', - 'fritz', - 'galen', - 'garth', - 'gavin', - 'gerry', - 'gino', - 'giovanni', - 'gonzalo', - 'gus', - 'hank', - 'hayden', - 'ike', - 'irwin', - 'isaiah', - 'isaias', - 'isiah', - 'issac', - 'jacques', - 'jamison', - 'jarod', - 'jarrett', - 'jarvis', - 'jayson', - 'jed', - 'johnathon', - 'jonah', - 'jordon', - 'josiah', - 'josue', - 'jude', - 'keenan', - 'kenton', - 'kip', - 'kirby', - 'kris', - 'kurtis', - 'landon', - 'leandro', - 'len', - 'leonel', - 'leslie', - 'luciano', - 'luigi', - 'lyndon', - 'marquis', - 'mauricio', - 'maxwell', - 'mervin', - 'milo', - 'mitch', - 'moises', - 'myles', - 'nathanael', - 'neville', - 'nickolas', - 'nigel', - 'octavio', - 'osvaldo', - 'quincy', - 'quinn', - 'randy', - 'rashad', - 'reid', - 'rhett', - 'richie', - 'rickie', - 'rico', - 'riley', - 'robby', - 'rocco', - 'romeo', - 'ronny', - 'rubin', - 'rupert', - 'russ', - 'scot', - 'scottie', - 'shayne', - 'shelton', - 'sid', - 'silas', - 'sonny', - 'stevie', - 'tanner', - 'thad', - 'thaddeus', - 'theo', - 'titus', - 'tod', - 'trenton', - 'trey', - 'tristan', - 'truman', - 'ulysses', - 'valentin', - 'valentine', - 'vaughn', - 'vince', - 'wally', - 'waylon', - 'wes', - 'weston', - 'wiley', - 'wyatt', 'zachariah', + 'zachary', 'zachery', 'zack', 'zackary', + 'zahid', 'zane', - - - 'wade', - 'johnie', - 'merrill', - 'federico', - 'donnell', - 'donny', - 'seymour' -]; + 'zoran', + // 'chase', +] diff --git a/data/people/people.js b/data/people/people.js new file mode 100644 index 000000000..8bc8de9a7 --- /dev/null +++ b/data/people/people.js @@ -0,0 +1,61 @@ +module.exports = [ + //famous people with names that are hard to recognize independendtly + //male + 'hitler', + 'ronaldo', + 'ashton kutcher', + 'barack obama', + 'cardinal wolsey', + 'carson palmer', + 'denzel washington', + 'dick wolf', + 'emeril lagasse', + 'hulk hogan', + 'kanye west', + 'kiefer sutherland', + 'kobe bryant', + 'lebron james', + 'messiaen', + 'mitt romney', + 'mubarek', + 'ray romano', + 'rod stewart', + 'ronaldinho', + 'rush limbaugh', + 'saddam hussain', + 'slobodan milosevic', + 'tiger woods', + 'valentino rossi', + 'van gogh', + + //female + 'halle berry', + 'jk rowling', + 'oprah winfrey', + 'paris hilton', + 'reese witherspoon', + 'scarlett johansson', + 'theresa may', + 'tyra banks', + 'virgin mary', + + //sometimes firstname, sometimes lastname + 'brock', + 'carson', + 'clinton', + 'cruz', + 'dalton', + 'dante', + 'effie', + 'ezekiel', + 'gaston', + 'inez', + 'jaime', + 'jefferson', + 'lee', + 'nettie', + 'ora', + 'palmer', + 'piper', + 'sung', +] diff --git a/data/places/cities.js b/data/places/cities.js new file mode 100644 index 000000000..3d16d188b --- /dev/null +++ b/data/places/cities.js @@ -0,0 +1,239 @@ +module.exports = [ + 'aalborg', + 'aarhus', + 'abidjan', + 'abu dhabi', + 'ahmedabad', + 'alexandria', + 'almaty', + 'amman', + 'amsterdam', + 'ankara', + 'antwerp', + 'aqaba', + 'ashdod', + 'ashgabat', + 'athens', + 'auckland', + 'baku', + 'bangalore', + 'bangkok', + 'banja luka', + 'barcelona', + 'barranquilla', + 'basel', + 'beijing', + 'beirut', + 'belgrade', + 'bergen', + 'berlin', + 'bern', + 'birmingham', + 'bogota', + 'brasilia', + 'bratislava', + 'brisbane', + 'brussels', + 'bucharest', + 'budapest', + 'buenos aires', + 'burgas', + 'bursa', + 'busan', + 'cairo', + 'calgary', + 'cape town', + 'caracas', + 'cebu', + 'chennai', + 'chiang mai', + 'chicago', + 'chittagong', + 'christchurch', + 'cologne', + 'colombo', + 'constanta', + 'copenhagen', + 'cork', + 'craiova', + 'curitiba', + 'daegu', + 'daejeon', + 'dakar', + 'damascus', + 'daugavpils', + 'dhaka', + 'doha', + 'dublin', + 'durban', + 'dushanbe', + 'edmonton', + 'eindhoven', + 'fes', + 'frankfurt', + 'galway', + 'gdansk', + 'geneva', + 'genoa', + 'ghent', + 'giza', + 'gothenburg', + 'graz', + 'guadalajara', + 'guangzhou', + 'haifa', + 'hamburg', + 'hamilton', + 'hanoi', + 'havana', + 'helsinki', + 'heraklion', + 'ho chi minh', + 'homs', + 'houston', + 'incheon', + 'istanbul', + 'i̇zmir', + 'jakarta', + 'kabul', + 'kampala', + 'kandy', + 'kaohsiung', + 'karachi', + 'karaj', + 'kaunas', + 'kharkiv', + 'kiev', + 'kingston', + 'klaipeda', + 'kobe', + 'kopavogur', + 'kosice', + 'krakow', + 'kuala lumpur', + 'la plata', + 'lausanne', + 'liege', + 'lima', + 'limassol', + 'linz', + 'lisbon', + 'liverpool', + 'london', + 'los angeles', + 'lviv', + 'lyon', + 'madrid', + 'malmo', + 'manchester', + 'mandalay', + 'manila', + 'maribor', + 'marseille', + 'medellín', + 'melbourne', + 'milan', + 'minsk', + 'miskolc', + 'montevideo', + 'montreal', + 'moscow', + 'mumbai', + 'munich', + 'nagoya', + 'nantes', + 'naples', + 'navan', + 'new delhi', + 'new taipei', + 'new york', + 'nis', + 'odessa', + 'osaka', + 'oslo', + 'ottawa', + 'palermo', + 'paris', + 'patras', + 'perth', + 'petah tikva', + 'philadelphia', + 'phnom penh', + 'phoenix', + 'pilsen', + 'piraeus', + 'port elizabeth', + 'porto', + 'poznan', + 'prague', + 'pretoria', + 'puebla', + 'pyongyang', + 'quito', + 'reykjavik', + 'riga', + 'rio de janeiro', + 'rome', + 'rosario', + 'rotterdam', + 'saint petersburg', + 'salvador', + 'salzburg', + 'san jose', + 'san salvador', + 'santiago', + 'sapporo', + 'seoul', + 'seville', + 'shanghai', + 'shenzhen', + 'skopje', + 'stockholm', + 'stuttgart', + 'sydney', + 'taichung', + 'tainan', + 'taipei', + 'tallinn', + 'tampere', + 'tangier', + 'tartu', + 'tbilisi', + 'tegucigalpa', + 'tehran', + 'tel aviv', + 'the hague', + 'thessaloniki', + 'tianjin', + 'tilburg', + 'timisoara', + 'tirana', + 'tokyo', + 'toronto', + 'toulouse', + 'trondheim', + 'tunis', + 'turin', + 'turku', + 'ulan bator', + 'utrecht', + 'valencia', + 'vancouver', + 'varna', + 'vienna', + 'vilnius', + 'warsaw', + 'wellington', + 'wexford', + 'wicklow', + 'winnipeg', + 'winterthur', + 'wroclaw', + 'yangon', + 'yekaterinburg', + 'yerevan', + 'yokohama', + 'zagreb', + 'zurich', + // 'sana\'a', +] diff --git a/data/words/places/countries.js b/data/places/countries.js similarity index 99% rename from data/words/places/countries.js rename to data/places/countries.js index b65776856..cff66988d 100644 --- a/data/words/places/countries.js +++ b/data/places/countries.js @@ -51,7 +51,6 @@ module.exports = [ 'congo-brazzaville', 'cook islands', 'costa rica', - 'cote d\'ivoire', 'croatia', 'cuba', 'curacao', @@ -92,8 +91,8 @@ module.exports = [ 'guam', 'guatemala', 'guernsey', - 'guinea', 'guinea-bissau', + 'guinea', 'guyana', 'haiti', 'honduras', @@ -112,7 +111,6 @@ module.exports = [ 'jamaica', 'japan', 'jersey', - // 'jordan', //... or a name? 'kazakhstan', 'keeling islands', 'kenya', @@ -233,8 +231,8 @@ module.exports = [ 'ukraine', 'united arab emirates', 'united kingdom', - 'united states', 'united states of america', + 'united states', 'uruguay', 'usa', 'ussr', @@ -247,5 +245,7 @@ module.exports = [ 'wallis and futuna', 'yemen', 'zambia', - 'zimbabwe' -]; + 'zimbabwe', + "cote d'ivoire", + // 'jordan', //... or a name? +] diff --git a/data/places/places.js b/data/places/places.js new file mode 100644 index 000000000..f164f148f --- /dev/null +++ b/data/places/places.js @@ -0,0 +1,70 @@ +module.exports = [ + //some of the busiest airports in the world from + //https://www.world-airport-codes.com/world-top-30-airports.html + 'ams', + 'atl', + 'bcn', + 'bkk', + 'cdg', + 'cgk', + 'clt', + 'den', + 'dfw', + 'dxb', + 'fco', + 'fra', + 'hkg', + 'hnd', + 'iax', + 'icn', + 'ist', + 'jfk', + 'kul', + 'las', + 'lax', + 'lgw', + 'lhr', + 'mco', + 'muc', + 'ord', + 'pek', + 'phl', + 'phx', + 'sfo', + 'syd', + 'yyz', + + 'antarctic ocean', + 'arctic ocean', + 'atlantic ocean', + 'everglades', + 'great britain', + 'great lakes', + 'indian ocean', + 'new england', + 'pacific ocean', + + //continents + 'africa', + 'europe', + 'americas', + 'asia', + + //some notable neighbourhoods (just #Place) + 'midtown', + 'downtown', + 'uptown', + 'the bronx', + 'brooklyn', + 'manhattan', + 'greenwich', + 'soho', + 'harlem', + 'chinatown', + 'the hamptons', + 'beverly hills', + 'bel air', + 'malibu', + 'gay village', + 'sunderland', +] diff --git a/data/words/places/regions.js b/data/places/regions.js similarity index 99% rename from data/words/places/regions.js rename to data/places/regions.js index 348a5a474..8c863a8c5 100644 --- a/data/words/places/regions.js +++ b/data/places/regions.js @@ -31,8 +31,8 @@ module.exports = [ 'new hampshire', 'new jersey', 'new mexico', - 'new york', 'new york state', + 'new york', 'north carolina', 'north dakota', 'ohio', @@ -47,8 +47,8 @@ module.exports = [ 'utah', 'vermont', 'virginia', - 'washington', 'washington dc', + 'washington', 'west virginia', 'wisconsin', 'wyoming', @@ -127,12 +127,12 @@ module.exports = [ 'zacatecas', //western-europe - 'corsica', - 'normandy', - 'midlands', - 'yorkshire', + 'basque', + 'bavaria', + 'bremen', 'buckinghamshire', 'cambridgeshire', + 'corsica', 'coventry', 'cumbria', 'derbyshire', @@ -145,22 +145,22 @@ module.exports = [ 'leeds', 'leicestershire', 'lincolnshire', + 'midlands', + 'normandy', 'north yorkshire', 'northamptonshire', 'nottinghamshire', 'oxfordshire', + 'saxony', + 'sicily', 'somerset', 'staffordshire', 'suffolk', 'surrey', 'sussex', - 'warwickshire', 'tuscany', - 'sicily', - 'basque', - 'bavaria', - 'saxony', - 'bremen', + 'warwickshire', + 'yorkshire', //bangladesh 'rajshahi', @@ -179,5 +179,5 @@ module.exports = [ 'santa catarina', //misc - 'siberia' -]; + 'siberia', +] diff --git a/data/plurals.js b/data/plurals.js deleted file mode 100644 index 84201326d..000000000 --- a/data/plurals.js +++ /dev/null @@ -1,69 +0,0 @@ -//nouns with irregular plural/singular forms -//used in noun.inflect, and also in the lexicon. -module.exports = { - 'addendum': 'addenda', - 'alga': 'algae', - 'alumna': 'alumnae', - 'alumnus': 'alumni', - 'appendix': 'appendices', - 'avocado': 'avocados', - 'bacillus': 'bacilli', - 'barracks': 'barracks', - 'beau': 'beaux', - 'bus': 'buses', - 'cactus': 'cacti', - 'chateau': 'chateaux', - 'analysis': 'analyses', - 'diagnosis': 'diagnoses', - 'parenthesis': 'parentheses', - 'prognosis': 'prognoses', - 'synopsis': 'synopses', - 'thesis': 'theses', - 'child': 'children', - 'circus': 'circuses', - 'clothes': 'clothes', - 'corpus': 'corpora', - 'criterion': 'criteria', - 'curriculum': 'curricula', - 'database': 'databases', - 'deer': 'deer', - 'echo': 'echoes', - 'embargo': 'embargoes', - 'epoch': 'epochs', - 'foot': 'feet', - 'genus': 'genera', - 'goose': 'geese', - 'halo': 'halos', - 'hippopotamus': 'hippopotami', - 'index': 'indices', - 'larva': 'larvae', - 'leaf': 'leaves', - 'libretto': 'libretti', - 'loaf': 'loaves', - 'man': 'men', - 'matrix': 'matrices', - 'memorandum': 'memoranda', - 'modulus': 'moduli', - 'mosquito': 'mosquitoes', - 'move': 'moves', - 'opus': 'opera', - 'ovum': 'ova', - 'ox': 'oxen', - 'person': 'people', - 'phenomenon': 'phenomena', - 'quiz': 'quizzes', - 'radius': 'radii', - 'referendum': 'referenda', - 'rodeo': 'rodeos', - 'sex': 'sexes', - 'shoe': 'shoes', - 'sombrero': 'sombreros', - 'stomach': 'stomachs', - 'syllabus': 'syllabi', - 'tableau': 'tableaux', - 'thief': 'thieves', - 'tooth': 'teeth', - 'tornado': 'tornados', - 'tuxedo': 'tuxedos', - 'zero': 'zeros' -}; diff --git a/data/regex.js b/data/regex.js deleted file mode 100644 index 43fcf2767..000000000 --- a/data/regex.js +++ /dev/null @@ -1,39 +0,0 @@ -//these are regexes applied to t.text, instead of t.normal -module.exports = { - //#funtime - '^#[a-z]+': 'HashTag', - //chillin' - '^[a-z]+n[\'’]$': 'Gerund', - //589-3809 - '^[0-9]{3}-[0-9]{4}$': 'PhoneNumber', - //632-589-3809 - '^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$': 'PhoneNumber', - - //dates/times - '^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$': 'Time', //4:32:32 - '^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$': 'Time', //4pm - '^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$': 'Time', //4:00pm - '^[PMCE]ST$': 'Time', //PST, time zone abbrevs - '^utc ?[+-]?[0-9]+?$': 'Time', //UTC 8+ - '^[a-z0-9]*? o\'?clock$': 'Time', //3 oclock - '^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$': 'Date', // 03-02-89 - '^[0-9]{1,4}\/[0-9]{1,2}\/[0-9]{1,4}$': 'Date', // 03/02/89 - - //money - '^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?$': ['Money', 'Value'], //like $5.30 - '^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$': ['Money', 'Value'], //like $5,231.30 - - //values - '^[0-9\.]{1,4}(st|nd|rd|th)?[-–][0-9\.]{1,4}(st|nd|rd|th)?$': 'NumberRange', //'NumericValue'], //5-7 - // '^[0-9]{1,4}[-–][0-9]{1,4}$': 'NumberRange', //'NumericValue'], //5-7 - '^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$': 'NiceNumber', //like 5,999.0 - '^[-+]?[0-9]+(.[0-9]+)?$': 'NumericValue', //like +5.0 - - '^.?[0-9]+([0-9,.]+)?%$': ['Percent', 'Cardinal', 'NumericValue'], //7% .. - '^[0-9]{1,4}/[0-9]{1,4}$': 'Fraction', //3/2ths - '^[0-9\.]{1,2}[-–][0-9]{1,2}$': ['Value', 'NumberRange'], //7-8 - //mc'adams - '^ma?c\'.*': 'LastName', - //o'douggan - '^o\'[drlkn].*': 'LastName' -}; diff --git a/data/words/verbs/infinitives.js b/data/verbs/infinitives.js similarity index 93% rename from data/words/verbs/infinitives.js rename to data/verbs/infinitives.js index 94dbec2a0..3606f39e9 100644 --- a/data/words/verbs/infinitives.js +++ b/data/verbs/infinitives.js @@ -46,11 +46,9 @@ module.exports = [ 'attract', 'avoid', 'await', - 'ban', 'bang', 'base', 'bear', - 'become', 'believe', 'belong', 'benefit', @@ -62,11 +60,8 @@ module.exports = [ 'borrow', 'bother', 'bounce', - 'brake', 'brush', - 'budget', 'bully', - 'burn', 'bury', 'call', 'cancel', @@ -86,21 +81,19 @@ module.exports = [ 'cite', 'claim', 'claw', - 'cling', 'clip', 'close', 'collapse', 'collect', 'combine', - 'come', 'comfort', 'command', 'compare', 'complain', 'concern', 'conduct', - 'confirm', 'configure', + 'confirm', 'conform', 'confront', 'consider', @@ -126,7 +119,6 @@ module.exports = [ 'cross', 'crush', 'cry', - 'cut', 'damage', 'dance', 'dare', @@ -153,7 +145,6 @@ module.exports = [ 'desire', 'destroy', 'determine', - 'die', 'differ', 'dip', 'direct', @@ -167,22 +158,17 @@ module.exports = [ 'dismiss', 'display', 'distinguish', - 'dive', 'divide', 'divorce', - 'do', 'dodge', 'doubt', 'drag', 'drain', - 'dream', 'dress', 'drift', - 'drop', 'dump', 'earn', 'echo', - 'edit', 'elect', 'embody', 'emerge', @@ -214,12 +200,11 @@ module.exports = [ 'expect', 'experience', 'explain', - 'expose', 'export', + 'expose', 'express', 'extend', 'fail', - 'fall', 'favor', 'fear', 'feature', @@ -244,14 +229,11 @@ module.exports = [ 'gain', 'gather', 'gaze', - 'get', 'gloss', - 'goes', 'govern', 'grab', 'grasp', 'grip', - 'grow', 'grumble', 'guarantee', 'guard', @@ -265,7 +247,6 @@ module.exports = [ 'heat', 'help', 'hire', - 'hold fast', 'honor', 'hope', 'host', @@ -273,9 +254,9 @@ module.exports = [ 'hurry', 'ignore', 'imagine', + 'implement', 'import', 'improve', - 'implement', 'include', 'increase', 'indicate', @@ -296,12 +277,10 @@ module.exports = [ 'join', 'judge', 'jump', - 'keep', 'kick', 'kill', 'kiss', 'knock', - 'know', 'labor', 'lack', 'laugh', @@ -324,10 +303,9 @@ module.exports = [ 'love', 'lump', 'maintain', - 'make due', 'manage', - 'market', 'march', + 'market', 'marry', 'match', 'matter', @@ -365,7 +343,6 @@ module.exports = [ 'participate', 'pass', 'pause', - 'pay', 'perform', 'permit', 'persist', @@ -394,7 +371,6 @@ module.exports = [ 'prohibit', 'promise', 'protest', - 'prove', 'provide', 'publish', 'pull', @@ -402,7 +378,6 @@ module.exports = [ 'purchase', 'pursue', 'push', - 'put', 'question', 'raise', 'range', @@ -414,18 +389,20 @@ module.exports = [ 'receive', 'reckon', 'recognize', + 'reconcile', + 'record', + 'recycle', 'reduce', + 'refactor', + 'refer', 'reflect', 'refuse', 'regard', 'regret', 'reject', 'relate', - 'release', - 'refactor', - 'revert', - 'recycle', 'relax', + 'release', 'relent', 'relive', 'rely', @@ -435,6 +412,7 @@ module.exports = [ 'remove', 'rent', 'repair', + 'repeat', 'replace', 'reply', 'report', @@ -445,29 +423,25 @@ module.exports = [ 'resent', 'reserve', 'resist', + 'resolve', 'resort', - 'restore', 'rest', + 'restore', 'restrict', + 'restructure', 'retain', 'retire', 'return', 'reveal', 'revel', 'reverse', + 'revert', 'review', 'revoke', 'reward', - 'resolve', - 'restructure', - 'record', - 'reconcile', - 'refer', - 'repeat', 'risk', 'roam', 'roll', - 'rub', 'ruin', 'rule', 'rush', @@ -479,35 +453,26 @@ module.exports = [ 'scratch', 'screw', 'search', - 'seek', 'seem', 'select', - 'send', 'sense', 'serve', - 'set', 'settle', 'share', - 'shave', 'shiver', 'shock', 'shout', 'side', 'skip', 'slam', - 'sleep', 'slip', - 'smash', 'smell', 'smile', 'smoke', - 'sneak', 'sneeze', 'sort', - 'spit', 'splash', 'spoil', - 'spring', 'sprinkle', 'stain', 'stake', @@ -545,8 +510,6 @@ module.exports = [ 'test', 'thank', 'threaten', - 'thrive', - 'take', 'torture', 'touch', 'trade', @@ -561,13 +524,12 @@ module.exports = [ 'tune', 'turn', 'twist', - 'undergo', 'undermine', 'undo', 'unite', 'unlock', - 'uplift', 'upgrade', + 'uplift', 'urge', 'use', 'value', @@ -594,11 +556,4 @@ module.exports = [ 'wreck', 'yawn', 'yield', - 'tie', - 'dream', - 'run', - 'begin', - 'win', - 'deal', - 'spin', -]; +] diff --git a/data/words/verbs/modals.js b/data/verbs/modals.js similarity index 86% rename from data/words/verbs/modals.js rename to data/verbs/modals.js index 44b0e3cdb..5e49b23cc 100644 --- a/data/words/verbs/modals.js +++ b/data/verbs/modals.js @@ -1,15 +1,15 @@ module.exports = [ 'can', - 'may', 'could', + 'lets', //arguable + 'may', 'might', - 'will', - 'ought to', - 'would', 'must', - 'shall', - 'should', + 'ought to', 'ought', + 'shall', 'shant', - 'lets' //arguable -]; + 'should', + 'will', + 'would', +] diff --git a/data/words/verbs/phrasals.js b/data/verbs/phrasals.js similarity index 99% rename from data/words/verbs/phrasals.js rename to data/verbs/phrasals.js index 10174bc57..1ba02667b 100644 --- a/data/words/verbs/phrasals.js +++ b/data/verbs/phrasals.js @@ -304,6 +304,7 @@ module.exports = [ 'hit up', 'hold back', 'hold down', + 'hold fast', 'hold off', 'hold on', 'hold out', @@ -615,8 +616,8 @@ module.exports = [ 'stave off', 'stay up', 'step up', - 'stir up', 'stink up', + 'stir up', 'stitch up', 'stop by', 'stop in', @@ -757,5 +758,5 @@ module.exports = [ 'zip by', 'zip up', 'zone out', - 'zonk out' -]; + 'zonk out', +] diff --git a/data/verbs/verbs.js b/data/verbs/verbs.js new file mode 100644 index 000000000..63bfe6bc9 --- /dev/null +++ b/data/verbs/verbs.js @@ -0,0 +1,21 @@ +//verbs we shouldn't conjugate +module.exports = [ + 'awaken', + 'born', + 'cannot', + 'frighten', + 'given', + 'gonna', + 'has', + 'hasten', + 'heighten', + 'keep tabs', + 'known', + 'lengthen', + 'lessen', + 'make sure', + 'msg', + 'seen', + 'shown', + 'worsen', +] diff --git a/data/words/dates/dates.js b/data/words/dates/dates.js deleted file mode 100644 index 381eb3017..000000000 --- a/data/words/dates/dates.js +++ /dev/null @@ -1,24 +0,0 @@ -module.exports = [ - 'weekend', - 'weekday', - - 'summer', - 'winter', - 'autumn', - - 'some day', - 'one day', - 'all day', - 'some point', - - 'eod', - 'eom', - 'standard time', - 'daylight time', - - 'today', - 'tomorrow', - 'tmr', - 'tmrw', - 'yesterday', -]; diff --git a/data/words/dates/days.js b/data/words/dates/days.js deleted file mode 100644 index 797815ff2..000000000 --- a/data/words/dates/days.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = [ - 'monday', - 'tuesday', - 'wednesday', - 'thursday', - 'friday', - 'saturday', - 'sunday', - 'mon', - 'tues', - 'wed', - 'thurs', - 'fri', - 'sat', - 'sun', - 'mondays', - 'tuesdays', - 'wednesdays', - 'thursdays', - 'fridays', - 'saturdays', - 'sundays' -]; diff --git a/data/words/dates/months.js b/data/words/dates/months.js deleted file mode 100644 index 497a63169..000000000 --- a/data/words/dates/months.js +++ /dev/null @@ -1,24 +0,0 @@ -module.exports = [ - 'january', - 'february', - 'april', - 'june', - 'july', - 'august', - 'september', - 'october', - 'november', - 'december', - 'jan', - 'feb', - 'mar', - 'apr', - 'jun', - 'jul', - 'aug', - 'sep', - 'oct', - 'nov', - 'dec', - 'sept' -]; diff --git a/data/words/index.js b/data/words/index.js deleted file mode 100644 index bd3c0625b..000000000 --- a/data/words/index.js +++ /dev/null @@ -1,66 +0,0 @@ -//directory of files to pack with `node scripts/pack.js` -//they are stored in compressed form -var lex = require('./misc'); - -//add-in the generic, flat word-lists -var data = [ - //nouns - [require('./nouns/singulars'), 'Singular'], - [require('./nouns/professions'), 'Actor'], - [require('./nouns/sportsTeams'), 'SportsTeam'], - [require('./nouns/uncountables'), 'Uncountable'], - [require('./nouns/pronouns'), 'Pronoun'], - // [require('./nouns/relative-prounoun'), 'RelativeProunoun'], - [require('./nouns/organizations'), 'Organization'], - [require('./nouns/demonyms'), 'Demonym'], - [require('./possessives'), 'Possessive'], //+pronoun? - [require('./currencies'), 'Currency'], - [require('./units'), 'Unit'], - - [require('./places/countries'), 'Country'], - [require('./places/regions'), 'Region'], - [require('./places/places'), 'Place'], - [require('./places/cities'), 'City'], - //dates - [require('./dates/days'), 'WeekDay'], - [require('./dates/dates'), ['Date', 'Noun']], - [require('./dates/holidays'), 'Holiday'], - [require('./dates/months'), 'Month'], - [require('./dates/durations'), 'Duration'], - [require('./dates/times'), 'Time'], - //people - [require('./people/firstnames'), 'FirstName'], - [require('./people/lastnames'), 'LastName'], - [require('./people/maleNames'), 'MaleName'], - [require('./people/femaleNames'), 'FemaleName'], - [require('./people/honorifics'), 'Honorific'], - [require('./people/people'), 'Person'], - //verbs - [require('./verbs/infinitives'), 'Infinitive'], - [require('./verbs/verbs'), 'Verb'], - [require('./verbs/phrasals'), 'PhrasalVerb'], - [require('./verbs/modals'), 'Modal'], - //adjectives - [require('./adjectives/adjectives'), 'Adjective'], - [require('./adjectives/comparables'), 'Comparable'], - [require('./adverbs'), 'Adverb'], - //misc - [require('./expressions'), 'Expression'], - [require('./prepositions'), 'Preposition'], - [require('./determiners'), 'Determiner'], - [require('./conjunctions'), 'Conjunction'] -]; -for (var i = 0; i < data.length; i++) { - var list = data[i][0]; - for (var o = 0; o < list.length; o++) { - //log duplicates - // if (lex[list[o]]) { - // console.log(list[o] + ' ' + lex[list[o]] + ' ' + data[i][1]); - // } - lex[list[o]] = data[i][1]; - } -} - -module.exports = lex; -// console.log(Object.keys(lex).length); -// console.log(lex['is']); diff --git a/data/words/misc.js b/data/words/misc.js deleted file mode 100644 index c2e95667d..000000000 --- a/data/words/misc.js +++ /dev/null @@ -1,53 +0,0 @@ -module.exports = { - 'better': 'Comparative', - 'earlier': 'Superlative', - 'sounds': 'PresentTense', - - 'a few': 'Value', - - 'here': 'Noun', - 'no doubt': 'Noun', - - 'is': 'Copula', - 'are': 'Copula', - 'was': 'Copula', - 'were': 'Copula', - 'am': 'Copula', - - 'if': 'Condition', - 'unless': 'Condition', - - 'said': 'PastTense', - 'had': 'PastTense', - 'been': 'PastTense', - 'began': 'PastTense', - 'came': 'PastTense', - 'did': 'PastTense', - 'meant': 'PastTense', - 'went': 'PastTense', - 'taken': 'PastTense', - - 'going': 'Gerund', - 'being': 'Gerund', - 'according': 'Gerund', - 'resulting': 'Gerund', - 'developing': 'Gerund', - 'staining': 'Gerund', - - 'not': 'Negative', - 'non': 'Negative', - 'never': 'Negative', - 'no': 'Negative', - - 'where': 'QuestionWord', - 'why': 'QuestionWord', - 'when': 'QuestionWord', - 'who': 'QuestionWord', - 'whom': 'QuestionWord', - 'whose': 'QuestionWord', - 'what': 'QuestionWord', - 'which': 'QuestionWord', - 'how\'s': 'QuestionWord', - 'how come': 'QuestionWord', - -}; diff --git a/data/words/nouns/organizations.js b/data/words/nouns/organizations.js deleted file mode 100644 index 716a74e58..000000000 --- a/data/words/nouns/organizations.js +++ /dev/null @@ -1,318 +0,0 @@ -//just a few named-organizations -//no acronyms needed. no product/brand pollution. -module.exports = [ - 'abc', - 'academy of sciences', - 'acer', - 'activision', - 'adidas', - 'aig', - 'al jazeera', - 'al qaeda', - 'alcatel-lucent', - 'alcatel', - 'altair', - 'amc', - 'amd', - 'american express', - 'amt', - 'amtrak', - 'anheuser-busch', - 'aol', - 'apple computers', - 'applebee\'s', - 'arby\'s', - 'argos', - 'armco', - 'ashland oil', - 'associated press', - 'at&t', - 'avis', - 'avon', - 'ayer', - 'banana republic', - 'basf', - 'baskin robbins', - 'baxter', - 'bayer', - 'bbc', - 'bechtel', - 'ben & jerry\'s', - 'berkshire hathaway', - 'bf goodrich', - 'bfgoodrich', - 'black & decker', - 'blockbuster video', - 'bloomingdale', - 'blue cross', - 'bmw', - 'bni', - 'boeing', - 'bombardier', - 'boston globe', - 'boston pizza', - 'bp', - 'capital one', - 'cadbury', - 'carl\'s jr', - 'cbc', - 'chevron', - 'chevy', - 'chick fil-a', - 'china daily', - 'cia', - 'cisco systems', - 'cisco', - 'citigroup', - 'cnn', - 'coca cola', - 'colgate', - 'comcast', - 'compaq', - 'coors', - 'costco', - 'craigslist', - 'crossrail', - 'daimler', - 'dea', - 'dell', - 'der spiegel', - 'disney', - 'doj', - 'dow jones', - 'dunkin donuts', - 'dupont', - 'ebay', - 'esa', - 'eu', - 'exxon mobil', - 'exxonmobil', - 'facebook', - 'fannie mae', - 'fbi', - 'fda', - 'fedex', - 'fiat', - 'financial times', - 'firestone', - 'ford', - 'frito-lay', - 'general electric', - 'general motors', - 'gmb', - 'ghq', - 'glaxo smith kline', - 'glencore', - 'goldman sachs', - 'goodyear', - 'google', - 'gucci', - 'h & m', - 'hasbro', - 'hewlett-packard', - 'hitachi', - 'hizbollah', - 'home depot', - 'honda', - 'hsbc', - 'hyundai', - 'ibm', - 'ihop', - 'ing', - 'intel', - 'interpol', - 'itv', - 'jiffy lube', - 'johnson & johnson', - 'jpmorgan chase', - 'jpmorgan', - 'jsa', - 'katv', - 'kfc', - 'kkk', - 'kmart', - 'kodak', - 'l\'oreal', - 'la presse', - 'labour party', - 'la-z-boy', - 'lenovo', - 'lexis', - 'lexmark', - 'lg', - 'little caesars', - 'mac\'s milk', - 'mattel', - 'mazda', - 'mcdonald\'s', - 'mcdonalds', - 'medicaid', - 'medicare', - 'mercedes-benz', - 'mercedes', - 'microsoft', - 'mitas', - 'mitsubishi', - 'mlb', - 'mobil', - 'monsanto', - 'motorola', - 'mtv', - 'myspace', - 'nandos', - 'nasa', - 'nascar', - 'nasdaq', - 'national academy of sciences', - 'nato', - 'natwest', - 'nba', - 'nbc', - 'nestle', - 'nestlé', - 'netflix', - 'nec', - 'new york times', - 'newsweek', - 'nfl', - 'nhl', - 'nhs', - 'nike', - 'nintendo', - 'nissan', - 'nokia', - 'notre dame', - 'novartis', - 'nsa', - 'nwa', - 'old navy', - 'opec', - 'orange julius', - 'oxfam', - 'pan am', - 'panasonic', - 'panda express', - 'pbs', - 'pepsico', - 'petrobras', - 'petrochina', - 'petronas', - 'peugeot', - 'pfizer', - 'philip morris', - 'pizza hut', - 'premier oil', - 'procter & gamble', - 'prudential', - 'quantas', - 'quizno\'s', - 'ukip', - 'rbc', - 'rbs', - 're/max', - 'readers digest', - 'red bull', - 'red cross', - 'red lobster', - 'revlon', - 'royal bank', - 'royal dutch shell', - 'ryanair', - 'safeway', - 'sainsbury\'s', - 'samsung', - 'sears', - 'siemens', - 'snp', - 'sony', - 'starbucks', - 'statoil', - 'subaru', - 't mobile', - 'taco bell', - 'td bank', - 'telefonica', - 'telus', - 'tesco', - 'tesla motors', - 'tgi fridays', - 'the daily mail', - 'tim hortons', - 'tmz', - 'toshiba', - 'toyota', - 'toys r us', - 'twitter', - 'ubs', - 'unesco', - 'unilever', - 'united nations', - 'ups', - 'usa today', - 'usps', - 'verizon', - 'visa', - 'vodafone', - 'volkswagen', - 'volvo', - 'wal-mart', - 'walgreens', - 'wall street journal', - 'walmart', - 'warner bros', - 'wells fargo', - 'westfield', - 'westinghouse', - 'world trade organization', - 'yahoo!', - 'yamaha', - 'ymca', - 'yougov', - 'youtube', - 'ywca', - - //some bands - 'abba', - 'ac/dc', - 'aerosmith', - 'bee gees', - 'coldplay', - 'creedence clearwater revival', - 'def leppard', - 'depeche mode', - 'destiny\'s child', - 'duran duran', - 'fleetwood mac', - 'green day', - 'guns n roses', - 'joy division', - 'metallica', - 'moody blues', - 'motley crue', - 'new kids on the block', - 'pink floyd', - 'r.e.m.', - 'radiohead', - 'red hot chili peppers', - 'sex pistols', - 'soundgarden', - 'spice girls', - 'the beach boys', - 'the beatles', - 'the black eyed peas', - 'the byrds', - 'the carpenters', - 'the guess who', - 'the hollies', - 'the rolling stones', - 'the smashing pumpkins', - 'the supremes', - 'the who', - 'thin lizzy', - 'u2', - 'van halen', - - // other groups - 'eurosceptics', - 'brexiteers' -]; diff --git a/data/words/nouns/professions.json b/data/words/nouns/professions.json deleted file mode 100644 index 3c8183ca6..000000000 --- a/data/words/nouns/professions.json +++ /dev/null @@ -1,53 +0,0 @@ -//professions 'lawyer' that aren't covered by verb.to_actor() - -module.exports = [ - 'accountant', - 'administrator', - 'advisor', - 'agent', - 'architect', - 'artist', - 'assistant', - 'attendant', - 'bricklayer', - 'butcher', - 'carpenter', - 'clerk', - 'deputy', - 'dietician', - 'engineer', - 'farmer', - 'firefighter', - 'fireman', - 'gardener', - 'hairdresser', - 'housekeeper', - 'instructor', - 'journalist', - 'lawyer', - 'mechanic', - 'minister', - 'musician', - 'nurse', - 'officer', - 'operator', - 'photographer', - 'plumber', - 'policeman', - 'politician', - 'practitioner', - 'president', - 'programmer', - 'psychologist', - 'receptionist', - 'researcher', - 'roofer', - 'sailor', - 'scientist', - 'secretary', - 'soldier', - 'supervisor', - 'surgeon', - 'technician', - 'therapist' -]; diff --git a/data/words/nouns/relative-prounoun.js b/data/words/nouns/relative-prounoun.js deleted file mode 100644 index e0e5f9ef0..000000000 --- a/data/words/nouns/relative-prounoun.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = [ - 'that', - 'when', - 'which', - 'whichever', - 'whichsoever', - 'who', - 'whoever', - 'whosoever', - 'whom', - 'whomever', - 'whomsoever', - 'whose', - 'whosesoever', - 'whatever', - 'whatsoever' -]; diff --git a/data/words/nouns/singulars.js b/data/words/nouns/singulars.js deleted file mode 100644 index 1351bd6c1..000000000 --- a/data/words/nouns/singulars.js +++ /dev/null @@ -1,111 +0,0 @@ -'use strict'; -//most nouns do not nead to be listed -//for whatever reasons, these look like not-nouns -// //so we make sure that they become nouns -// const toPlural = require('../../text/subset/nouns/methods/pluralize'); - -module.exports = [ - //double-consonant rule - 'egg', - 'bottle', - 'cottage', - 'kitty', - 'doggy', - - //.ing - 'funding', - 'pudding', - 'frosting', - 'bunting', - 'icing', - 'ring', - 'blessing', - 'advertising', - - //..ly rule - 'ally', - 'belly', - 'bully', - 'dolly', - 'folly', - 'rally', - 'jelly', - 'gully', - 'holly', - 'tally', - 'fly', - 'lily', - 'monopoly', - 'doily', - 'family', - 'anomaly', - 'butterfly', - 'dragonfly', - 'gadfly', - 'mayfly', - - 'ad hominem', - 'banking', - 'body', - 'boyfriend', - 'breakfast', - 'canary', - 'ceiling', - 'chocolate', - 'city', - 'civil war', - 'credit card', - 'death', - 'dinner', - 'documentary', - 'door', - 'economy', - 'energy', - 'event', - 'example', - 'friend', - - 'girlfriend', - 'glacier', - 'god', - 'grand slam', - 'head start', - 'home run', - 'home', - 'house', - 'lunch', - 'meeting', - 'model', - 'nothing', - 'number', - 'ocean', - 'others', - 'part', - 'patent', - 'problem', - 'purpose', - 'question mark', - 'record', - 'room', - 'sky', - 'student', - 'stuff', - 'string', - 'super bowl', - 'system', - 't rex', - 'there', - 'thing', - 'tic', - 'tragedy', - 'tv show', - 'us dollar', - 'us state', - 'tax return' -// 'things', -// 'yesterday', -// 'today', -// 'tomorrow', -// 'weekend', -// 'tonight' -]; diff --git a/data/words/people/honorifics.js b/data/words/people/honorifics.js deleted file mode 100644 index b2ccbf4dc..000000000 --- a/data/words/people/honorifics.js +++ /dev/null @@ -1,50 +0,0 @@ -//extend to person-names if infront of a name - 'Professor Frink' -module.exports = [ - 'king', - 'queen', - 'prince', - 'princess', - 'dutchess', - 'president', - 'excellency', - 'professor', - 'chancellor', - 'count', - 'pastor', - 'doctor', - 'reverend', - 'rabbi', - 'judge', - 'ayatullah', - 'councillor', - 'secretary', - 'sultan', - 'mayor', - 'congressman', - 'congresswoman', - 'first lady', - 'prime minister', - 'chancellor', - 'magistrate', - - 'sergeant', - 'captain', - 'commander', - 'lieutenant', - 'first lieutenant', - 'second lieutenant', - 'colonel', - 'brigadier', - 'admiral', - 'officer', - 'commander', - 'captain', - 'marshal', - 'field marshal', - 'vice admiral', - 'rear admiral', - 'taoiseach', -// 'his honorable', -// 'her honorable', -// 'the honorable', -]; diff --git a/data/words/people/people.js b/data/words/people/people.js deleted file mode 100644 index 480dd1dfd..000000000 --- a/data/words/people/people.js +++ /dev/null @@ -1,88 +0,0 @@ -module.exports = [ - //famous people with names that are hard to recognize independendtly - //male - 'messiaen', - 'saddam hussain', - 'van gogh', - 'mitt romney', - 'barack obama', - 'kanye west', - 'mubarek', - 'lebron james', - 'emeril lagasse', - 'rush limbaugh', - 'carson palmer', - 'ray romano', - 'ronaldinho', - 'valentino rossi', - 'rod stewart', - 'kiefer sutherland', - 'denzel washington', - 'dick wolf', - 'tiger woods', - 'adolf hitler', - 'hulk hogan', - 'ashton kutcher', - 'kobe bryant', - 'cardinal wolsey', - 'slobodan milosevic', - - //female - 'jk rowling', - 'virgin mary', - 'oprah winfrey', - 'reese witherspoon', - 'tyra banks', - 'halle berry', - 'paris hilton', - 'scarlett johansson', - 'theresa may', - - //family-words are people - 'father', - 'mother', - 'mom', - 'dad', - 'mommy', - 'daddy', - 'sister', - 'brother', - 'aunt', - 'uncle', - 'grandfather', - 'grandmother', - 'cousin', - 'stepfather', - 'stepmother', - 'boy', - 'girl', - 'man', - 'woman', - 'guy', - 'dude', - 'bro', - 'gentleman', - 'someone', - 'fella', - - //sometimes firstname, sometimes lastname - 'carson', - 'brock', - 'cruz', - 'gaston', - 'palmer', - 'jefferson', - 'dante', - 'ezekiel', - 'dalton', - 'lee', - 'jaime', - 'clinton', - 'inez', - 'ora', - 'nettie', - 'rosario', - 'effie', - 'sung', - 'piper' -]; diff --git a/data/words/places/cities.js b/data/words/places/cities.js deleted file mode 100644 index 54021deb5..000000000 --- a/data/words/places/cities.js +++ /dev/null @@ -1,239 +0,0 @@ -module.exports = [ - 'aalborg', - 'aarhus', - 'abidjan', - 'abu dhabi', - 'ahmedabad', - 'alexandria', - 'almaty', - 'amman', - 'amsterdam', - 'ankara', - 'antwerp', - 'aqaba', - 'ashdod', - 'ashgabat', - 'athens', - 'auckland', - 'baku', - 'bangalore', - 'bangkok', - 'banja luka', - 'barcelona', - 'barranquilla', - 'basel', - 'beijing', - 'beirut', - 'belgrade', - 'bergen', - 'berlin', - 'bern', - 'birmingham', - 'bogota', - 'brasilia', - 'bratislava', - 'brisbane', - 'brussels', - 'bucharest', - 'budapest', - 'buenos aires', - 'burgas', - 'bursa', - 'busan', - 'cairo', - 'calgary', - 'cape town', - 'caracas', - 'cebu', - 'chennai', - 'chiang mai', - 'chicago', - 'chittagong', - 'christchurch', - 'cologne', - 'colombo', - 'constanta', - 'copenhagen', - 'cork', - 'craiova', - 'curitiba', - 'daegu', - 'daejeon', - 'dakar', - 'damascus', - 'daugavpils', - 'dhaka', - 'doha', - 'dublin', - 'durban', - 'dushanbe', - 'edmonton', - 'eindhoven', - 'fes', - 'frankfurt', - 'galway', - 'gdansk', - 'geneva', - 'genoa', - 'ghent', - 'giza', - 'gothenburg', - 'graz', - 'guadalajara', - 'guangzhou', - 'haifa', - 'hamburg', - 'hamilton', - 'hanoi', - 'havana', - 'helsinki', - 'heraklion', - 'ho chi minh', - 'homs', - 'houston', - 'incheon', - 'istanbul', - 'i̇zmir', - 'jakarta', - 'kabul', - 'kampala', - 'kandy', - 'kaohsiung', - 'karachi', - 'karaj', - 'kaunas', - 'kharkiv', - 'kiev', - 'kingston', - 'klaipeda', - 'kobe', - 'kopavogur', - 'kosice', - 'krakow', - 'kuala lumpur', - 'la plata', - 'lausanne', - 'liege', - 'lima', - 'limassol', - 'linz', - 'lisbon', - 'liverpool', - 'london', - 'los angeles', - 'lviv', - 'lyon', - 'madrid', - 'malmo', - 'manchester', - 'mandalay', - 'manila', - 'maribor', - 'marseille', - 'medellín', - 'melbourne', - 'milan', - 'minsk', - 'miskolc', - 'montevideo', - 'montreal', - 'moscow', - 'mumbai', - 'munich', - 'nagoya', - 'nantes', - 'navan', - 'naples', - 'new delhi', - 'new taipei', - 'new york', - 'nis', - 'odessa', - 'osaka', - 'oslo', - 'ottawa', - 'palermo', - 'paris', - 'patras', - 'perth', - 'petah tikva', - 'philadelphia', - 'phnom penh', - 'phoenix', - 'pilsen', - 'piraeus', - 'port elizabeth', - 'porto', - 'poznan', - 'prague', - 'pretoria', - 'puebla', - 'pyongyang', - 'quito', - 'reykjavik', - 'riga', - 'rio de janeiro', - 'rome', - 'rosario', - 'rotterdam', - 'saint petersburg', - 'salvador', - 'salzburg', - 'san jose', - 'san salvador', - // 'sana\'a', - 'santiago', - 'sapporo', - 'seoul', - 'seville', - 'shanghai', - 'shenzhen', - 'skopje', - 'stockholm', - 'stuttgart', - 'sydney', - 'taichung', - 'tainan', - 'taipei', - 'tallinn', - 'tampere', - 'tangier', - 'tartu', - 'tbilisi', - 'tegucigalpa', - 'tehran', - 'tel aviv', - 'the hague', - 'thessaloniki', - 'tianjin', - 'tilburg', - 'timisoara', - 'tirana', - 'tokyo', - 'toronto', - 'toulouse', - 'trondheim', - 'tunis', - 'turin', - 'turku', - 'ulan bator', - 'utrecht', - 'valencia', - 'vancouver', - 'varna', - 'vienna', - 'vilnius', - 'warsaw', - 'wellington', - 'wexford', - 'wicklow', - 'winnipeg', - 'winterthur', - 'wroclaw', - 'yangon', - 'yekaterinburg', - 'yerevan', - 'yokohama', - 'zagreb', - 'zurich' -] diff --git a/data/words/places/places.js b/data/words/places/places.js deleted file mode 100644 index 683eb8e23..000000000 --- a/data/words/places/places.js +++ /dev/null @@ -1,70 +0,0 @@ -module.exports = [ - //some of the busiest airports in the world from - //https://www.world-airport-codes.com/world-top-30-airports.html - 'atl', - 'pek', - 'lhr', - 'hnd', - 'ord', - 'lax', - 'cdg', - 'dfw', - 'cgk', - 'dxb', - 'fra', - 'hkg', - 'den', - 'bkk', - 'ams', - 'jfk', - 'ist', - 'sfo', - 'clt', - 'las', - 'phx', - 'iax', - 'kul', - 'mia', - 'icn', - 'muc', - 'syd', - 'fco', - 'mco', - 'bcn', - 'yyz', - 'lgw', - 'phl', - - 'new england', - 'great britain', - 'great lakes', - 'pacific ocean', - 'atlantic ocean', - 'indian ocean', - 'arctic ocean', - 'antarctic ocean', - 'everglades', - - 'africa', - 'europe', - 'americas', - 'asia', - - //some notable neighbourhoods (just #Place) - 'midtown', - 'downtown', - 'uptown', - 'the bronx', - 'brooklyn', - 'manhattan', - 'greenwich', - 'soho', - 'harlem', - 'chinatown', - 'the hamptons', - 'beverly hills', - 'bel air', - 'malibu', - 'gay village', - 'sunderland', -]; diff --git a/data/words/possessives.js b/data/words/possessives.js deleted file mode 100644 index 0fd43a494..000000000 --- a/data/words/possessives.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = [ - 'mine', - 'something', - 'none', - 'anything', - 'anyone', - 'theirs', - 'himself', - 'ours', - 'his', - 'my', - 'their', - 'yours', - 'your', - 'our', - 'its', - 'herself', - 'hers', - 'themselves', - 'myself', - 'her' //this one is check ambiguous -]; diff --git a/data/words/verbs/verbs.js b/data/words/verbs/verbs.js deleted file mode 100644 index ce1484a77..000000000 --- a/data/words/verbs/verbs.js +++ /dev/null @@ -1,22 +0,0 @@ -//verbs we shouldn't conjugate -module.exports = [ - 'lengthen', - 'heighten', - 'worsen', - 'lessen', - 'awaken', - 'frighten', - 'hasten', - 'given', - //misc - 'known', - 'shown', - 'seen', - 'born', - 'make sure', - 'keep tabs', - 'gonna', - 'cannot', - 'has', - 'msg' -]; diff --git a/demo/README.md b/demo/README.md deleted file mode 100644 index e64c61191..000000000 --- a/demo/README.md +++ /dev/null @@ -1,17 +0,0 @@ - -check out the interesting demos at [http://compromise.cool/demos](compromise.cool/demos). - -these are a some simple static examples to help get things going. - -you can view them running at: - * [https://rawgit.com/nlp-compromise/compromise/master/demo/keypress/index.html](keyPress demo) - * [https://rawgit.com/nlp-compromise/compromise/master/demo/webworker/index.html](webWorker demo) - - -or to run them locally, -```bash -git clone https://github.com/nlp-compromise/compromise.git -cd demo -python -m SimpleHTTPServer -visit http://localhost:8000/ -``` diff --git a/demo/_worker.js b/demo/_worker.js new file mode 100644 index 000000000..0d8508c6f --- /dev/null +++ b/demo/_worker.js @@ -0,0 +1,12 @@ +//loads and runs compromise inside the worker-instance +self.addEventListener( + 'message', + function(e) { + // importScripts('https://unpkg.com/compromise@next') + importScripts('../builds/compromise.js') + let doc = self.nlp(e.data) + let m = doc.places() + self.postMessage(m.json({ count: true, unique: true })) + }, + false +) diff --git a/demo/conjugation/index.css b/demo/conjugation/index.css deleted file mode 100644 index c7a7304fa..000000000 --- a/demo/conjugation/index.css +++ /dev/null @@ -1,52 +0,0 @@ -html { - overflow: hidden; - height: 100%; -} -body { - overflow: auto; - display:flex; - justify-content: center; - align-items: center; - color:grey; - width:100%; - height:100%; - margin:0px; -} -#container{ - display:flex; - flex-direction: column; - justify-content: start; - text-align:center; - align-content: center; - min-height:80%; - font-family: "Avenir Next" !important; -} -#input{ - width:40rem; - height:4rem; - padding-left:0.5rem; - font-size:3rem; - border:none; - color:#44677D; - border-bottom:2px solid #A6B3BB; - font-family: "Avenir Next" !important; -} -#table{ - min-width:24rem; - min-height:5rem; - align-self: center; -} -.key{ - color:#29587F; - font-size:1rem; - vertical-align: bottom; - text-align:right; - max-width:4rem; - border-bottom:1px solid #6AA5D3; -} -.value{ - color:#9FBCD3; - vertical-align: bottom; - margin-top:1.5rem; - font-size:2.5rem; -} diff --git a/demo/conjugation/index.html b/demo/conjugation/index.html deleted file mode 100644 index 7ef3b649f..000000000 --- a/demo/conjugation/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - -
- -
- from: - -
-
-
- - - - - \ No newline at end of file diff --git a/demo/contractions/index.css b/demo/contractions/index.css deleted file mode 100644 index 51661b1bb..000000000 --- a/demo/contractions/index.css +++ /dev/null @@ -1,37 +0,0 @@ -html { - overflow: hidden; - height: 100%; -} -body { - overflow: auto; - display:flex; - justify-content: center; - align-items: center; - color:grey; - width:100%; - height:100%; - margin:0px; -} -#container{ - display:flex; - flex-direction: column; - justify-content: center; - text-align:center; - min-height:10rem; -} -#input{ - width:42rem; - height:4rem; - padding-left:0.5rem; - font-size:3rem; - border:none; - border-bottom:2px solid #A6B3BB; - color:#44677D; - font-family: "Avenir Next" !important; -} -#result{ - font-size:4rem; - color:#87cefa; - min-height:11rem; - font-family: "Avenir Next" !important; -} diff --git a/demo/contractions/index.html b/demo/contractions/index.html deleted file mode 100644 index b57a3dfcf..000000000 --- a/demo/contractions/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - -
- -
-
- - - - diff --git a/demo/performance.html b/demo/performance.html new file mode 100644 index 000000000..d10e086be --- /dev/null +++ b/demo/performance.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + +
+
nlp-compromise stress-test
+
parse a bunch of large texts in the browser
+ +
+
+
+ + + + + diff --git a/demo/plugin.html b/demo/plugin.html new file mode 100644 index 000000000..ab2a751ff --- /dev/null +++ b/demo/plugin.html @@ -0,0 +1,29 @@ + + + + + + + + + + +
compromise plugin demo ...
+ + diff --git a/demo/value-parsing/index.css b/demo/value-parsing/index.css deleted file mode 100644 index af42e3792..000000000 --- a/demo/value-parsing/index.css +++ /dev/null @@ -1,37 +0,0 @@ -html { - overflow: hidden; - height: 100%; -} -body { - overflow: auto; - display:flex; - justify-content: center; - align-items: center; - color:grey; - width:100%; - height:100%; - margin:0px; -} -#container{ - display:flex; - flex-direction: column; - justify-content: center; - text-align:center; - min-height:10rem; -} -#input{ - width:40rem; - height:4rem; - padding-left:0.5rem; - font-size:3rem; - border:none; - border-bottom:2px solid #A6B3BB; - color:#44677D; - font-family: "Avenir Next" !important; -} -#result{ - font-size:4rem; - color:#87cefa; - min-height:6rem; - font-family: "Avenir Next" !important; -} diff --git a/demo/value-parsing/index.html b/demo/value-parsing/index.html deleted file mode 100644 index 518dccc1a..000000000 --- a/demo/value-parsing/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - -
- -
-
- - - - diff --git a/demo/webworker.html b/demo/webworker.html new file mode 100644 index 000000000..ca4d86cc8 --- /dev/null +++ b/demo/webworker.html @@ -0,0 +1,97 @@ + + + + + + + +
+ It's sometimes clever to run compromise in a + webworker. +

+
+ This way you can keep the synchronous operations off the main-thread, +
+
    + and run multiple tasks (potentially) in parallel. +
+
+
+ +
worker output:
+
+ + diff --git a/demo/webworker/freshPrince.js b/demo/webworker/freshPrince.js deleted file mode 100644 index f3ef0fda4..000000000 --- a/demo/webworker/freshPrince.js +++ /dev/null @@ -1,28 +0,0 @@ -window.freshPrince = `Now this is a story all about how my life got flipped-turned upside down. -and I'd like to take a minute, just sit right there, I'll tell you how I became the prince of a town called Bel-Air. - -In west Philadelphia born and raised, on the playground was where I spent most of my days. -Chillin' out maxin' relaxin' all cool, and all shooting some b-ball outside of the school. -When a couple of guys who were up to no good started making trouble in my neighborhood, -I got in one little fight and my mom got scared, she said, "You're movin' with your auntie and uncle in Bel-Air". - -I begged and pleaded with her day after day but she packed my suitcase and sent me on my way. -She gave me a kiss and then she gave me my ticket. I put my Walkman on and said, "I might as well kick it". - -First class, yo, this is bad. Drinking orange juice out of a champagne glass. -Is this what the people of Bel-Air living like? Hmm, this might be alright. - -But wait I hear they're prissy, bourgeois, all that. Is this the type of place that they just send this cool cat? -I don't think so, I'll see when I get there. -I hope they're prepared for the prince of Bel-Air. - -Well, the plane landed and when I came out. There was a dude who looked like a cop standing there with my name out. -I ain't trying to get arrested yet, I just got here. -I sprang with the quickness like lightning, disappeared. - -I whistled for a cab and when it came near. The license plate said "Fresh" and it had dice in the mirror. -If anything I could say that this cab was rare, but I thought, "Nah, forget it" – "Yo, home to Bel-Air"! - -I pulled up to the house about 7 or 8 and I yelled to the cabbie, "Yo home smell ya later". -I looked at my kingdom, I was finally there. To sit on my throne as the Prince of Bel-Air. -`; diff --git a/demo/webworker/index.css b/demo/webworker/index.css deleted file mode 100644 index b6bcc634f..000000000 --- a/demo/webworker/index.css +++ /dev/null @@ -1,26 +0,0 @@ -html { - overflow: hidden; - height: 100%; -} -body { - overflow: auto; - position:relative; - width:100%; - height:100%; - padding:20%; - color:grey; - font-family: "Avenir Next" !important; -} -#desc { - color:steelblue; -} -.textarea { - position:relative; - width:400px; - height:200px; - color:lightgrey; - border-radius:5px; -} -#result { - color:#B1A8FF; -} diff --git a/demo/webworker/index.html b/demo/webworker/index.html deleted file mode 100644 index fc396a0f4..000000000 --- a/demo/webworker/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - -
-
- It's sometimes clever to run compromise - in a webworker. -

-
- This way you can keep the synchronous operations off the main-thread, -
-
    - and run multiple tasks (potentially) in parallel. -
-
-
-

-
original text:
- -

-
webworker response:
-

-
-
- - - - - diff --git a/demo/webworker/webworker.js b/demo/webworker/webworker.js deleted file mode 100644 index 5cacc9957..000000000 --- a/demo/webworker/webworker.js +++ /dev/null @@ -1,7 +0,0 @@ -//loads and runs compromise inside the worker-instance -self.addEventListener('message', function(e) { - importScripts('https://unpkg.com/compromise@latest/builds/compromise.min.js'); - var r = self.nlp(e.data); - var s = r.sentences(0).toUpperCase(); - self.postMessage(s.out('html')); -}, false); diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index a8924863f..000000000 --- a/docs/README.md +++ /dev/null @@ -1,4 +0,0 @@ -for the pretty version, see [compromise.cool/docs](http://compromise.cool/docs) - -this is the json version of the docs, which are run [as part of the unit tests](../test/unit/docs/docs.test.js) -this ensures that the docs stay somewhat up-to-date diff --git a/docs/api.json b/docs/api.json deleted file mode 100644 index 925d5d4ab..000000000 --- a/docs/api.json +++ /dev/null @@ -1,765 +0,0 @@ -{ - "generic": { - "doc-inspect": { - "data": { - "desc": "return a handy array of meta-data for this subset. Default subset is sentences, but it can be anything.", - "example": "nlp('The stage was set for the Alan Parsons Project! Which I believe was some sort of hovercraft.').data()\n//[{normal:'the stage was set...'}]", - "returns": "array" - }, - "found": { - "desc": "is the match empty or not", - "returns": "bool", - "example": "nlp('oh say can you see?').match('see').found\n//true" - }, - "all": { - "desc": "zooms-out from a subset back to the whole input", - "returns": "Text", - "example": "nlp('this is yelling').verbs().toTitleCase().all().out()\n//this IS yelling" - }, - "debug": { - "desc": "pretty-print the current selection to the console", - "returns": "Text", - "example": "nlp('wayne’s world, party time, excellent- weeeyooweeeyoo!').out()" - }, - "out": { - "desc": "render parsed data as an output. supports `text`, `normal`, `array`, `html`, `grid`, `color`, `debug`, `csv`", - "returns": "Text", - "example": "nlp('you might say there’s a little Uter in all of us').match('#Adjective uter').out('html')\n//little Uter" - }, - "whitespace": { - "desc": "set before or after whitespace on each match", - "returns": "Text", - "example": "nlp('We like Roy! We like Roy!').whitespace.before(' ').out()\n//We like Roy! We like Roy!" - }, - "normalize": { - "desc": "transforms whitespace, case, punctuation, contractions and values, so that they are more standard and workable", - "returns": "Text", - "example": "nlp(' so... you like DONUTS? have all the donuts in the WORLD!!!').normalize().sentences(0).out()\n//So you like donuts?" - }, - "length": { - "desc": "how many individual matches in the result", - "returns": "int", - "example": "nlp('jackie kennedy and aristotle onassis').people().length\n//2" - }, - "random": { - "desc": "sample a random section of n matches", - "returns": "Text", - "example": "nlp('one two three four').terms().random(2).out('array')\n//['four','one']" - }, - "sort": { - "desc": "set a new ordering for the sentences/results. Accepts `alphabetical`, `chronological`, `length`, `wordcount`, `frequency`", - "returns": "Text", - "example": "nlp('Larry, Curly, and Moe').people().sort('alphabetical').out('array')\n//Curly, Larry, Moe" - }, - "forEach": { - "desc": "do something on each result independently", - "returns": "Text", - "example": "nlp('Larry, Curly, and Moe').people().forEach((m,i)=> m.people().toLowerCase() )\n//curly\n//larry\n//moe" - }, - "map": { - "desc": "create a new array from these results", - "returns": "Text", - "example": "nlp('Larry, Curly, and Moe').people().map((m)=> m.out('normal'))\n// ['curly', 'larry', 'moe']" - }, - "filter": { - "desc": "select only the results that return true for some function", - "returns": "Text", - "example": "nlp('Larry, Curly, and Moe').people().filter(m => m.out('normal')==='larry' ).length\n//1" - }, - "find": { - "desc": "select only the first result that returns true", - "returns": "Text", - "example": "nlp('Larry, Curly, and Moe').people().find(m => m.out('normal')==='larry' ).out()\n//\"Larry,\"" - }, - "reduce": { - "desc": "combine the results of a function into one thing", - "returns": "Text", - "example": "nlp('Larry, Curly, and Moe').people().reduce((h,m) => {\n var str=m.out('normal');\n h[str]=true;\n return h }, {})\n//{larry:true, curly:true, moe:true}" - } - }, - "word-changes": { - "toTitleCase": { - "desc": "set the first letter of each term as a capital", - "returns": "Text", - "example": "nlp('jupiter, pluto and mars').nouns().toTitleCase().all().out()\n//Jupiter, Pluto and Mars." - }, - "toUpperCase": { - "desc": "set all the letters as a capital", - "returns": "Text", - "example": "nlp('Dental plan. Lisa needs braces.').match('dental .').toUpperCase().out()\n//DENTAL PLAN." - }, - "toLowerCase": { - "desc": "set all the letters as a not-capital. Even acronyms and first-letters of sentences", - "returns": "Text", - "example": "nlp('Careful! They’re RUFFLED!!').toLowerCase().out()\n//careful! they’re ruffled!!" - }, - "toCamelCase": { - "desc": "remove whitespace and titlecase the words", - "returns": "Text", - "example": "nlp('natural language processing').toCamelCase().out()\n//NaturalLanguageProcessing" - }, - "hyphenate": { - "desc": "remove whitespace and add a hyphenate between the words", - "returns": "Text", - "example": "nlp('natural language processing').hyphenate().out()\n//natural-language-processing" - }, - "dehyphenate": { - "desc": "remove hyphens and add normal whitespace between words", - "returns": "Text", - "example": "nlp('natural-language processing').dehyphenate().out()\n//natural language processing" - }, - "trim": { - "desc": "remove leading and trailing whitespace from each match", - "returns": "Text", - "example": "nlp(' Lenny and Carl ').people().trim().out()\n//['Lenny', 'Carl']" - }, - "getPunctuation": { - "desc": "get an array of trailing-punctuation for the results", - "returns": "Array", - "example": "nlp('my bubbly, longnecked, beechwood aged lover').adjectives().eq(1).getPunctuation()\n//[',']" - }, - "setPunctuation": { - "desc": "overwrite the trailing punctuation", - "returns": "Text", - "example": "nlp('there\\'s a new mexico?').sentences().setPunctuation('!??').out()\n//there's a new mexico!??" - } - }, - "sentence-changes": { - "insertBefore": { - "desc": "append a word (or words) before each match", - "mutative": true, - "returns": "Text", - "example": "nlp('stupid flanders').match('flanders').insertBefore('sexy').all().out()\n//stupid sexy flanders" - }, - "insertAfter": { - "desc": "append a word (or words) after each match", - "mutative": true, - "returns": "Text", - "example": "nlp('i know so many words').insertAfter('bigly').all().out()\n//i know so many words bigly" - }, - "insertAt": { - "desc": "insert a word or words at a known index (zero-based)", - "mutative": true, - "returns": "Text", - "example": "nlp('so you are from Africa?').insertAt(2, 'like,').all().out()\n//so you are like, from africa?" - }, - "lump": { - "desc": "merge matches into one term, with shared tags.", - "mutative": true, - "returns": "Text", - "example": "nlp('Keanu Reeves said whoa').match('#Person+').lump().all().out('terms')\n//['Keanu Reeves', 'said', 'whoa']" - }, - "replaceWith": { - "desc": "turn the current selection into something else. Essentially just delete() -> insertAt(). The second param says whether to keep original tags around.", - "mutative": true, - "returns": "Text", - "example": "nlp('it was the worst of times').match('worst').replaceWith('blurst', true).all().out()\n//it was the blurst of times" - }, - "replace": { - "desc": "turn a new selection into something else. Essentially just match() -> delete() -> insertAt(). Third optional param keeps original tags around.", - "mutative": true, - "returns": "Text", - "example": "nlp('trust me folks, big league.').replace('big league','bigly').all().out()\n//trust me folks, bigly." - }, - "delete": { - "desc": "remove a match from the Text permanently. For a temporary filter, see `.not()`", - "mutative": true, - "returns": "Text", - "example": "nlp('you don’t win friends with salad').delete('do not').out()\n//you win friends with salad" - }, - "splitOn": { - "desc": "split matches into [before, match, after]", - "mutative": true, - "returns": "Text", - "example": "nlp('Monorail...Once again! Monorail... Monorail!').splitOn('monorail').get(0).out()\n//Monorail" - }, - "splitBefore": { - "desc": "split matches into [before, match + after]", - "mutative": true, - "returns": "Text", - "example": "nlp('Monorail...Once again! Monorail... Monorail!').splitBefore('monorail').get(0).out()\n//Monorail...Once again!" - }, - "splitAfter": { - "desc": "split matches into [before + match, after]", - "mutative": true, - "returns": "Text", - "example": "nlp('Monorail...Once again! Monorail... Monorail!').splitAfter('monorail').get(0).out()\n//Monorail" - }, - "slice": { - "desc": "grab a subset of the results", - "mutative": false, - "returns": "Text", - "example": "nlp('Homer, have you been eating that sandwich again?').terms().slice(0, 3).out()\n//Homer, have you" - }, - "clone": { - "desc": "copy the object, so changes no longer effect the original (make it ~immutable)", - "mutative": false, - "returns": "Text", - "example": "nlp('would somebody please think of the children').clone().toUpperCase().parent.out()\n//would somebody please think of the children" - }, - "concat": { - "desc": "combine two results into one", - "mutative": false, - "returns": "Text", - "example": "nlp('My name is Otto').concat('and i love to get blotto').sentences().length\n//1" - }, - "flatten": { - "desc": "turn a list of results into one result", - "mutative": false, - "returns": "Text", - "example": "nlp('sex cauldron? I thought they closed that place down.').flatten().length\n//1" - } - }, - "match/tag": { - "match": { - "desc": "zoom-in to a subset of the text, using a [regex-like syntax](https:\n//github.com/nlp-compromise/compromise/wiki/Match-syntax)", - "returns": "Text", - "example": "nlp('we understand, we are from the land of chocolate.').match('land of #Noun').out()\n//land of chocolate" - }, - "not": { - "desc": "return parts of the text that do not match. Like .match() but opposite.", - "returns": "Text", - "example": "nlp('wait, there’s a new mexico?').places().not('new').out()\n//mexico" - }, - "if": { - "desc": "returns only the sets which contain this match. Like a Array.filter() method, for your results", - "returns": "Text", - "example": "nlp('We’re here, we’re clear, we don’t want anymore bears.').clauses().if('anymore').out()\n//we don't want anymore bears" - }, - "ifNo": { - "desc": "removes any sets that have this match", - "returns": "Text", - "example": "nlp('We’re here, we’re clear, we don’t want anymore bears.').clauses().ifNo('anymore').out()\n//We're here, we're clear," - }, - "has": { - "desc": "quick check to see if this match is found", - "returns": "Boolean", - "example": "nlp('I am the very model of a modern Major-General').has('#Pronoun')\n//true," - }, - "before": { - "desc": "find a match, and return everything infront of it", - "returns": "Text", - "example": "nlp('one two three four five').before('three').out()\n//one two" - }, - "after": { - "desc": "find a match, and return everything following of it", - "returns": "Text", - "example": "nlp('one two three four five').after('three').out()\n//four five" - }, - "tag": { - "desc": "set a particular interpretation for these terms. Can tag your match as anything. Supported tags do dependency/conflict logic.", - "returns": "Text", - "example": "nlp('Michael Apple ate a delicious apple.').match('#FirstName apple').tag('Person').people().out()\n//Michael Apple" - }, - "unTag": { - "desc": "remove a particular tag for all these terms. Passing in a '*' removes all the current tags.", - "returns": "Text", - "example": "nlp('they made a catch & scored a run').match(['run','catch']).unTag('#Verb').nouns().out('array')\n//catch, run" - }, - "canBe": { - "desc": "return only terms that have no conflicts with this tag", - "returns": "Text", - "example": "nlp('it’s fusilli jerry!').canBe('Person').out()\n//fusilli jerry" - } - } - }, - "subsets": { - "contractions": { - "data": { - "desc": "return a handy array of meta-data for this the contractions in this text", - "example": "nlp(' I’d like to request seventeen dollars for a push broom rebristling').contractions().data()\n//[{text:'I'd'}]", - "returns": "array" - }, - "expand": { - "desc": "turn `didn't` into `did not`, etc", - "returns": "Text", - "example": "nlp('He’s the greatest guy in history').contractions().expand().out('')\n//He is" - }, - "contract": { - "desc": "turn did not into didn't, etc.", - "returns": "Text", - "example": "nlp('He is about to hit a chestnut tree').contractions().contract().out('')\n//He's" - }, - "contracted": { - "desc": "show only the contractions that are currently contracted -eg. `i'll` but not `i will`", - "returns": "Text", - "example": "nlp('Lisa, I’d like to buy your rock.').contractions().contracted().out('')\n//I'd" - }, - "expanded": { - "desc": "show only the contractions that are currently not contracted -eg. `he would` but not `he'd`", - "returns": "Text", - "example": "nlp('Lisa, I would like to buy your rock.').contractions().expanded().out('')\n//I would" - } - }, - "dates": { - "data": { - "desc": "return an array of meta-data about the dates and times in this text", - "example": "nlp('Finally, I just stopped caring. Luckily for me, it was 1980 and no one noticed.').dates().data()\n//[{text:'1980'}]", - "returns": "array" - }, - "toShortForm": { - "desc": "turn 'Thurs' and 'Sept' into `Thursday` and `September`", - "returns": "Text", - "example": "nlp('April, June, and Sept').dates().toShortForm().all().out()\n//Apr, Jun, and Sept" - }, - "toLongForm": { - "desc": "turn `Thursday` and `September` into 'Thurs' and 'Sept'", - "returns": "Text", - "example": "nlp('April, June, and Sept').dates().toShortForm().all().out()\n//April, June, and September" - } - }, - "ngrams": { - "data": { - "desc": "return a handy array of meta-data for the n-grams in this text. accepts an obj with `max` or `size` number", - "example": "nlp('love love me do.').ngrams({max:3}).data()\n//[{text:'love', count:2, size:1}..]", - "returns": "array" - }, - "unigrams": { - "desc": "return only the ngrams of size 1", - "returns": "Text", - "example": "nlp('University of Toronto, in toronto').ngrams().unigrams(0).data()\n//[{normal:'toronto', count:2, size:1}]" - }, - "bigrams": { - "desc": "return only the ngrams of size 2", - "returns": "Text", - "example": "nlp('The University of Ryerson and University of Toronto, in toronto').ngrams().bigrams(0).data()\n//[{normal:'university of', count:2, size:2}]" - }, - "trigrams": { - "desc": "return only the ngrams of size 3", - "returns": "Text", - "example": "nlp('we like Roy! we like Roy!').ngrams().trigrams(0).data()\n//[{normal:'we like roy', count:2, size:3}]" - }, - "sort": { - "desc": "the default sort for ngrams - count, then size, then character length. (called by default)", - "returns": "Text", - "example": "nlp('i scream, you scream, we all scream for icecream.').ngrams().sort().first().out()\n//scream" - } - }, - "nouns": { - "data": { - "desc": "return a handy array of meta-data for the nouns in this text", - "example": "nlp('Lunchlady Doris, have you got any grease?').nouns().data()\n//[{text:'Lunchlady Doris'}, {text:'grease'}]", - "returns": "Array" - }, - "isPlural": { - "desc": "return only the plural nouns", - "returns": "Text", - "example": "nlp('All my life I’ve had one dream, to accomplish my many goals.').nouns().isPlural().out()\n//goals" - }, - "hasPlural": { - "desc": "return only the nouns which can be plural (sometimes called 'countable' nouns)", - "returns": "Text", - "example": "nlp('bring joy to the air, water, earth, and sky.').nouns().hasPlural().length\n//0" - }, - "toPlural": { - "desc": "transform singular nouns into their plural (inflected) forms", - "returns": "Text", - "example": "nlp('the purple dinosaur').nouns().toPlural().all().out()\n//the purple dinosaurs" - }, - "toSingular": { - "desc": "transform plural nouns into their singular forms", - "returns": "Text", - "example": "nlp('the king’s men').nouns().toSingular().out()\n//the king's man" - }, - "toPossessive": { - "desc": "transform nouns into a possessive form - John → John's", - "returns": "Text", - "example": "nlp('the king').nouns().toPossessive().out()\n//the king's" - }, - "articles": { - "desc": "whether this noun deserves 'a' or 'an'", - "returns": "Array", - "example": "nlp('the king').nouns().articles()\n//[{text:\"king\", article:\"a\"}]" - } - }, - "sentences": { - "data": { - "desc": "return a handy array of meta-data for the sentences in this text", - "example": "nlp('hi everybody! Hi Dr. Nick!').sentences().data().length\n//[{normal:'hi everybody'}, {normal:'hi dr nick'}]", - "returns": "array" - }, - "prepend": { - "desc": "add a word (or words) at the beginning of these sentences, and move the sentnece's titlecase appropriately", - "returns": "Text", - "example": "nlp('I know so many words.').sentences().prepend('believe me').out()\n//Believe me, I know so many words." - }, - "append": { - "desc": "add a word (or words) at the end of these sentences, and move the sentnece's punctuation appropriately", - "returns": "Text", - "example": "nlp('I know so many words.').sentences().append('big league').out()\n//I know so many words big league." - }, - "toPastTense": { - "desc": "transform the sentences so that they are in the past tense", - "returns": "Text", - "example": "nlp('I pay the Homer tax.').sentences().toPastTense().out()\n//I paid the Homer tax." - }, - "toPresentTense": { - "desc": "transform the sentences so that they are in the present tense", - "returns": "Text", - "example": "nlp('I paid the Homer tax.').sentences().toPresentTense().out()\n//I pay the Homer tax." - }, - "toFutureTense": { - "desc": "transform the sentences so that they are in the future tense", - "returns": "Text", - "example": "nlp('That’s the home-owner tax.').sentences().toFutureTense().out()\n//That will be the home-owner tax" - }, - "toContinuous": { - "desc": "like present tense, but still happening. ('walks'->'is walking')", - "returns": "Text", - "example": "nlp('rock and/or roll').sentences().toContinuous().out()\n//rocking and/or rolling" - }, - "toNegative": { - "desc": "turn the sentence negative, so that it means the opposite thing", - "returns": "Text", - "example": "nlp('Now make like my pants, and split.').sentences(0).toNegative().out()\n//Now do not make like my pants, and split." - }, - "toPositive": { - "desc": "if the sentence is negatively-stated, make it say the opposite thing", - "returns": "Text", - "example": "nlp('The goggles do nothing!').sentences().toPositive().out()\n//The goggles do everything!" - }, - "isPassive": { - "desc": "return only sentences that are passive-tense", - "returns": "Text", - "example": "nlp('you were saved by the bell').sentences().isPassive().out()\n//you were saved by the bell" - }, - "isQuestion": { - "desc": "return only sentences that are questions", - "returns": "Text", - "example": "nlp('Dogs are funny. Are they funny? Yes they are.').sentences().isQuestion().out('array')\n//['are they funny']" - }, - "toExclamation": { - "desc": "replace the sentence's end punctuation with an exclamation point", - "returns": "Text", - "example": "nlp('sweet balls of fire?').sentences().toExclamation().out()\n//sweet balls of fire!" - }, - "toQuestion": { - "desc": "turn the sentence into a question", - "returns": "Text", - "example": "nlp('Stupider like a fox.').sentences().toQuestion().out()\n//Stupider like a fox?" - }, - "toStatement": { - "desc": "turn the sentence into a statement. Replace it's end punctuation with a period", - "returns": "Text", - "example": "nlp('Go out on a Tuesday? Who am I, Charlie Sheen?').sentences(0).toStatement().out()\n//Go out on a Tuesday. Who am I, Charlie Sheen?" - } - }, - "people": { - "data": { - "desc": "return a handy array of meta-data of people mentioned in the text", - "example": "nlp('The bone-rattling bass of Mel Schacher? The competent drum work of Don Brewer?').people().data()\n//[{text:' Mel Schacher'}, {text:'Don Brewer'}]", - "returns": "array" - }, - "pronoun": { - "desc": "find the pronoun used to refer to the person, or suggest one based on their inferred gender.", - "returns": "String", - "example": "nlp('Tony Hawk did a 900').people().pronoun()\n//'he'" - }, - "firstNames": { - "desc": "grab only the first-names", - "returns": "Text", - "example": "nlp('Tony Hawk did a 900').people().firstNames().out('array')\n//['tony']" - }, - "lastNames": { - "desc": "grab only the last-names", - "returns": "Text", - "example": "nlp('Tony Hawk did a 900').people().lastNames().out('array')\n//['hawk']" - } - }, - "values": { - "data": { - "desc": "return a handy array of meta-data for the numbers and values in this text", - "example": "nlp('I’d like to request seventeen dollars for a push broom rebristling').values().data()\n//[{number:17, TextValue:{ Ordinal:'seventeenth'}, NumericValue:{ Ordinal:'17th'}} ]", - "returns": "array" - }, - "noDates": { - "desc": "remove numbers that are also dates, like in 'June 5th 1999'.", - "returns": "Text", - "example": "nlp('in 2016, I’m going to party like it’s on sale for $19.99.').values().noDates().length\n//1" - }, - "noUnits": { - "desc": "remove 'books' from '12 books'", - "returns": "Text", - "example": "nlp('harry potter and the 12 sequels').values().noUnits().out()\n//'12'" - }, - "toNumber": { - "desc": "turn a written number like `five thousand five hundred` into it's numerical form, like `5500`", - "returns": "Text", - "example": "nlp('ten things i hate about you').values().toNumber().all().out()\n//10 things i hate about you" - }, - "toText": { - "desc": "turn a number like `5,500` into it's textual form, like `five thousand five hundred`", - "returns": "Text", - "example": "nlp('10 things i hate about you').values().toText().all().out()\n//ten things i hate about you" - }, - "toNice": { - "desc": "turn a number into numerical form, but with nice commas, like `5,500`", - "returns": "Text", - "example": "nlp('five hundred sixty two thousand, four hundred and seven').values().toNice().all().out()\n//'562,407'" - }, - "toCardinal": { - "desc": "turn `fifth` into `five`, and `5th` into `5`", - "returns": "Text", - "example": "nlp('twenty-third of december').values().toCardinal().all().out()\n//23rd of december" - }, - "toOrdinal": { - "desc": "turn `five` into `fifth` and `5` into `5th`", - "returns": "Text", - "example": "nlp('three strikes').values().toOrdinal().all().nouns().toSingular().all().out()\n//third strike" - }, - "numbers": { - "desc": "return the actual javascript integers (or floats)", - "returns": "Array", - "example": "nlp('at the seven eleven').values().numbers()\n// [7, 11]" - }, - "greaterThan": { - "desc": "return only the values larger than a given value", - "returns": "Text", - "example": "nlp('seven peaches weigh ten kilograms').values().greaterThan(7).out('array')\n// ['10']" - }, - "lessThan": { - "desc": "return only the values smaller than a given value", - "returns": "Text", - "example": "nlp('he is 7 years old').values().greaterThan('five').out('array')\n// ['7']" - }, - "between": { - "desc": "return values between a max and min - wrapper of .greaterThan(min).lessThan(max)", - "returns": "Text", - "example": "nlp('seven peaches weigh ten kilograms').values().between(8, 12).out('array')\n// ['7']" - }, - "isEqual": { - "desc": "return only the values equal to a given value", - "returns": "Text", - "example": "nlp('his 7th birthday').values().isEqual(7).out('array')\n// ['7th']" - }, - "add": { - "desc": "increment the current number by a given integer", - "returns": "Text", - "example": "nlp('his 7th birthday').values().add(2).out()\n// 'his 9th birthday'" - }, - "subtract": { - "desc": "subtract the current number by a given integer", - "returns": "Text", - "example": "nlp('his seventh birthday').values().subtract(2).out()\n// 'his fifth birthday'" - }, - "increment": { - "desc": "add one to the current number", - "returns": "Text", - "example": "nlp('his seventh birthday').values().increment().out()\n// 'his eighth birthday'" - }, - "decrement": { - "desc": "subtract one from the current number", - "returns": "Text", - "example": "nlp('his 7th birthday').values().decrement().out()\n// 'his 6th birthday'" - } - }, - "verbs": { - "data": { - "desc": "return a handy array of meta-data for the verbs and their auxillaries in this text", - "example": "nlp('he will have been walking quickly').verbs().data()\n//[{verb:'walking', auxillary:'will have been', adverb:'quickly'}]\n", - "returns": "array" - }, - "conjugation": { - "desc": "which form of is the verb in currently? PastTense, PresentTense, Infinitive, etc", - "returns": "String", - "example": "nlp('My cat’s breath smells like cat food').verbs().conjugation()\n//['PresentTense']\n" - }, - "conjugate": { - "desc": "blast-out all conjugated forms of these verbs", - "returns": "Array", - "example": "nlp('she walked the walk').verbs().conjugate()\n//[{Infinitive:'walk', ...}]\n" - }, - "isSingular": { - "desc": "return only the verbs that are singular, like 'is' but not 'are'", - "returns": "Text", - "example": "nlp('we were discussing Wittgenstein over a game of backgammon').verbs().isSingular().out('array')\n//[{text:'were discussing'}]\n" - }, - "isPlural": { - "desc": "return only the verbs that are plural, like 'are' but not 'is'", - "returns": "Text", - "example": "nlp('We were sitting in Barney’s car').verbs().isPlural().out('array')\n//[]\n" - }, - "isPositive": { - "desc": "return only the verbs that are not negative, like 'would sing' but not 'would not sing'", - "returns": "Text", - "example": "nlp('Dear Miss Hoover, you have Lyme disease.').verbs().isPositive().length\n //1\n " - }, - "isNegative": { - "desc": "return only the verbs that are negative, like 'would not sing' but not 'would sing'", - "returns": "Text", - "example": "nlp('Dear Miss Hoover, you have Lyme disease.').verbs().isNegative().length\n//0\n" - }, - "toNegative": { - "desc": "make the verbs mean the opposite thing - `walk`->`did not walk` etc", - "returns": "Text", - "example": "nlp('Dear Miss Hoover, you have Lyme disease.').verbs().toNegative().out()\n//do not have\n" - }, - "toPositive": { - "desc": "if the verb is negative, make it not negative", - "returns": "Text", - "example": "nlp('Dear Miss Hoover, you do not have Lyme disease').verbs().toPositive().out()\n//have\n" - }, - "toPastTense": { - "desc": "turn the verb into past tense - `walk`->`walked` etc.", - "returns": "Text", - "example": "nlp('It tastes like burning.').verbs().toPastTense().out()\n//tasted\n" - }, - "toPresentTense": { - "desc": "turn the verb into present tense - `walked`->`walks` etc.", - "returns": "Text", - "example": "nlp('you ate the sandwich?').verbs().toPresentTense().out()\n//you eat the sandwich?\n" - }, - "toFutureTense": { - "desc": "turn the verb into future tense - `walked`->`will walk` etc.", - "returns": "Text", - "example": "nlp('rock and/or roll').verbs().toGerund().out('array')\n//['rocking','rolling']" - }, - "toGerund": { - "desc": "turn the verb into 'continual' tense - `walked`->`walking` etc.", - "returns": "Text", - "example": "nlp('I’m a furniture! ').verbs().toFutureTense().out()\n//will be" - }, - "asAdjective": { - "desc": "conjugate the verb to its adjectival form - `walk`->`walkable`", - "returns": "Array", - "example": "nlp('strain').verbs().asAdjective()\n//strenuous" - } - }, - "acronyms": { - "stripPeriods": { - "desc": "turn 'FBI' into 'F.B.I.'", - "returns": "Text", - "example": "nlp('Director of the F.B.I.').acronyms().stripPeriods().out()\n//Director of the FBI" - }, - "addPeriods": { - "desc": "turn 'FBI' into 'F.B.I.'", - "returns": "Text", - "example": "nlp('Director of the FBI').acronyms().addPeriods().out()\n//Director of the F.B.I." - }, - "data": { - "desc": "return an array of meta-data for the acronyms in this text", - "example": "nlp('In the USA, the big CIA. The Bloods and the Crips, and the KKK.').acronyms().data()\n//[{text:'USA'...}]", - "returns": "array" - } - }, - "adjectives": { - "data": { - "desc": "return an array of meta-data for the adjectives and their adverbs", - "example": "nlp('Guys, we have to assume our guns are useless. Throw them in the lake.').adjectives().data()\n//[{text:'useless'}]", - "returns": "array" - } - }, - "adverbs": { - "data": { - "desc": "return an array of meta-data for the adverbs in this text", - "example": "nlp('truly, madly, deeply').adverbs().data()\n//[{text:'truly'...}]", - "returns": "array" - } - }, - "clauses": { - "data": { - "desc": "return an array of words split by sentence phrase (clause)", - "example": "nlp('All right, Colossus, you’re free to go, but stay away from Death Mountain').clauses().data()\n//[{normal:'all right'}, {normal:'Colossus'}, {normal:'you're free to go'},]", - "returns": "array" - } - }, - "hashTags": { - "data": { - "desc": "return an array of parsed hashtags used in the text", - "example": "nlp('oh, but where is the #anykey').hashTags().data()\n//[{normal:'anykey'}]", - "returns": "array" - } - }, - "startGrams": { - "data": { - "desc": "return an array of subsequences beginning at the start of each sentence or match", - "example": "nlp('Who controls the British crown? Who keeps the metric system down?').startGrams().data()\n//[{normal:'who', size:1, count:2}...]", - "returns": "array" - } - }, - "endGrams": { - "data": { - "desc": "return an array of subsequences ending at the end of each sentence or match", - "example": "nlp('you think that’s a knife? I’ll show you a knife.').endGrams().data()\n//[{normal:'knife', count:2, size:1}...]", - "returns": "array" - } - }, - "organizations": { - "data": { - "desc": "return an array of named-organizations in this text", - "example": "nlp('Your dreams may vary from those of Globex Corporation, its subsidiaries and shareholders.').organizations().data()\n//[{text:'Globex Corporation'}]", - "returns": "array" - } - }, - "phoneNumbers": { - "data": { - "desc": "return an array of parsed phonenumbers in this text", - "example": "nlp('Moe Sizlak. That’s right. I’m a surgeon. (800) 555-0000.').phoneNumbers().data()\n//[{text:'(800) 555-0000'}]", - "returns": "array" - } - }, - "places": { - "data": { - "desc": "return an array of locations mentioned in this text", - "example": "nlp('you could still go to McGill, the Harvard of Canada!').places().data()\n//[{normal:'canada'}]", - "returns": "array" - } - }, - "parentheses": { - "data": { - "desc": "return a list of phrases between ( ) brackets.", - "example": "nlp('Use a pointed stick (a pencil) or a similar tool').parentheses().data()\n//[{text:'a pencil'}..]", - "returns": "array" - } - }, - "questions": { - "data": { - "desc": "return an array of question sentences in this text", - "example": "nlp('are you saying boo, or boo-urns?').questions().data().length\n//1", - "returns": "array" - } - }, - "quotations": { - "data": { - "desc": "return an array of meta-data with the parsed quoations", - "example": "nlp('the he said \"crazy like a fox!\".').quotations().data().length\n//1", - "returns": "array" - } - }, - "statements": { - "data": { - "desc": "return an array of sentences that are not questions", - "example": "nlp('i was saying boo-urns.').statements().data()\n//[{normal:'i was saying boo-urns'}]", - "returns": "array" - } - }, - "terms": { - "data": { - "desc": "split all words into individual results, and return their metadata", - "example": "nlp('we should all be more like little Ruttiger').terms().data()\n//[{text:'we'}, {text:'should'}...]", - "returns": "array" - } - }, - "possessives": { - "strip": { - "desc": "grab all the things that are possessive, like \"Homer Simpson's\"", - "example": "nlp('moe’s tavern').possessives().strip()\n//moe", - "returns": "array" - } - }, - "topics": { - "data": { - "desc": "return the people, places, and organizations of this text", - "example": "nlp('Hey everybody, I’m lookin’ for Amanda Hugginkiss').topics().data()\n//[{text:'Amanda Hugginkiss'}]", - "returns": "array" - } - }, - "urls": { - "data": { - "desc": "return an array of urls mentioned in this text", - "example": "nlp('👏 http://simpsons.wikia.com').urls().data()\n//[{text:'http://simpsons.wikia.com'}]", - "returns": "array" - } - } - } -} diff --git a/fixme.md b/fixme.md deleted file mode 100644 index 3e106b85f..000000000 --- a/fixme.md +++ /dev/null @@ -1,54 +0,0 @@ -### tense - tricky cases -```js -//infinitives -['he does what he can to stop', 'he did what he could to stop', 'he will do what he can to stop'] - -//passive -['cardboard is made of tree fibre', 'cardboard was made of tree fibre', 'cardboard will be made of tree fibre'] - -//grammatical-number -['we do what we can to stop', 'we did what we could to stop', 'we will do what we can to stop'] -``` - - -## negation - tricky cases -```js -//middle-adverb -[`he quietly walked`, `he did not quietly walk`], -``` - -## inflection - add article -```js - var str = 'men go'; - var m = nlp(str).sentences().toPastTense().nouns().toSingular(); - t.equal(m.out('normal'), 'a man went', str); -``` - - -##conjugations - -// coming => com -// moving => mov -// joking => jok -// poking => pok -// naming => nam -// aching => ach -// tuning => tun -// bling => ble -// hazing => haz -// oozing => ooz -// gazing => gaz -// easing => eas -// dozing => doz -// raring => rar -// honing => hon -// fuming => fum -// razing => raz - -// lied => ly -// shed => sh -// owed => ow -// aged => ag -// aced => ac -// axed => ax -// egged => eg diff --git a/hmm.md b/hmm.md new file mode 100644 index 000000000..4553133ee --- /dev/null +++ b/hmm.md @@ -0,0 +1,95 @@ +```js +//bad greedy match issue +nlp(`wayne's world, party time`) + .match('#Noun+? wayne') + .debug() +``` + +dangling child replace.... + +```js +let doc = nlp("springfield, springfield, it's a hell of a town.") +// keep a 'dangling' child document +let a = doc.match('a hell of a town') +// transform the parent document +doc.replace('hell of a', 'reasonable') +//dangling document is updated? +return a.text() +``` + +empty split() parent + +```js +let doc = nlp(`i have two questions for Homer - 'Why lie?' and 'Lies, why?'`) +doc + .quotations() + .split() + .out('array') +doc.clauses().split() +``` + +ngram collisions + +```js +let doc = nlp('he fished and caught two fish') +doc.normalize('heavy') +console.log(doc.ngram()) +``` + +syllables issues + +```js +let doc = nlp(`Andreas Johnsson, Auston Matthews, and Zach Hyman.`) +let names = doc.clauses().split() +let json = names.syllables() +``` + +```js +nlp('it is a UNESCO world heritage site') + .acronyms() + .text() +``` + +trailing whitespace + +```js +let doc = nlp('The children are right to laugh at you, Rälf. ') +doc.text('reduced') +``` + +possessive, sentence period + +```js +nlp(`Wayne's World, party-time, excellent!! `).text('reduced') +nlp(`Wayne's World, party-time, excellent!! `).text('root') +``` + +```js +var doc = nlp('we get it, you vape.') +doc.verbs().toNegative() +console.log(doc.text()) +``` + +```js +let nlpA = nlp.clone() +nlp.extend(require('compromise-dates')) +return { + before: nlpA('quarter to nine').json(), + after: nlp('quarter to nine').json(), +} +``` + +```js +console.log(doc.normalize('heavy').text()) +``` + +```js +nlp(`Cows don't`) + .nouns() + .toSingular() +//a cow doesn't +``` + +```js +let doc = nlp('I’m lookin’ for Amanda').debug() +``` diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..eed4aac9b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2214 @@ +{ + "name": "compromise", + "version": "12.0.0-rc3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz", + "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz", + "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz", + "integrity": "sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-call-delegate": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz", + "integrity": "sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz", + "integrity": "sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A==", + "dev": true, + "requires": { + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" + } + }, + "@babel/helper-define-map": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz", + "integrity": "sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.7.4", + "@babel/types": "^7.7.4", + "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz", + "integrity": "sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg==", + "dev": true, + "requires": { + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-hoist-variables": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz", + "integrity": "sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz", + "integrity": "sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.4.tgz", + "integrity": "sha512-ehGBu4mXrhs0FxAqN8tWkzF8GSIGAiEumu4ONZ/hD9M88uHcD+Yu2ttKfOCgwzoesJOJrtQh7trI5YPbRtMmnA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.7.4", + "@babel/helper-simple-access": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4", + "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz", + "integrity": "sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "dev": true, + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz", + "integrity": "sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.7.4", + "@babel/helper-wrap-function": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-replace-supers": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz", + "integrity": "sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.7.4", + "@babel/helper-optimise-call-expression": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-simple-access": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz", + "integrity": "sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A==", + "dev": true, + "requires": { + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-wrap-function": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz", + "integrity": "sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helpers": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz", + "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==", + "dev": true, + "requires": { + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz", + "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz", + "integrity": "sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.7.4", + "@babel/plugin-syntax-async-generators": "^7.7.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz", + "integrity": "sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.7.4" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz", + "integrity": "sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.7.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-rnpnZR3/iWKmiQyJ3LKJpSwLDcX/nSXhdLk4Aq/tXOApIvyu7qoabrige0ylsAJffaUC51WiBu209Q0U+86OWQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.7.4" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz", + "integrity": "sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.7.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.4.tgz", + "integrity": "sha512-cHgqHgYvffluZk85dJ02vloErm3Y6xtH+2noOBOJ2kXOJH3aVCDnj5eR/lVNlTnYu4hndAPJD3rTFjW3qee0PA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz", + "integrity": "sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz", + "integrity": "sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz", + "integrity": "sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz", + "integrity": "sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz", + "integrity": "sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz", + "integrity": "sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz", + "integrity": "sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.7.4" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz", + "integrity": "sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz", + "integrity": "sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.13" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz", + "integrity": "sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.7.4", + "@babel/helper-define-map": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-optimise-call-expression": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz", + "integrity": "sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz", + "integrity": "sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.4.tgz", + "integrity": "sha512-mk0cH1zyMa/XHeb6LOTXTbG7uIJ8Rrjlzu91pUx/KS3JpcgaTDwMS8kM+ar8SLOvlL2Lofi4CGBAjCo3a2x+lw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz", + "integrity": "sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz", + "integrity": "sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz", + "integrity": "sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz", + "integrity": "sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz", + "integrity": "sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz", + "integrity": "sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.4.tgz", + "integrity": "sha512-/542/5LNA18YDtg1F+QHvvUSlxdvjZoD/aldQwkq+E3WCkbEjNSN9zdrOXaSlfg3IfGi22ijzecklF/A7kVZFQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.4.tgz", + "integrity": "sha512-k8iVS7Jhc367IcNF53KCwIXtKAH7czev866ThsTgy8CwlXjnKZna2VHwChglzLleYrcHz1eQEIJlGRQxB53nqA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.7.4", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz", + "integrity": "sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz", + "integrity": "sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz", + "integrity": "sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.7.4" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz", + "integrity": "sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz", + "integrity": "sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.7.4" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz", + "integrity": "sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.7.4", + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz", + "integrity": "sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.4.tgz", + "integrity": "sha512-e7MWl5UJvmPEwFJTwkBlPmqixCtr9yAASBqff4ggXTNicZiwbF8Eefzm6NVgfiBp7JdAGItecnctKTgH44q2Jw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz", + "integrity": "sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz", + "integrity": "sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz", + "integrity": "sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz", + "integrity": "sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz", + "integrity": "sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz", + "integrity": "sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz", + "integrity": "sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/preset-env": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.4.tgz", + "integrity": "sha512-Dg+ciGJjwvC1NIe/DGblMbcGq1HOtKbw8RLl4nIjlfcILKEOkWT/vRqPpumswABEBVudii6dnVwrBtzD7ibm4g==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.7.4", + "@babel/plugin-proposal-dynamic-import": "^7.7.4", + "@babel/plugin-proposal-json-strings": "^7.7.4", + "@babel/plugin-proposal-object-rest-spread": "^7.7.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.7.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.7.4", + "@babel/plugin-syntax-async-generators": "^7.7.4", + "@babel/plugin-syntax-dynamic-import": "^7.7.4", + "@babel/plugin-syntax-json-strings": "^7.7.4", + "@babel/plugin-syntax-object-rest-spread": "^7.7.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.7.4", + "@babel/plugin-syntax-top-level-await": "^7.7.4", + "@babel/plugin-transform-arrow-functions": "^7.7.4", + "@babel/plugin-transform-async-to-generator": "^7.7.4", + "@babel/plugin-transform-block-scoped-functions": "^7.7.4", + "@babel/plugin-transform-block-scoping": "^7.7.4", + "@babel/plugin-transform-classes": "^7.7.4", + "@babel/plugin-transform-computed-properties": "^7.7.4", + "@babel/plugin-transform-destructuring": "^7.7.4", + "@babel/plugin-transform-dotall-regex": "^7.7.4", + "@babel/plugin-transform-duplicate-keys": "^7.7.4", + "@babel/plugin-transform-exponentiation-operator": "^7.7.4", + "@babel/plugin-transform-for-of": "^7.7.4", + "@babel/plugin-transform-function-name": "^7.7.4", + "@babel/plugin-transform-literals": "^7.7.4", + "@babel/plugin-transform-member-expression-literals": "^7.7.4", + "@babel/plugin-transform-modules-amd": "^7.7.4", + "@babel/plugin-transform-modules-commonjs": "^7.7.4", + "@babel/plugin-transform-modules-systemjs": "^7.7.4", + "@babel/plugin-transform-modules-umd": "^7.7.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.4", + "@babel/plugin-transform-new-target": "^7.7.4", + "@babel/plugin-transform-object-super": "^7.7.4", + "@babel/plugin-transform-parameters": "^7.7.4", + "@babel/plugin-transform-property-literals": "^7.7.4", + "@babel/plugin-transform-regenerator": "^7.7.4", + "@babel/plugin-transform-reserved-words": "^7.7.4", + "@babel/plugin-transform-shorthand-properties": "^7.7.4", + "@babel/plugin-transform-spread": "^7.7.4", + "@babel/plugin-transform-sticky-regex": "^7.7.4", + "@babel/plugin-transform-template-literals": "^7.7.4", + "@babel/plugin-transform-typeof-symbol": "^7.7.4", + "@babel/plugin-transform-unicode-regex": "^7.7.4", + "@babel/types": "^7.7.4", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.5.0" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", + "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "amble": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/amble/-/amble-0.0.7.tgz", + "integrity": "sha512-+a947e5dICWr+cNNkws5PN3Z6qi7i/BvmtcRfsa2Ymzik4cghq1R/alewhdbejgj2IaXw5X/tgHCIkd4DyabNw==", + "dev": true, + "requires": { + "chalk": "2.4.0", + "gaze": "1.1.2", + "shelljs": "0.8.1" + }, + "dependencies": { + "chalk": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "shelljs": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", + "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + } + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browserslist": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.3.tgz", + "integrity": "sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001010", + "electron-to-chromium": "^1.3.306", + "node-releases": "^1.1.40" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001012", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001012.tgz", + "integrity": "sha512-7RR4Uh04t9K1uYRWzOJmzplgEOAXbfK72oVNokCdMzA67trrhPzy93ahKk1AWHiA0c58tD2P+NHqxrA8FZ+Trg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js-compat": { + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.4.5.tgz", + "integrity": "sha512-rYVvzvKJDKoefdAC+q6VP63vp5hMmeVONCi9pVUbU1qRrtVrmAk/nPhnRg+i+XFd775m1hpG2Yd5RY3X45ccuw==", + "dev": true, + "requires": { + "browserslist": "^4.7.3", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "efrt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/efrt/-/efrt-2.2.1.tgz", + "integrity": "sha512-QNemkK2zg2lNtBxji1lR/sI9HoWb5qSsHXByeGQ0k6MUb45kJbqlgTyAFGCNMbJGzgnUSPVG9UWTwgEFHO78zg==", + "dev": true + }, + "efrt-unpack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/efrt-unpack/-/efrt-unpack-2.2.0.tgz", + "integrity": "sha512-9xUSSj7qcUxz+0r4X3+bwUNttEfGfK5AH+LVa1aTpqdAfrN5VhROYCfcF+up4hp5OL7IUKcZJJrzAGipQRDoiQ==" + }, + "electron-to-chromium": { + "version": "1.3.314", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.314.tgz", + "integrity": "sha512-IKDR/xCxKFhPts7h+VaSXS02Z1mznP3fli1BbXWXeN89i2gCzKraU8qLpEid8YzKcmZdZD3Mly3cn5/lY9xsBQ==", + "dev": true + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz", + "integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-releases": { + "version": "1.1.41", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.41.tgz", + "integrity": "sha512-+IctMa7wIs8Cfsa8iYzeaLTFwv5Y4r5jZud+4AnfymzeEXKBCavFX0KBgzVaPVqf0ywa6PrO8/b+bPqdwjGBSg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-transform": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, + "regexpu-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", + "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.1.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "regjsgen": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", + "dev": true + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.1.tgz", + "integrity": "sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 03738e3e1..3e4a35345 100644 --- a/package.json +++ b/package.json @@ -2,63 +2,66 @@ "author": "Spencer Kelly (http://spencermounta.in)", "name": "compromise", "description": "natural language processing in the browser", - "version": "11.14.3", + "version": "12.0.0", "main": "./builds/compromise.js", "unpkg": "./builds/compromise.min.js", - "types": "types", + "module": "./builds/compromise.mjs", + "type": "commonjs", + "types": "types/index.d.ts", "repository": { "type": "git", - "url": "git://github.com/nlp-compromise/compromise.git" + "url": "git://github.com/spencermountain/compromise.git" }, "scripts": { - "test": "tape \"./test/unit/**/*.test.js\" | tap-dancer", - "test:spec": "tape \"./test/unit/**/*.test.js\" | tap-spec", - "testb": "TESTENV=prod tape \"./test/unit/**/*.test.js\" | tap-dancer", - "buildTest": "TESTENV=prod node ./scripts/test.js", - "test:types": "dtslint types", - "browserTest": "node ./scripts/browserTest.js", - "benchmark": "node ./scripts/benchmark.js", - "build": "node ./scripts/build/index.js", + "build": "npm run version && rollup -c && npm run filesize", + "build:all": "node ./scripts/buildAll.js && npm run build", "pack": "node ./scripts/pack.js", - "prepublishOnly": "node ./scripts/prepublish && npm run test:types", - "postpublish": "node ./scripts/postpublish", + "version": "node ./scripts/version.js", + "test": "node ./scripts/testAll.js", + "testb": "TESTENV=prod node ./scripts/testAll.js", + "testOne": "tape \"./tests/**/*.test.js\" | tap-dancer", + "test:spec": "tape \"./tests/**/*.test.js\" | tap-spec", + "filesize": "node ./scripts/filesize.js", "watch": "amble ./scratch.js", - "filesize": "node ./scripts/lib/filesize.js", - "coverage": "node ./scripts/postpublish/coverage.js", - "lint": "node ./scripts/prepublish/linter.js" + "stress": "node ./scripts/stress-test/stress.js", + "plugins": "node ./scripts/plugin-check.js", + "speed": "node ./scripts/stress-test/speed.js", + "demo": "python -m SimpleHTTPServer 8888", + "coverage": "nyc --reporter=html tape \"./tests/**/*.test.js\" | tap-dancer --color always", + "test:types": "ts-node ./types/types.test.ts | tap-dancer", + "lint": "eslint ./src/" }, "files": [ "builds/", - "docs/", "types/index.d.ts" ], "prettier": { - "trailingComma": "none", + "trailingComma": "es5", "tabWidth": 2, - "semi": true, + "semi": false, "singleQuote": true, - "printWidth": 100 + "printWidth": 120 }, "dependencies": { "efrt-unpack": "2.2.0" }, "devDependencies": { - "@babel/core": "7.5.5", - "@babel/preset-env": "7.5.5", + "@babel/core": "7.7.4", + "@babel/preset-env": "7.7.4", "amble": "0.0.7", - "babelify": "10.0.0", - "babili": "0.1.4", - "browserify": "16.5.0", - "chalk": "2.4.2", - "codecov": "3.5.0", - "compromise-plugin": "0.0.9", - "derequire": "2.0.6", - "dtslint": "0.9.3", - "nyc": "14.1.1", + "efrt": "2.2.1", + "rollup": "1.27.5", + "rollup-plugin-babel": "4.3.3", + "rollup-plugin-commonjs": "10.1.0", + "rollup-plugin-json": "4.0.0", + "rollup-plugin-node-resolve": "5.2.0", + "rollup-plugin-terser": "5.1.2", "shelljs": "0.8.3", "tap-dancer": "0.2.0", - "tape": "4.11.0", - "terser": "4.2.1" + "tape": "4.11.0" }, + "eslintIgnore": [ + "builds/*.js" + ], "license": "MIT" } diff --git a/plugins/adjectives/README.md b/plugins/adjectives/README.md new file mode 100644 index 000000000..4b815e6b4 --- /dev/null +++ b/plugins/adjectives/README.md @@ -0,0 +1,53 @@ +
+ + +
a plugin for compromise
+ + + + + + + + + + +
+
+ +
+ npm install compromise-adjectives +
+ +Some additional conjugation of adjectives + +```js +const nlp = require('compromise') +nlp.extend(require('compromise-adjectives')) + +let doc = nlp('quick') +doc.adjectives().json() +/* + [{ + text:'quick', + toNoun:'quickness', + toAdverb:'quickly' + toVerb:'quicken' + toComparative:'quicker' + toSuperlative:'quickest' + }] +*/ +``` + +- **[.adjectives()](https://observablehq.com/@spencermountain/compromise-adjectives)** - like `quick` + - **[.adjectives().json()](https://observablehq.com/@spencermountain/compromise-adjectives)** - overloaded output with adjective metadata + - **[.adjectives().conjugate()](https://observablehq.com/@spencermountain/compromise-adjectives)** - return all conjugated forms of this adjective + - **[.adjectives().toSuperlative()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickest` + - **[.adjectives().toComparative()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickest` + - **[.adjectives().toAdverb()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickly` + - **[.adjectives().toVerb()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quicken` + - **[.adjectives().toNoun()](https://observablehq.com/@spencermountain/compromise-adjectives)** - convert `quick` to `quickness` + +work-in-progress + +MIT diff --git a/plugins/adjectives/builds/compromise-adjectives.js b/plugins/adjectives/builds/compromise-adjectives.js new file mode 100644 index 000000000..7f4a50fc4 --- /dev/null +++ b/plugins/adjectives/builds/compromise-adjectives.js @@ -0,0 +1,404 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseAdjectives = factory()); +}(this, (function () { 'use strict'; + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + //turn 'quick' into 'quickly' + var not_matches = [/airs$/, /ll$/, /ee.$/, /ile$/, /y$/]; + var irregulars = { + bad: 'badly', + good: 'well', + icy: 'icily', + idle: 'idly', + male: 'manly', + "public": 'publicly', + simple: 'simply', + single: 'singly', + special: 'especially', + straight: 'straight', + vague: 'vaguely', + whole: 'wholly' + }; + var dontChange = ['best', 'early', 'hard', 'fast', 'wrong', 'well', 'late', 'latter', 'little', 'long', 'low'].reduce(function (h, c) { + h[c] = true; + return h; + }, {}); + var transforms = [{ + reg: /al$/i, + repl: 'ally' + }, { + reg: /ly$/i, + repl: 'ly' + }, { + reg: /(.{3})y$/i, + repl: '$1ily' + }, { + reg: /que$/i, + repl: 'quely' + }, { + reg: /ue$/i, + repl: 'uly' + }, { + reg: /ic$/i, + repl: 'ically' + }, { + reg: /ble$/i, + repl: 'bly' + }, { + reg: /l$/i, + repl: 'ly' + }]; + + var adj_to_adv = function adj_to_adv(str) { + if (irregulars.hasOwnProperty(str) === true) { + return irregulars[str]; + } + + if (dontChange.hasOwnProperty(str) === true) { + return str; + } + + for (var i = 0; i < not_matches.length; i++) { + if (not_matches[i].test(str) === true) { + return null; + } + } + + for (var _i = 0; _i < transforms.length; _i++) { + if (transforms[_i].reg.test(str) === true) { + return str.replace(transforms[_i].reg, transforms[_i].repl); + } + } + + return str + 'ly'; + }; + + var toAdverb = adj_to_adv; + + //convert 'cute' to 'cuteness' + var irregulars$1 = { + clean: 'cleanliness', + naivety: 'naivety', + hurt: 'hurt' + }; + var transforms$1 = [{ + reg: /y$/, + repl: 'iness' + }, { + reg: /le$/, + repl: 'ility' + }, { + reg: /ial$/, + repl: 'y' + }, { + reg: /al$/, + repl: 'ality' + }, { + reg: /ting$/, + repl: 'ting' + }, { + reg: /ring$/, + repl: 'ring' + }, { + reg: /bing$/, + repl: 'bingness' + }, { + reg: /sing$/, + repl: 'se' + }, { + reg: /ing$/, + repl: 'ment' + }, { + reg: /ess$/, + repl: 'essness' + }, { + reg: /ous$/, + repl: 'ousness' + }]; + + var to_noun = function to_noun(w) { + if (irregulars$1.hasOwnProperty(w)) { + return irregulars$1[w]; + } + + var lastChar = w.charAt(w.length - 1); + + if (lastChar === 'w' || lastChar === 's') { + return null; + } + + for (var i = 0; i < transforms$1.length; i++) { + if (transforms$1[i].reg.test(w) === true) { + return w.replace(transforms$1[i].reg, transforms$1[i].repl); + } + } + + return w + 'ness'; + }; + + var toNoun = to_noun; + + //turn an adjective like 'soft' into a verb like 'soften' + //(don't do words like 'green' -> 'greenen') + //these are suffices that are usually too weird + var dontDo = ['c', 'e', 'g', 'l', 'n', 'r', 'w', 'y'].reduce(function (h, c) { + h[c] = true; + return h; + }, {}); + var dontDoTwo = { + ed: true, + nt: true + }; + var blacklist = { + random: true, + wild: true + }; + var irregulars$2 = { + bored: 'bore', + red: 'redden', + sad: 'sadden', + fat: 'fatten', + small: 'shrink', + full: 'fill', + tired: 'tire' + }; + + var toVerb = function toVerb(str) { + if (irregulars$2.hasOwnProperty(str) === true) { + return irregulars$2[str]; + } //don't bother with these: + + + if (str.length <= 3) { + return null; + } + + if (blacklist.hasOwnProperty(str) === true) { + return null; + } //suffixes to avoid + + + if (dontDo.hasOwnProperty(str[str.length - 1])) { + return null; + } + + var suffix = str.substr(str.length - 2); + + if (dontDoTwo.hasOwnProperty(suffix) === true) { + return null; + } + + if (/e$/.test(str) === true) { + return str + 'n'; + } + + return str + 'en'; + }; + + var toVerb_1 = toVerb; + + var addMethods = function addMethods(Doc) { + /** */ + var Adjective = + /*#__PURE__*/ + function (_Doc) { + _inherits(Adjective, _Doc); + + function Adjective() { + _classCallCheck(this, Adjective); + + return _possibleConstructorReturn(this, _getPrototypeOf(Adjective).apply(this, arguments)); + } + + _createClass(Adjective, [{ + key: "json", + + /** overload the original json with noun information */ + value: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var str = doc.text('reduced'); + json.toAdverb = toAdverb(str); + json.toNoun = toNoun(str); + json.toVerb = toVerb_1(str); + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + } + }, { + key: "conjugate", + value: function conjugate(n) { + var transform = this.world.transforms.adjectives; + var arr = []; + this.forEach(function (doc) { + var str = doc.text('reduced'); + var obj = transform(str); + obj.Adverb = toAdverb(str); + obj.Noun = toNoun(str); + obj.Verb = toVerb_1(str); + arr.push(obj); + }); //support nth result + + if (typeof n === 'number') { + return arr[n]; + } + + return arr; + } + }, { + key: "toSuperlative", + value: function toSuperlative() { + var transform = this.world.transforms.adjectives; + this.forEach(function (doc) { + var obj = transform(doc.text('reduced')); + doc.replaceWith(obj.Superlative, true, true); + }); + return this; + } + }, { + key: "toComparative", + value: function toComparative() { + var transform = this.world.transforms.adjectives; + this.forEach(function (doc) { + var obj = transform(doc.text('reduced')); + doc.replaceWith(obj.Comparative, true, true); + }); + return this; + } + }, { + key: "toAdverb", + value: function toAdverb$1() { + this.forEach(function (doc) { + var adverb = toAdverb(doc.text('reduced')); + + doc.replaceWith(adverb, true, true); + }); + return this; + } + }, { + key: "toVerb", + value: function toVerb() { + this.forEach(function (doc) { + var verb = toVerb_1(doc.text('reduced')); + + doc.replaceWith(verb, true, true); + }); + return this; + } + }, { + key: "toNoun", + value: function toNoun$1() { + this.forEach(function (doc) { + var noun = toNoun(doc.text('reduced')); + + doc.replaceWith(noun, true, true); + }); + return this; + } + }]); + + return Adjective; + }(Doc); + /** grab all the adjectives */ + + + Doc.prototype.adjectives = function (n) { + var m = this.match('#Adjective'); //grab (n)th result + + if (typeof n === 'number') { + m = m.get(n); + } + + return new Adjective(m.list, this, this.world); + }; + }; + + var src = addMethods; + + return src; + +}))); +//# sourceMappingURL=compromise-adjectives.js.map diff --git a/plugins/adjectives/builds/compromise-adjectives.js.map b/plugins/adjectives/builds/compromise-adjectives.js.map new file mode 100644 index 000000000..86e3bfe96 --- /dev/null +++ b/plugins/adjectives/builds/compromise-adjectives.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-adjectives.js","sources":["../src/toAdverb.js","../src/toNoun.js","../src/toVerb.js","../src/index.js"],"sourcesContent":["//turn 'quick' into 'quickly'\nconst not_matches = [/airs$/, /ll$/, /ee.$/, /ile$/, /y$/]\n\nconst irregulars = {\n bad: 'badly',\n good: 'well',\n icy: 'icily',\n idle: 'idly',\n male: 'manly',\n public: 'publicly',\n simple: 'simply',\n single: 'singly',\n special: 'especially',\n straight: 'straight',\n vague: 'vaguely',\n whole: 'wholly',\n}\nconst dontChange = ['best', 'early', 'hard', 'fast', 'wrong', 'well', 'late', 'latter', 'little', 'long', 'low'].reduce(\n (h, c) => {\n h[c] = true\n return h\n },\n {}\n)\n\nconst transforms = [\n {\n reg: /al$/i,\n repl: 'ally',\n },\n {\n reg: /ly$/i,\n repl: 'ly',\n },\n {\n reg: /(.{3})y$/i,\n repl: '$1ily',\n },\n {\n reg: /que$/i,\n repl: 'quely',\n },\n {\n reg: /ue$/i,\n repl: 'uly',\n },\n {\n reg: /ic$/i,\n repl: 'ically',\n },\n {\n reg: /ble$/i,\n repl: 'bly',\n },\n {\n reg: /l$/i,\n repl: 'ly',\n },\n]\n\nconst adj_to_adv = function(str) {\n if (irregulars.hasOwnProperty(str) === true) {\n return irregulars[str]\n }\n if (dontChange.hasOwnProperty(str) === true) {\n return str\n }\n for (let i = 0; i < not_matches.length; i++) {\n if (not_matches[i].test(str) === true) {\n return null\n }\n }\n for (let i = 0; i < transforms.length; i++) {\n if (transforms[i].reg.test(str) === true) {\n return str.replace(transforms[i].reg, transforms[i].repl)\n }\n }\n return str + 'ly'\n}\n\nmodule.exports = adj_to_adv\n","//convert 'cute' to 'cuteness'\nconst irregulars = {\n clean: 'cleanliness',\n naivety: 'naivety',\n hurt: 'hurt',\n}\n\nconst transforms = [\n {\n reg: /y$/,\n repl: 'iness',\n },\n {\n reg: /le$/,\n repl: 'ility',\n },\n {\n reg: /ial$/,\n repl: 'y',\n },\n {\n reg: /al$/,\n repl: 'ality',\n },\n {\n reg: /ting$/,\n repl: 'ting',\n },\n {\n reg: /ring$/,\n repl: 'ring',\n },\n {\n reg: /bing$/,\n repl: 'bingness',\n },\n {\n reg: /sing$/,\n repl: 'se',\n },\n {\n reg: /ing$/,\n repl: 'ment',\n },\n {\n reg: /ess$/,\n repl: 'essness',\n },\n {\n reg: /ous$/,\n repl: 'ousness',\n },\n]\n\nconst to_noun = function(w) {\n if (irregulars.hasOwnProperty(w)) {\n return irregulars[w]\n }\n const lastChar = w.charAt(w.length - 1)\n if (lastChar === 'w' || lastChar === 's') {\n return null\n }\n for (let i = 0; i < transforms.length; i++) {\n if (transforms[i].reg.test(w) === true) {\n return w.replace(transforms[i].reg, transforms[i].repl)\n }\n }\n return w + 'ness'\n}\n\nmodule.exports = to_noun\n","//turn an adjective like 'soft' into a verb like 'soften'\n//(don't do words like 'green' -> 'greenen')\n\n//these are suffices that are usually too weird\nlet dontDo = ['c', 'e', 'g', 'l', 'n', 'r', 'w', 'y'].reduce((h, c) => {\n h[c] = true\n return h\n}, {})\n\nconst dontDoTwo = { ed: true, nt: true }\n\nconst blacklist = {\n random: true,\n wild: true,\n}\n\nconst irregulars = {\n bored: 'bore',\n red: 'redden',\n sad: 'sadden',\n fat: 'fatten',\n small: 'shrink',\n full: 'fill',\n tired: 'tire',\n}\n\nconst toVerb = str => {\n if (irregulars.hasOwnProperty(str) === true) {\n return irregulars[str]\n }\n //don't bother with these:\n if (str.length <= 3) {\n return null\n }\n if (blacklist.hasOwnProperty(str) === true) {\n return null\n }\n //suffixes to avoid\n if (dontDo.hasOwnProperty(str[str.length - 1])) {\n return null\n }\n let suffix = str.substr(str.length - 2)\n if (dontDoTwo.hasOwnProperty(suffix) === true) {\n return null\n }\n\n if (/e$/.test(str) === true) {\n return str + 'n'\n }\n return str + 'en'\n}\nmodule.exports = toVerb\n","const toAdverb = require('./toAdverb')\nconst toNoun = require('./toNoun')\nconst toVerb = require('./toVerb')\n\nconst addMethods = function(Doc) {\n /** */\n class Adjective extends Doc {\n /** overload the original json with noun information */\n json(options) {\n let n = null\n if (typeof options === 'number') {\n n = options\n options = null\n }\n let res = []\n this.forEach(doc => {\n let json = doc.json(options)[0]\n let str = doc.text('reduced')\n json.toAdverb = toAdverb(str)\n json.toNoun = toNoun(str)\n json.toVerb = toVerb(str)\n res.push(json)\n })\n if (n !== null) {\n return res[n]\n }\n return res\n }\n conjugate(n) {\n let transform = this.world.transforms.adjectives\n let arr = []\n this.forEach(doc => {\n let str = doc.text('reduced')\n let obj = transform(str)\n obj.Adverb = toAdverb(str)\n obj.Noun = toNoun(str)\n obj.Verb = toVerb(str)\n arr.push(obj)\n })\n //support nth result\n if (typeof n === 'number') {\n return arr[n]\n }\n return arr\n }\n\n toSuperlative() {\n let transform = this.world.transforms.adjectives\n this.forEach(doc => {\n let obj = transform(doc.text('reduced'))\n doc.replaceWith(obj.Superlative, true, true)\n })\n return this\n }\n toComparative() {\n let transform = this.world.transforms.adjectives\n this.forEach(doc => {\n let obj = transform(doc.text('reduced'))\n doc.replaceWith(obj.Comparative, true, true)\n })\n return this\n }\n toAdverb() {\n this.forEach(doc => {\n let adverb = toAdverb(doc.text('reduced'))\n doc.replaceWith(adverb, true, true)\n })\n return this\n }\n toVerb() {\n this.forEach(doc => {\n let verb = toVerb(doc.text('reduced'))\n doc.replaceWith(verb, true, true)\n })\n return this\n }\n toNoun() {\n this.forEach(doc => {\n let noun = toNoun(doc.text('reduced'))\n doc.replaceWith(noun, true, true)\n })\n return this\n }\n }\n\n /** grab all the adjectives */\n Doc.prototype.adjectives = function(n) {\n let m = this.match('#Adjective')\n //grab (n)th result\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return new Adjective(m.list, this, this.world)\n }\n}\nmodule.exports = addMethods\n"],"names":["not_matches","irregulars","bad","good","icy","idle","male","simple","single","special","straight","vague","whole","dontChange","reduce","h","c","transforms","reg","repl","adj_to_adv","str","hasOwnProperty","i","length","test","replace","clean","naivety","hurt","to_noun","w","lastChar","charAt","dontDo","dontDoTwo","ed","nt","blacklist","random","wild","bored","red","sad","fat","small","full","tired","toVerb","suffix","substr","addMethods","Doc","Adjective","options","n","res","forEach","doc","json","text","toAdverb","toNoun","push","transform","world","adjectives","arr","obj","Adverb","Noun","Verb","replaceWith","Superlative","Comparative","adverb","verb","noun","prototype","m","match","get","list"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/adjectives/builds/compromise-adjectives.min.js b/plugins/adjectives/builds/compromise-adjectives.min.js new file mode 100644 index 000000000..da6b9b33f --- /dev/null +++ b/plugins/adjectives/builds/compromise-adjectives.min.js @@ -0,0 +1 @@ +!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e=e||self).compromiseAdjectives=r()}(this,(function(){"use strict";function e(e,r){for(var t=0;t 'greenen') +//these are suffices that are usually too weird +var dontDo = ['c', 'e', 'g', 'l', 'n', 'r', 'w', 'y'].reduce(function (h, c) { + h[c] = true; + return h; +}, {}); +var dontDoTwo = { + ed: true, + nt: true +}; +var blacklist = { + random: true, + wild: true +}; +var irregulars$2 = { + bored: 'bore', + red: 'redden', + sad: 'sadden', + fat: 'fatten', + small: 'shrink', + full: 'fill', + tired: 'tire' +}; + +var toVerb = function toVerb(str) { + if (irregulars$2.hasOwnProperty(str) === true) { + return irregulars$2[str]; + } //don't bother with these: + + + if (str.length <= 3) { + return null; + } + + if (blacklist.hasOwnProperty(str) === true) { + return null; + } //suffixes to avoid + + + if (dontDo.hasOwnProperty(str[str.length - 1])) { + return null; + } + + var suffix = str.substr(str.length - 2); + + if (dontDoTwo.hasOwnProperty(suffix) === true) { + return null; + } + + if (/e$/.test(str) === true) { + return str + 'n'; + } + + return str + 'en'; +}; + +var toVerb_1 = toVerb; + +var addMethods = function addMethods(Doc) { + /** */ + var Adjective = + /*#__PURE__*/ + function (_Doc) { + _inherits(Adjective, _Doc); + + function Adjective() { + _classCallCheck(this, Adjective); + + return _possibleConstructorReturn(this, _getPrototypeOf(Adjective).apply(this, arguments)); + } + + _createClass(Adjective, [{ + key: "json", + + /** overload the original json with noun information */ + value: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var str = doc.text('reduced'); + json.toAdverb = toAdverb(str); + json.toNoun = toNoun(str); + json.toVerb = toVerb_1(str); + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + } + }, { + key: "conjugate", + value: function conjugate(n) { + var transform = this.world.transforms.adjectives; + var arr = []; + this.forEach(function (doc) { + var str = doc.text('reduced'); + var obj = transform(str); + obj.Adverb = toAdverb(str); + obj.Noun = toNoun(str); + obj.Verb = toVerb_1(str); + arr.push(obj); + }); //support nth result + + if (typeof n === 'number') { + return arr[n]; + } + + return arr; + } + }, { + key: "toSuperlative", + value: function toSuperlative() { + var transform = this.world.transforms.adjectives; + this.forEach(function (doc) { + var obj = transform(doc.text('reduced')); + doc.replaceWith(obj.Superlative, true, true); + }); + return this; + } + }, { + key: "toComparative", + value: function toComparative() { + var transform = this.world.transforms.adjectives; + this.forEach(function (doc) { + var obj = transform(doc.text('reduced')); + doc.replaceWith(obj.Comparative, true, true); + }); + return this; + } + }, { + key: "toAdverb", + value: function toAdverb$1() { + this.forEach(function (doc) { + var adverb = toAdverb(doc.text('reduced')); + + doc.replaceWith(adverb, true, true); + }); + return this; + } + }, { + key: "toVerb", + value: function toVerb() { + this.forEach(function (doc) { + var verb = toVerb_1(doc.text('reduced')); + + doc.replaceWith(verb, true, true); + }); + return this; + } + }, { + key: "toNoun", + value: function toNoun$1() { + this.forEach(function (doc) { + var noun = toNoun(doc.text('reduced')); + + doc.replaceWith(noun, true, true); + }); + return this; + } + }]); + + return Adjective; + }(Doc); + /** grab all the adjectives */ + + + Doc.prototype.adjectives = function (n) { + var m = this.match('#Adjective'); //grab (n)th result + + if (typeof n === 'number') { + m = m.get(n); + } + + return new Adjective(m.list, this, this.world); + }; +}; + +var src = addMethods; + +export default src; diff --git a/plugins/adjectives/package-lock.json b/plugins/adjectives/package-lock.json new file mode 100644 index 000000000..196cafb08 --- /dev/null +++ b/plugins/adjectives/package-lock.json @@ -0,0 +1,774 @@ +{ + "name": "compromise-adjectives", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz", + "integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", + "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz", + "integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "htm": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/htm/-/htm-2.2.1.tgz", + "integrity": "sha512-nPWqBlSbdSHaT2d/cpFRpZLqH5BcdaRcXaicyAtXbkIsIiXLnstPPg0fEX3I8SrlY16FSzb1FLK44uk25xhMvw==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", + "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "magic-string": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz", + "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "pure-md5": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/pure-md5/-/pure-md5-0.1.9.tgz", + "integrity": "sha512-SA/xeqGm/WSx9sup7801Xl8cs2mi5IB6UTCOapWcHc7IeAlMn4k3JBO9aLH+88+JrqqUANhVwX1+Tz3dlvRI+A==" + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.8.tgz", + "integrity": "sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vhtml": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vhtml/-/vhtml-2.1.0.tgz", + "integrity": "sha1-qFjtLjKMWVOZphroig4A+3Vr4Bw=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/plugins/adjectives/package.json b/plugins/adjectives/package.json new file mode 100644 index 000000000..50f293ebb --- /dev/null +++ b/plugins/adjectives/package.json @@ -0,0 +1,51 @@ +{ + "name": "compromise-adjectives", + "description": "smart-replace plugin for nlp-compromise", + "version": "0.0.2", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-adjectives.js", + "unpkg": "./builds/compromise-adjectives.min.js", + "module": "./builds/compromise-adjectives.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*" + }, + "dependencies": { + "htm": "^2.2.1", + "pure-md5": "^0.1.9", + "vhtml": "^2.1.0" + }, + "devDependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/plugins/adjectives/rollup.config.js b/plugins/adjectives/rollup.config.js new file mode 100644 index 000000000..20c307dd2 --- /dev/null +++ b/plugins/adjectives/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-adjectives' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseAdjectives', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseAdjectives', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/adjectives/src/index.js b/plugins/adjectives/src/index.js new file mode 100644 index 000000000..5349fb72b --- /dev/null +++ b/plugins/adjectives/src/index.js @@ -0,0 +1,96 @@ +const toAdverb = require('./toAdverb') +const toNoun = require('./toNoun') +const toVerb = require('./toVerb') + +const addMethods = function(Doc) { + /** */ + class Adjective extends Doc { + /** overload the original json with noun information */ + json(options) { + let n = null + if (typeof options === 'number') { + n = options + options = null + } + let res = [] + this.forEach(doc => { + let json = doc.json(options)[0] + let str = doc.text('reduced') + json.toAdverb = toAdverb(str) + json.toNoun = toNoun(str) + json.toVerb = toVerb(str) + res.push(json) + }) + if (n !== null) { + return res[n] + } + return res + } + conjugate(n) { + let transform = this.world.transforms.adjectives + let arr = [] + this.forEach(doc => { + let str = doc.text('reduced') + let obj = transform(str) + obj.Adverb = toAdverb(str) + obj.Noun = toNoun(str) + obj.Verb = toVerb(str) + arr.push(obj) + }) + //support nth result + if (typeof n === 'number') { + return arr[n] + } + return arr + } + + toSuperlative() { + let transform = this.world.transforms.adjectives + this.forEach(doc => { + let obj = transform(doc.text('reduced')) + doc.replaceWith(obj.Superlative, true, true) + }) + return this + } + toComparative() { + let transform = this.world.transforms.adjectives + this.forEach(doc => { + let obj = transform(doc.text('reduced')) + doc.replaceWith(obj.Comparative, true, true) + }) + return this + } + toAdverb() { + this.forEach(doc => { + let adverb = toAdverb(doc.text('reduced')) + doc.replaceWith(adverb, true, true) + }) + return this + } + toVerb() { + this.forEach(doc => { + let verb = toVerb(doc.text('reduced')) + doc.replaceWith(verb, true, true) + }) + return this + } + toNoun() { + this.forEach(doc => { + let noun = toNoun(doc.text('reduced')) + doc.replaceWith(noun, true, true) + }) + return this + } + } + + /** grab all the adjectives */ + Doc.prototype.adjectives = function(n) { + let m = this.match('#Adjective') + //grab (n)th result + if (typeof n === 'number') { + m = m.get(n) + } + return new Adjective(m.list, this, this.world) + } +} +module.exports = addMethods diff --git a/plugins/adjectives/src/toAdverb.js b/plugins/adjectives/src/toAdverb.js new file mode 100644 index 000000000..d38428e60 --- /dev/null +++ b/plugins/adjectives/src/toAdverb.js @@ -0,0 +1,81 @@ +//turn 'quick' into 'quickly' +const not_matches = [/airs$/, /ll$/, /ee.$/, /ile$/, /y$/] + +const irregulars = { + bad: 'badly', + good: 'well', + icy: 'icily', + idle: 'idly', + male: 'manly', + public: 'publicly', + simple: 'simply', + single: 'singly', + special: 'especially', + straight: 'straight', + vague: 'vaguely', + whole: 'wholly', +} +const dontChange = ['best', 'early', 'hard', 'fast', 'wrong', 'well', 'late', 'latter', 'little', 'long', 'low'].reduce( + (h, c) => { + h[c] = true + return h + }, + {} +) + +const transforms = [ + { + reg: /al$/i, + repl: 'ally', + }, + { + reg: /ly$/i, + repl: 'ly', + }, + { + reg: /(.{3})y$/i, + repl: '$1ily', + }, + { + reg: /que$/i, + repl: 'quely', + }, + { + reg: /ue$/i, + repl: 'uly', + }, + { + reg: /ic$/i, + repl: 'ically', + }, + { + reg: /ble$/i, + repl: 'bly', + }, + { + reg: /l$/i, + repl: 'ly', + }, +] + +const adj_to_adv = function(str) { + if (irregulars.hasOwnProperty(str) === true) { + return irregulars[str] + } + if (dontChange.hasOwnProperty(str) === true) { + return str + } + for (let i = 0; i < not_matches.length; i++) { + if (not_matches[i].test(str) === true) { + return null + } + } + for (let i = 0; i < transforms.length; i++) { + if (transforms[i].reg.test(str) === true) { + return str.replace(transforms[i].reg, transforms[i].repl) + } + } + return str + 'ly' +} + +module.exports = adj_to_adv diff --git a/plugins/adjectives/src/toNoun.js b/plugins/adjectives/src/toNoun.js new file mode 100644 index 000000000..4dcf08dff --- /dev/null +++ b/plugins/adjectives/src/toNoun.js @@ -0,0 +1,71 @@ +//convert 'cute' to 'cuteness' +const irregulars = { + clean: 'cleanliness', + naivety: 'naivety', + hurt: 'hurt', +} + +const transforms = [ + { + reg: /y$/, + repl: 'iness', + }, + { + reg: /le$/, + repl: 'ility', + }, + { + reg: /ial$/, + repl: 'y', + }, + { + reg: /al$/, + repl: 'ality', + }, + { + reg: /ting$/, + repl: 'ting', + }, + { + reg: /ring$/, + repl: 'ring', + }, + { + reg: /bing$/, + repl: 'bingness', + }, + { + reg: /sing$/, + repl: 'se', + }, + { + reg: /ing$/, + repl: 'ment', + }, + { + reg: /ess$/, + repl: 'essness', + }, + { + reg: /ous$/, + repl: 'ousness', + }, +] + +const to_noun = function(w) { + if (irregulars.hasOwnProperty(w)) { + return irregulars[w] + } + const lastChar = w.charAt(w.length - 1) + if (lastChar === 'w' || lastChar === 's') { + return null + } + for (let i = 0; i < transforms.length; i++) { + if (transforms[i].reg.test(w) === true) { + return w.replace(transforms[i].reg, transforms[i].repl) + } + } + return w + 'ness' +} + +module.exports = to_noun diff --git a/plugins/adjectives/src/toVerb.js b/plugins/adjectives/src/toVerb.js new file mode 100644 index 000000000..eb78688cb --- /dev/null +++ b/plugins/adjectives/src/toVerb.js @@ -0,0 +1,52 @@ +//turn an adjective like 'soft' into a verb like 'soften' +//(don't do words like 'green' -> 'greenen') + +//these are suffices that are usually too weird +let dontDo = ['c', 'e', 'g', 'l', 'n', 'r', 'w', 'y'].reduce((h, c) => { + h[c] = true + return h +}, {}) + +const dontDoTwo = { ed: true, nt: true } + +const blacklist = { + random: true, + wild: true, +} + +const irregulars = { + bored: 'bore', + red: 'redden', + sad: 'sadden', + fat: 'fatten', + small: 'shrink', + full: 'fill', + tired: 'tire', +} + +const toVerb = str => { + if (irregulars.hasOwnProperty(str) === true) { + return irregulars[str] + } + //don't bother with these: + if (str.length <= 3) { + return null + } + if (blacklist.hasOwnProperty(str) === true) { + return null + } + //suffixes to avoid + if (dontDo.hasOwnProperty(str[str.length - 1])) { + return null + } + let suffix = str.substr(str.length - 2) + if (dontDoTwo.hasOwnProperty(suffix) === true) { + return null + } + + if (/e$/.test(str) === true) { + return str + 'n' + } + return str + 'en' +} +module.exports = toVerb diff --git a/plugins/adjectives/tests/_lib.js b/plugins/adjectives/tests/_lib.js new file mode 100644 index 000000000..254633449 --- /dev/null +++ b/plugins/adjectives/tests/_lib.js @@ -0,0 +1,12 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + } + + module.exports = nlp +} diff --git a/plugins/adjectives/tests/adjective.test.js b/plugins/adjectives/tests/adjective.test.js new file mode 100644 index 000000000..0b5508af7 --- /dev/null +++ b/plugins/adjectives/tests/adjective.test.js @@ -0,0 +1,90 @@ +const test = require('tape') +const nlp = require('./_lib') + +// const doc = nlp('quick').adjectives() +test('to_adverb:', function(t) { + const list = [ + ['quick', 'quickly'], + // ['idle', 'idly'], + ['dirty', ''], + // ['fun', ''], + ['full', ''], + // ['quixotic', 'quixotically'], + ['cute', 'cutely'], + // ['good', 'well'], + // ['low', 'low'] + ] + list.forEach(function(a) { + const doc = nlp(a[0]) + .adjectives() + .toAdverb() + t.equal(doc.text(), a[1], a[0]) + }) + t.end() +}) + +test(' to_superlative', function(t) { + let list = [ + ['quick', 'quickest'], + ['friendly', 'friendliest'], + // ['caring', 'most caring'], + // ['fun', 'most fun'], + ['full', 'fullest'], + // ['quixotic', 'most quixotic'], + ['cute', 'cutest'], + ['large', 'largest'], + ] + list.forEach(function(a) { + const doc = nlp(a[0]) + .adjectives() + .toSuperlative() + t.equal(doc.text(), a[1], a[0]) + }) + t.end() +}) +// +test(' to_comparative', function(t) { + let list = [ + ['quick', 'quicker'], + ['friendly', 'friendlier'], + // ['caring', 'more caring'], + // ['fun', 'more fun'], + ['full', 'fuller'], + // ['quixotic', 'more quixotic'], + ['cute', 'cuter'], + ] + list.forEach(function(a) { + const doc = nlp(a[0]) + .adjectives() + .toComparative() + t.equal(doc.text(), a[1], a[0]) + }) + t.end() +}) + +test(' to_noun', function(t) { + let list = [ + ['quick', 'quickness'], + ['fancy', 'fanciness'], + // ['ferocious', 'ferociousness'], + ['clean', 'cleanliness'], + ] + list.forEach(function(a) { + const doc = nlp(a[0]) + .adjectives() + .toNoun() + t.equal(doc.text(), a[1], a[0]) + }) + t.end() +}) + +test(' conjugate', function(t) { + const o = nlp('nice') + .adjectives() + .conjugate(0) + t.equal(o.Comparative, 'nicer', 'comparative') + t.equal(o.Superlative, 'nicest', 'superlative') + t.equal(o.Adverb, 'nicely', 'adverb') + t.equal(o.Noun, 'niceness', 'noun') + t.end() +}) diff --git a/plugins/dates/README.md b/plugins/dates/README.md new file mode 100644 index 000000000..c2a31f773 --- /dev/null +++ b/plugins/dates/README.md @@ -0,0 +1,47 @@ +
+ + +
date-parsing plugin for compromise
+ + + + + + + + + + +
+
+ +
+ npm install compromise-dates +
+`compromise-date` also depends on [compromise-numbers](../numbers) +
+ npm install compromise-numbers +
+ +```js +const nlp = require('compromise') +nlp.extend(require('compromise-dates')) +nlp.extend(require('compromise-numbers')) + +let doc = nlp('my birthday is June 5th 1998') +doc.dates().json() +/*[{ + text: 'June 5th 1998', + date: { start: '1998-06-05T00:00:00.000-04:00', end: null } +}]*/ +``` + +### API + +- **.dates()** - find dates like `June 8th` or `03/03/18` + - **.dates().json()** - overloaded output with date metadata + - **.dates().format('')** - convert the dates to specific formats + +Work in progress. + +MIT diff --git a/plugins/dates/builds/compromise-dates.js b/plugins/dates/builds/compromise-dates.js new file mode 100644 index 000000000..626cccedb --- /dev/null +++ b/plugins/dates/builds/compromise-dates.js @@ -0,0 +1,5757 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseDates = factory()); +}(this, (function () { 'use strict'; + + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + //ambiguous 'may' and 'march' + var preps = '(in|by|before|during|on|until|after|of|within|all)'; //6 + + var thisNext = '(last|next|this|previous|current|upcoming|coming)'; //2 + + var sections = '(start|end|middle|starting|ending|midpoint|beginning)'; //2 + + var seasons = '(spring|summer|winter|fall|autumn)'; //ensure a year is approximately typical for common years + //please change in one thousand years + + var tagYear = function tagYear(m, reason) { + if (m.found !== true) { + return; + } + + var term = m.termList()[0]; + + if (term) { + var num = parseInt(term.clean, 10); + + if (num && num > 1000 && num < 3000) { + m.tag('Year', reason); + } + } + }; //same, but for less-confident values + + + var tagYearSafe = function tagYearSafe(m, reason) { + if (m.found !== true) { + return; + } + + var term = m.termList()[0]; + + if (term) { + var num = parseInt(term.clean, 10); + + if (num && num > 1900 && num < 2030) { + m.tag('Year', reason); + } + } + }; + + var fixDates = function fixDates(doc) { + doc.match('in the (night|evening|morning|afternoon|day|daytime)').tag('Time', 'in-the-night'); + doc.match('(#Value|#Time) (am|pm)').tag('Time', 'value-ampm'); //months: + + var month = doc["if"]('#Month'); + + if (month.found === true) { + //June 5-7th + month.match("#Month #DateRange+").tag('Date', 'correction-numberRange'); //5th of March + + month.match('#Value of #Month').tag('Date', 'value-of-month'); //5 March + + month.match('#Cardinal #Month').tag('Date', 'cardinal-month'); //march 5 to 7 + + month.match('#Month #Value to #Value').tag('Date', 'value-to-value'); //march the 12th + + month.match('#Month the #Value').tag('Date', 'month-the-value'); + } //months: + + + var val = doc["if"]('#Value'); + + if (val.found === true) { + //june 7 + val.match('(#WeekDay|#Month) #Value').ifNo('#Money').tag('Date', 'date-value'); //7 june + + val.match('#Value (#WeekDay|#Month)').ifNo('#Money').tag('Date', 'value-date'); //may twenty five + + val.match('#TextValue #TextValue')["if"]('#Date').tag('#Date', 'textvalue-date'); //eg 'year' + + var duration = val["if"]('#Duration'); + + if (duration.found === true) { + //for 4 months + duration.match('for #Value #Duration').tag('Date', 'for-x-duration'); //two days before + + duration.match('#Value #Duration #Conjunction').tag('Date', 'val-duration-conjunction'); //for four days + + duration.match("".concat(preps, "? #Value #Duration")).tag('Date', 'value-duration'); //two years old + + duration.match('#Value #Duration old').unTag('Date', 'val-years-old'); + } + } //seasons + + + var season = doc["if"](seasons); + + if (season.found === true) { + season.match("".concat(preps, "? ").concat(thisNext, " ").concat(seasons)).tag('Date', 'thisNext-season'); + season.match("the? ".concat(sections, " of ").concat(seasons)).tag('Date', 'section-season'); + season.match("".concat(seasons, " ").concat(preps, "? #Cardinal")).tag('Date', 'season-year'); + } //rest-dates + + + var date = doc["if"]('#Date'); + + if (date.found === true) { + //june the 5th + date.match('#Date the? #Ordinal').tag('Date', 'correction'); //last month + + date.match("".concat(thisNext, " #Date")).tag('Date', 'thisNext'); //by 5 March + + date.match('due? (by|before|after|until) #Date').tag('Date', 'by'); //next feb + + date.match('(last|next|this|previous|current|upcoming|coming|the) #Date').tag('Date', 'next-feb'); //start of june + + date.match("the? ".concat(sections, " of #Date")).tag('Date', 'section-of'); //fifth week in 1998 + + date.match('#Ordinal #Duration in #Date').tag('Date', 'duration-in'); //early in june + + date.match('(early|late) (at|in)? the? #Date').tag('Time', 'early-evening'); //tomorrow before 3 + + date.match('#Date (by|before|after|at|@|about) #Cardinal').not('^#Date').tag('Time', 'date-before-Cardinal'); //saturday am + + date.match('#Date [(am|pm)]').unTag('Verb').unTag('Copula').tag('Time', 'date-am'); //feb to june + + date.match('#Date (#Preposition|to) #Date').ifNo('#Duration').tag('Date', 'date-prep-date'); + } //year/cardinal tagging + + + var cardinal = doc["if"]('#Cardinal'); + + if (cardinal.found === true) { + var v = cardinal.match("#Date #Value [#Cardinal]"); + tagYear(v, 'date-value-year'); //scoops up a bunch + + v = cardinal.match("#Date+ [#Cardinal]"); + tagYear(v, 'date-year'); //feb 8 2018 + + v = cardinal.match("#Month #Value [#Cardinal]"); + tagYear(v, 'month-value-year'); //feb 8 to 10th 2018 + + v = cardinal.match("#Month #Value to #Value [#Cardinal]"); + tagYear(v, 'month-range-year'); //in 1998 + + v = cardinal.match("(in|of|by|during|before|starting|ending|for|year) [#Cardinal]"); + tagYear(v, 'in-year'); //q2 2009 + + v = cardinal.match('(q1|q2|q3|q4) [#Cardinal]'); + tagYear(v, 'in-year'); //2nd quarter 2009 + + v = cardinal.match('#Ordinal quarter [#Cardinal]'); + tagYear(v, 'in-year'); //in the year 1998 + + v = cardinal.match('the year [#Cardinal]'); + tagYear(v, 'in-year'); //it was 1998 + + v = cardinal.match('it (is|was) [#Cardinal]'); + tagYearSafe(v, 'in-year'); + } + + var time = doc["if"]('#Time'); + + if (time.found === true) { + //by 6pm + time.match('(by|before|after|at|@|about) #Time').tag('Time', 'preposition-time'); //7 7pm + + time.match('#Cardinal #Time').not('#Year').tag('Time', 'value-time'); //2pm est + + time.match('#Time [(eastern|pacific|central|mountain)]').tag('Time', 'timezone'); //6pm est + + time.match('#Time [(est|pst|gmt)]').tag('Time', 'timezone abbr'); + } + + return doc; + }; + + var _00Basic = fixDates; + + var here = 'date-values'; // + + var values = function values(doc) { + if (doc.has('#Value')) { + //june 5 to 7th + doc.match('#Month #Value to #Value of? #Year?').tag('Date', here); //5 to 7th june + + doc.match('#Value to #Value of? #Month #Year?').tag('Date', here); //third week of may + + doc.match('#Value #Duration of #Date').tag('Date', here); //two days after + + doc.match('#Value+ #Duration (after|before|into|later|afterwards|ago)?').tag('Date', here); //two days + + doc.match('#Value #Date').tag('Date', here); //june 5th + + doc.match('#Date #Value').tag('Date', here); //tuesday at 5 + + doc.match('#Date #Preposition #Value').tag('Date', here); //tomorrow before 3 + + doc.match('#Date (after|before|during|on|in) #Value').tag('Date', here); //a year and a half + + doc.match('#Value (year|month|week|day) and a half').tag('Date', here); //5 and a half years + + doc.match('#Value and a half (years|months|weeks|days)').tag('Date', here); //on the fifth + + doc.match('on the #Ordinal').tag('Date', here); + } + + return doc; + }; + + var _01Values = values; + + var here$1 = 'date-tagger'; // + + var dateTagger = function dateTagger(doc) { + doc.match('(spring|summer|winter|fall|autumn|springtime|wintertime|summertime)').match('#Noun').tag('Season', here$1); + doc.match('(q1|q2|q3|q4)').tag('FinancialQuarter', here$1); + doc.match('(this|next|last|current) quarter').tag('FinancialQuarter', here$1); + doc.match('(this|next|last|current) season').tag('Season', here$1); + + if (doc.has('#Date')) { + //friday to sunday + doc.match('#Date #Preposition #Date').tag('Date', here$1); //once a day.. + + doc.match('(once|twice) (a|an|each) #Date').tag('Date', here$1); //TODO:fixme + + doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here$1); //tuesday + + doc.match('#Date+').tag('Date', here$1); //by June + + doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here$1); //a year after.. + + doc.match('a #Duration').tag('Date', here$1); //between x and y + + doc.match('(between|from) #Date').tag('Date', here$1); + doc.match('(to|until|upto) #Date').tag('Date', here$1); + doc.match('#Date and #Date').tag('Date', here$1); //during this june + + doc.match('(by|until|after|before|during|on|in|following) (next|this|last)? (#Date|#Date)').tag('Date', here$1); //day after next + + doc.match('the? #Date after next one?').tag('Date', here$1); //approximately... + + doc.match('(about|approx|approximately|around) #Date').tag('Date', here$1); + } + + return doc; + }; + + var _02Dates = dateTagger; + + var here$2 = 'section-tagger'; // + + var sectionTagger = function sectionTagger(doc) { + if (doc.has('#Date')) { + // //next september + doc.match('this? (last|next|past|this|previous|current|upcoming|coming|the) #Date').tag('Date', here$2); //starting this june + + doc.match('(starting|beginning|ending) #Date').tag('Date', here$2); //start of june + + doc.match('the? (start|end|middle|beginning) of (last|next|this|the) (#Date|#Date)').tag('Date', here$2); //this coming june + + doc.match('(the|this) #Date').tag('Date', here$2); + } + + return doc; + }; + + var _03Sections = sectionTagger; + + var here$3 = 'time-tagger'; // + + var timeTagger = function timeTagger(doc) { + if (doc.has('#Time')) { + //eastern daylight time + doc.match('#Noun (standard|daylight|central|mountain)? time').tag('Timezone', here$3); + } // https://raw.githubusercontent.com/davispuh/TimezoneParser/master/data/abbreviations.yml + + + if (doc.has('#Acronym')) { + var abbr = '(acdt|acst|ace|dmt|ist|tse|addt|adt|aedt|aest|ahdt|ahst|akdt|akst|amt|nst|apt|awt|gmt|awdt|awst|bdst|bst|bdt|nwt|bmt|wet|bost|cddt|cdt|cet|cmt|cpt|cst|cwt|chst|gst|eat|eddt|edt|eest|eet|emt|ept|ewt|est|ffmt|fmt|hdt|hst|hkst|hkt|hmt|iddt|idt|jmt|imt|jdt|jst|kdt|kst|kmt|lst|mddt|mdst|msd|msk|mdt|mmt|mpt|pdt|pst|mst|mwt|nddt|ndt|npt|nzdt|nzmt|nzst|pddt|pkst|pkt|plmt|pmmt|pmt|ppmt|ppt|pwt|qmt|rmt|sast|sdmt|set|sjmt|smt|sst|tbmt|tmt|utc|wast|wemt|wib|wit|wita|wmt|yddt|ydt|ypt|ywt|yst)'; + doc.match(abbr).tag('Timezone', here$3); + } // quarter to seven + + + if (doc.has('#Cardinal')) { + doc.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal').tag('Time'); + } + + return doc; + }; + + var _04Time = timeTagger; + + var here$4 = 'shift-tagger'; // + + var shiftTagger = function shiftTagger(doc) { + if (doc.has('#Date')) { + //two weeks before + doc.match('#Cardinal #Duration (before|after)').tag('#DateShift', here$4); //two weeks and three days before + + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here$4); + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here$4); + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here$4); + } + + return doc; + }; + + var _05Shifts = shiftTagger; + + var here$5 = 'fix-tagger'; // + + var fixUp = function fixUp(doc) { + //fixups + if (doc.has('#Date')) { + //first day by monday + var oops = doc.match('#Date+ by #Date+'); + + if (oops.found && !oops.has('^due')) { + oops.match('^#Date+').unTag('Date', 'by-monday'); + } + + var d = doc.match('#Date+'); //'spa day' + + d.match('^day$').unTag('Date', 'spa-day'); + var knownDate = '(yesterday|today|tomorrow)'; + + if (d.has(knownDate)) { + //yesterday 7 + d.match("".concat(knownDate, " [#Value]$")).unTag('Date', 'yesterday-7'); //7 yesterday + + d.match("^[#Value] ".concat(knownDate, "$")).unTag('Date', '7 yesterday'); //friday yesterday + + d.match("#WeekDay+ ".concat(knownDate, "$")).unTag('Date').lastTerm().tag('Date', 'fri-yesterday'); // yesterday yesterday + // d.match(`${knownDate}+ ${knownDate}$`) + // .unTag('Date') + // .lastTerm() + // .tag('Date', here) + + d.match("(this|last|next) #Date ".concat(knownDate, "$")).unTag('Date').lastTerm().tag('Date', 'this month yesterday'); + } //tomorrow on 5 + + + d.match("on #Cardinal$").unTag('Date', here$5); //this tomorrow + + d.match("this tomorrow").terms(0).unTag('Date', 'this-tomorrow'); //q2 2019 + + d.match("(q1|q2|q3|q4) #Year").tag('Date', here$5); //5 tuesday + // d.match(`^#Value #WeekDay`).terms(0).unTag('Date'); + //5 next week + + d.match("^#Value (this|next|last)").terms(0).unTag('Date', here$5); + + if (d.has('(last|this|next)')) { + //this month 7 + d.match("(last|this|next) #Duration #Value").terms(2).unTag('Date', here$5); //7 this month + + d.match("!#Month #Value (last|this|next) #Date").terms(0).unTag('Date', here$5); + } //january 5 5 + + + if (d.has('(#Year|#Time|#TextValue|#NumberRange)') === false) { + d.match('(#Month|#WeekDay) #Value #Value').terms(2).unTag('Date', here$5); + } //between june + + + if (d.has('^between') && !d.has('and .')) { + d.unTag('Date', here$5); + } //june june + + + if (d.has('#Month #Month') && !d.has('@hasHyphen') && !d.has('@hasComma')) { + d.match('#Month').lastTerm().unTag('Date', 'month-month'); + } + } + + return doc; + }; + + var _06Fixup = fixUp; + + var methods = [_00Basic, _01Values, _02Dates, _03Sections, _04Time, _05Shifts, _06Fixup]; // run each of the taggers + + var tagDate = function tagDate(doc) { + methods.forEach(function (fn) { + return fn(doc); + }); + return doc; + }; + + var tagger = tagDate; + + var tags = { + FinancialQuarter: { + isA: 'Date' + }, + // 'summer' + Season: { + isA: 'Date' + }, + // '1982' + Year: { + isA: ['Date'], + notA: 'RomanNumeral' + }, + // 'months' + Duration: { + isA: ['Date', 'Noun'] + }, + // '9:20pm' + Time: { + isA: ['Date'] + }, + // 'easter' + Holiday: { + isA: ['Date', 'Noun'] + }, + // 'PST' + Timezone: { + isA: ['Date', 'Noun'] + }, + // 'two weeks before' + DateShift: { + isA: ['Date'] + } + }; + + var dates = ['weekend', 'weekday', 'summer', 'winter', 'autumn', 'some day', 'one day', 'all day', 'some point', 'eod', 'eom', 'standard time', 'daylight time', 'today', 'tomorrow', 'tmr', 'tmrw', 'yesterday']; + + var durations = ['centuries', 'century', 'day', 'days', 'decade', 'decades', 'hour', 'hours', 'millisecond', 'milliseconds', 'minute', 'minutes', 'month', 'months', 'seconds', 'week', 'weeks', 'year', 'years']; + + var holidays = ['all hallows eve', 'all saints day', 'all sts day', 'april fools', 'armistice day', 'australia day', 'bastille day', 'boxing day', 'canada day', 'christmas eve', 'christmas', 'cinco de mayo', 'day of the dead', 'dia de muertos', 'dieciseis de septiembre', 'emancipation day', 'grito de dolores', 'groundhog day', 'halloween', 'harvey milk day', 'inauguration day', 'independence day', 'independents day', 'juneteenth', 'labour day', 'national freedom day', 'national nurses day', 'new years eve', 'new years', 'purple heart day', 'rememberance day', 'rosa parks day', 'saint andrews day', 'saint patricks day', 'saint stephens day', 'saint valentines day', 'st andrews day', 'st patricks day', 'st stephens day', 'st valentines day ', 'valentines day', 'valentines', 'veterans day', 'victoria day', 'womens equality day', 'xmas', // Fixed religious and cultural holidays + // Catholic + Christian + 'epiphany', 'orthodox christmas day', 'orthodox new year', 'assumption of mary', 'all souls day', 'feast of the immaculate conception', 'feast of our lady of guadalupe', // Kwanzaa + 'kwanzaa', // Pagan / metal 🤘 + 'imbolc', 'beltaine', 'lughnassadh', 'samhain', 'martin luther king day', 'mlk day', 'presidents day', 'mardi gras', 'tax day', 'commonwealth day', 'mothers day', 'memorial day', 'fathers day', 'columbus day', 'indigenous peoples day', 'canadian thanksgiving', 'election day', 'thanksgiving', 't-day', 'turkey day', 'black friday', 'cyber monday', // Astronomical religious and cultural holidays + 'ash wednesday', 'palm sunday', 'maundy thursday', 'good friday', 'holy saturday', 'easter', 'easter sunday', 'easter monday', 'orthodox good friday', 'orthodox holy saturday', 'orthodox easter', 'orthodox easter monday', 'ascension day', 'pentecost', 'whitsunday', 'whit sunday', 'whit monday', 'trinity sunday', 'corpus christi', 'advent', // Jewish + 'tu bishvat', 'tu bshevat', 'purim', 'passover', 'yom hashoah', 'lag baomer', 'shavuot', 'tisha bav', 'rosh hashana', 'yom kippur', 'sukkot', 'shmini atzeret', 'simchat torah', 'chanukah', 'hanukkah', // Muslim + 'isra and miraj', 'lailat al-qadr', 'eid al-fitr', 'id al-Fitr', 'eid ul-Fitr', 'ramadan', 'eid al-adha', 'muharram', 'the prophets birthday', 'ostara', 'march equinox', 'vernal equinox', 'litha', 'june solistice', 'summer solistice', 'mabon', 'september equinox', 'fall equinox', 'autumnal equinox', 'yule', 'december solstice', 'winter solstice', // Additional important holidays + 'chinese new year', 'diwali']; + + var times = ['noon', 'midnight', 'now', 'morning', 'tonight', 'evening', 'afternoon', 'night', 'breakfast time', 'lunchtime', 'dinnertime', 'ago', 'sometime', 'eod', 'oclock', 'oclock', 'all day', 'at night']; + + var lex = {}; + var data = [[dates, ['#Date']], [durations, ['#Duration']], [holidays, ['#Holiday']], [times, ['#Time']]]; + data.forEach(function (a) { + for (var i = 0; i < a[0].length; i++) { + lex[a[0][i]] = a[1]; + } + }); + var words = lex; + + var normalize = function normalize(doc) { + doc = doc.clone(); + + if (!doc.numbers) { + console.warn("Compromise: compromise-dates cannot find plugin dependency 'compromise-number'"); + } else { + // convert 'two' to 2 + var num = doc.numbers(); + num.toNumber(); + num.toCardinal(); + } // remove adverbs + + + doc.adverbs().remove(); + return doc; + }; + + var _01Normalize = normalize; + + var knownUnits = { + second: true, + minute: true, + hour: true, + day: true, + week: true, + month: true, + season: true, + quarter: true, + year: true + }; //turn '5 weeks before' to {weeks:5} + + var parseShift = function parseShift(doc) { + var result = {}; + var m = doc.match('#DateShift+'); + + if (m.found === false) { + return result; + } + + m.match('#Cardinal #Duration').forEach(function (ts) { + var num = ts.match('#Cardinal').text('normal'); + num = parseFloat(num); + + if (num && typeof num === 'number') { + var unit = ts.match('#Duration').text('normal'); + unit = unit.replace(/s$/, ''); + + if (unit && knownUnits.hasOwnProperty(unit)) { + result[unit] = num; + } + } + }); //is it 2 weeks before? → -2 + + if (m.has('before$') === true) { + Object.keys(result).forEach(function (k) { + return result[k] *= -1; + }); + } // finally, remove it from our text + + + doc.remove('#DateShift'); + return result; + }; + + var _01Shift = parseShift; + + function createCommonjsModule(fn, module) { + return module = { + exports: {} + }, fn(module, module.exports), module.exports; + } + + function getCjsExportFromNamespace(n) { + return n && n['default'] || n; + } + + var fns = createCommonjsModule(function (module, exports) { + //git:blame @JuliasCaesar https://www.timeanddate.com/date/leapyear.html + exports.isLeapYear = function (year) { + return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; + }; // unsurprisingly-nasty `typeof date` call + + + exports.isDate = function (d) { + return Object.prototype.toString.call(d) === '[object Date]' && !isNaN(d.valueOf()); + }; + + exports.isArray = function (input) { + return Object.prototype.toString.call(input) === '[object Array]'; + }; + + exports.isObject = function (input) { + return Object.prototype.toString.call(input) === '[object Object]'; + }; + + exports.zeroPad = function (str) { + var len = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; + var pad = '0'; + str = str + ''; + return str.length >= len ? str : new Array(len - str.length + 1).join(pad) + str; + }; + + exports.titleCase = function (str) { + if (!str) { + return ''; + } + + return str[0].toUpperCase() + str.substr(1); + }; + + exports.ordinal = function (i) { + var j = i % 10; + var k = i % 100; + + if (j === 1 && k !== 11) { + return i + 'st'; + } + + if (j === 2 && k !== 12) { + return i + 'nd'; + } + + if (j === 3 && k !== 13) { + return i + 'rd'; + } + + return i + 'th'; + }; //strip 'st' off '1st'.. + + + exports.toCardinal = function (str) { + str = String(str); + str = str.replace(/([0-9])(st|nd|rd|th)$/i, '$1'); + return parseInt(str, 10); + }; //used mostly for cleanup of unit names, like 'months' + + + exports.normalize = function () { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + str = str.toLowerCase().trim(); + str = str.replace(/ies$/, 'y'); //'centuries' + + str = str.replace(/s$/, ''); + str = str.replace(/-/g, ''); + + if (str === 'day') { + return 'date'; + } + + return str; + }; + + exports.getEpoch = function (tmp) { + //support epoch + if (typeof tmp === 'number') { + return tmp; + } //suport date objects + + + if (exports.isDate(tmp)) { + return tmp.getTime(); + } + + if (tmp.epoch) { + return tmp.epoch; + } + + return null; + }; //make sure this input is a spacetime obj + + + exports.beADate = function (d, s) { + if (exports.isObject(d) === false) { + return s.clone().set(d); + } + + return d; + }; + + exports.formatTimezone = function (offset) { + var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var absOffset = Math.abs(offset); + var sign = offset > 0 ? '+' : '-'; + return "".concat(sign).concat(exports.zeroPad(absOffset)).concat(delimiter, "00"); + }; + }); + var fns_1 = fns.isLeapYear; + var fns_2 = fns.isDate; + var fns_3 = fns.isArray; + var fns_4 = fns.isObject; + var fns_5 = fns.zeroPad; + var fns_6 = fns.titleCase; + var fns_7 = fns.ordinal; + var fns_8 = fns.toCardinal; + var fns_9 = fns.normalize; + var fns_10 = fns.getEpoch; + var fns_11 = fns.beADate; + var fns_12 = fns.formatTimezone; + var zeroPad = fns.zeroPad; + + var toString = function toString(d) { + return zeroPad(d.getMonth() + 1) + '/' + zeroPad(d.getDate()) + ':' + zeroPad(d.getHours()); + }; // a timezone will begin with a specific offset in january + // then some will switch to something else between november-march + + + var shouldChange = function shouldChange(epoch, start, end, defaultOffset) { + //note: this has a cray order-of-operations issue + //we can't get the date, without knowing the timezone, and vice-versa + //it's possible that we can miss a dst-change by a few hours. + var d = new Date(epoch); //(try to mediate this a little?) + + var bias = d.getTimezoneOffset() || 0; + var shift = bias + defaultOffset * 60; //in minutes + + shift = shift * 60 * 1000; //in ms + + d = new Date(epoch + shift); + var current = toString(d); //eg. is it after ~november? + + if (current >= start) { + //eg. is it before ~march~ too? + if (current < end) { + return true; + } + } + + return false; + }; + + var summerTime = shouldChange; // this method avoids having to do a full dst-calculation on every operation + // it reproduces some things in ./index.js, but speeds up spacetime considerably + + var quickOffset = function quickOffset(s) { + var zones = s.timezones; + var obj = zones[s.tz]; + + if (obj === undefined) { + console.warn("Warning: couldn't find timezone " + s.tz); + return 0; + } + + if (obj.dst === undefined) { + return obj.offset; + } //get our two possible offsets + + + var jul = obj.offset; + var dec = obj.offset + 1; // assume it's the same for now + + if (obj.hem === 'n') { + dec = jul - 1; + } + + var split = obj.dst.split('->'); + var inSummer = summerTime(s.epoch, split[0], split[1], jul); + + if (inSummer === true) { + return jul; + } + + return dec; + }; + + var quick = quickOffset; + var _build = { + "9|s": "2/dili,2/jayapura", + "9|n": "2/chita,2/khandyga,2/pyongyang,2/seoul,2/tokyo,11/palau", + "9.5|s|04/07:03->10/06:02": "4/adelaide,4/broken_hill,4/south,4/yancowinna", + "9.5|s": "4/darwin,4/north", + "8|s": "12/casey,2/kuala_lumpur,2/makassar,2/singapore,4/perth,4/west", + "8|n|03/25:03->09/29:23": "2/ulan_bator", + "8|n": "2/brunei,2/choibalsan,2/chongqing,2/chungking,2/harbin,2/hong_kong,2/irkutsk,2/kuching,2/macao,2/macau,2/manila,2/shanghai,2/taipei,2/ujung_pandang,2/ulaanbaatar", + "8.75|s": "4/eucla", + "7|s": "12/davis,2/jakarta,9/christmas", + "7|n": "2/bangkok,2/barnaul,2/ho_chi_minh,2/hovd,2/krasnoyarsk,2/novokuznetsk,2/novosibirsk,2/phnom_penh,2/pontianak,2/saigon,2/tomsk,2/vientiane", + "6|s": "12/vostok", + "6|n": "2/almaty,2/bishkek,2/dacca,2/dhaka,2/kashgar,2/omsk,2/qyzylorda,2/thimbu,2/thimphu,2/urumqi,9/chagos", + "6.5|n": "2/rangoon,9/cocos", + "5|s": "12/mawson,9/kerguelen", + "5|n": "2/aqtau,2/aqtobe,2/ashgabat,2/ashkhabad,2/atyrau,2/baku,2/dushanbe,2/karachi,2/oral,2/samarkand,2/tashkent,2/yekaterinburg,9/maldives", + "5.75|n": "2/kathmandu,2/katmandu", + "5.5|n": "2/calcutta,2/colombo,2/kolkata", + "4|s": "9/reunion", + "4|n": "2/dubai,2/muscat,2/tbilisi,2/yerevan,8/astrakhan,8/samara,8/saratov,8/ulyanovsk,8/volgograd,2/volgograd,9/mahe,9/mauritius", + "4.5|n|03/22:00->09/21:24": "2/tehran", + "4.5|n": "2/kabul", + "3|s": "12/syowa,9/antananarivo", + "3|n|03/31:03->10/27:04": "2/nicosia,8/athens,8/bucharest,8/helsinki,8/kiev,8/mariehamn,8/nicosia,8/riga,8/sofia,8/tallinn,8/uzhgorod,8/vilnius,8/zaporozhye", + "3|n|03/31:02->10/27:03": "8/chisinau,8/tiraspol", + "3|n|03/31:00->10/26:24": "2/beirut", + "3|n|03/29:02->10/27:02": "2/jerusalem,2/tel_aviv", + "3|n|03/29:00->10/26:01": "2/gaza,2/hebron", + "3|n|03/29:00->10/25:01": "2/amman", + "3|n|03/29:00->10/24:24": "2/damascus", + "3|n": "0/addis_ababa,0/asmara,0/asmera,0/dar_es_salaam,0/djibouti,0/juba,0/kampala,0/mogadishu,0/nairobi,2/aden,2/baghdad,2/bahrain,2/istanbul,2/kuwait,2/qatar,2/riyadh,8/istanbul,8/kirov,8/minsk,8/moscow,8/simferopol,9/comoro,9/mayotte", + "2|s|03/31:02->10/27:02": "12/troll", + "2|s": "0/gaborone,0/harare,0/johannesburg,0/lubumbashi,0/lusaka,0/maputo,0/maseru,0/mbabane", + "2|n|03/31:02->10/27:03": "0/ceuta,arctic/longyearbyen,3/jan_mayen,8/amsterdam,8/andorra,8/belgrade,8/berlin,8/bratislava,8/brussels,8/budapest,8/busingen,8/copenhagen,8/gibraltar,8/ljubljana,8/luxembourg,8/madrid,8/malta,8/monaco,8/oslo,8/paris,8/podgorica,8/prague,8/rome,8/san_marino,8/sarajevo,8/skopje,8/stockholm,8/tirane,8/vaduz,8/vatican,8/vienna,8/warsaw,8/zagreb,8/zurich", + "2|n": "0/blantyre,0/bujumbura,0/cairo,0/khartoum,0/kigali,0/tripoli,8/kaliningrad", + "1|s|04/02:01->09/03:03": "0/windhoek", + "1|s": "0/kinshasa,0/luanda", + "1|n|05/05:03->06/09:02": "0/casablanca,0/el_aaiun", + "1|n|03/31:01->10/27:02": "3/canary,3/faeroe,3/faroe,3/madeira,8/belfast,8/dublin,8/guernsey,8/isle_of_man,8/jersey,8/lisbon,8/london", + "1|n": "0/algiers,0/bangui,0/brazzaville,0/douala,0/lagos,0/libreville,0/malabo,0/ndjamena,0/niamey,0/porto-novo,0/tunis", + "14|n": "11/kiritimati", + "13|s|04/07:04->09/29:03": "11/apia", + "13|s|01/15:02->11/05:03": "11/tongatapu", + "13|n": "11/enderbury,11/fakaofo", + "12|s|04/07:03->09/29:02": "12/mcmurdo,12/south_pole,11/auckland", + "12|s|01/13:03->11/10:02": "11/fiji", + "12|n": "2/anadyr,2/kamchatka,2/srednekolymsk,11/funafuti,11/kwajalein,11/majuro,11/nauru,11/tarawa,11/wake,11/wallis", + "12.75|s|04/07:03->09/29:02": "11/chatham", + "11|s": "12/macquarie,11/bougainville", + "11|n": "2/magadan,2/sakhalin,11/efate,11/guadalcanal,11/kosrae,11/noumea,11/pohnpei,11/ponape", + "11.5|n": "11/norfolk", + "10|s|04/07:03->10/06:02": "4/act,4/canberra,4/currie,4/hobart,4/melbourne,4/nsw,4/sydney,4/tasmania,4/victoria", + "10|s": "12/dumontdurville,4/brisbane,4/lindeman,4/queensland", + "10|n": "2/ust-nera,2/vladivostok,2/yakutsk,11/chuuk,11/guam,11/port_moresby,11/saipan,11/truk,11/yap", + "10.5|s|04/07:01->10/06:02": "4/lhi,4/lord_howe", + "0|n|03/31:00->10/27:01": "1/scoresbysund,3/azores", + "0|n": "0/abidjan,0/accra,0/bamako,0/banjul,0/bissau,0/conakry,0/dakar,0/freetown,0/lome,0/monrovia,0/nouakchott,0/ouagadougou,0/sao_tome,0/timbuktu,1/danmarkshavn,3/reykjavik,3/st_helena,13/gmt,13/gmt+0,13/gmt-0,13/gmt0,13/greenwich,13/utc,13/universal,13/zulu", + "-9|n|03/10:02->11/03:02": "1/adak,1/atka", + "-9|n": "11/gambier", + "-9.5|n": "11/marquesas", + "-8|n|03/10:02->11/03:02": "1/anchorage,1/juneau,1/metlakatla,1/nome,1/sitka,1/yakutat", + "-8|n": "11/pitcairn", + "-7|n|03/10:02->11/03:02": "1/dawson,1/ensenada,1/los_angeles,1/santa_isabel,1/tijuana,1/vancouver,1/whitehorse,6/pacific,6/yukon,10/bajanorte", + "-7|n": "1/creston,1/dawson_creek,1/hermosillo,1/phoenix", + "-6|s|04/06:22->09/07:22": "7/easterisland,11/easter", + "-6|n|04/07:02->10/27:02": "1/chihuahua,1/mazatlan,10/bajasur", + "-6|n|03/10:02->11/03:02": "1/boise,1/cambridge_bay,1/denver,1/edmonton,1/inuvik,1/ojinaga,1/shiprock,1/yellowknife,6/mountain", + "-6|n": "1/belize,1/costa_rica,1/el_salvador,1/guatemala,1/managua,1/regina,1/swift_current,1/tegucigalpa,6/east-saskatchewan,6/saskatchewan,11/galapagos", + "-5|s": "1/lima,1/rio_branco,5/acre", + "-5|n|04/07:02->10/27:02": "1/bahia_banderas,1/merida,1/mexico_city,1/monterrey,10/general", + "-5|n|03/12:03->11/05:01": "1/north_dakota", + "-5|n|03/10:02->11/03:02": "1/chicago,1/knox_in,1/matamoros,1/menominee,1/rainy_river,1/rankin_inlet,1/resolute,1/winnipeg,6/central", + "-5|n": "1/atikokan,1/bogota,1/cancun,1/cayman,1/coral_harbour,1/eirunepe,1/guayaquil,1/jamaica,1/panama,1/porto_acre", + "-4|s|05/13:23->08/13:01": "12/palmer", + "-4|s|04/06:24->09/08:00": "1/santiago,7/continental", + "-4|s|03/23:24->10/06:00": "1/asuncion", + "-4|s|02/16:24->11/03:00": "1/campo_grande,1/cuiaba", + "-4|s": "1/la_paz,1/manaus,5/west", + "-4|n|03/12:03->11/05:01": "1/indiana,1/kentucky", + "-4|n|03/10:02->11/03:02": "1/detroit,1/fort_wayne,1/grand_turk,1/indianapolis,1/iqaluit,1/louisville,1/montreal,1/nassau,1/new_york,1/nipigon,1/pangnirtung,1/port-au-prince,1/thunder_bay,1/toronto,6/eastern", + "-4|n|03/10:00->11/03:01": "1/havana", + "-4|n": "1/anguilla,1/antigua,1/aruba,1/barbados,1/blanc-sablon,1/boa_vista,1/caracas,1/curacao,1/dominica,1/grenada,1/guadeloupe,1/guyana,1/kralendijk,1/lower_princes,1/marigot,1/martinique,1/montserrat,1/port_of_spain,1/porto_velho,1/puerto_rico,1/santo_domingo,1/st_barthelemy,1/st_kitts,1/st_lucia,1/st_thomas,1/st_vincent,1/tortola,1/virgin", + "-3|s": "1/argentina,1/buenos_aires,1/cordoba,1/fortaleza,1/montevideo,1/punta_arenas,1/sao_paulo,12/rothera,3/stanley,5/east", + "-3|n|03/10:02->11/03:02": "1/glace_bay,1/goose_bay,1/halifax,1/moncton,1/thule,3/bermuda,6/atlantic", + "-3|n": "1/araguaina,1/bahia,1/belem,1/catamarca,1/cayenne,1/jujuy,1/maceio,1/mendoza,1/paramaribo,1/recife,1/rosario,1/santarem", + "-2|s": "5/denoronha", + "-2|n|03/30:22->10/26:23": "1/godthab", + "-2|n|03/10:02->11/03:02": "1/miquelon", + "-2|n": "1/noronha,3/south_georgia", + "-2.5|n|03/10:02->11/03:02": "1/st_johns,6/newfoundland", + "-1|n": "3/cape_verde", + "-11|n": "11/midway,11/niue,11/pago_pago,11/samoa", + "-10|n": "11/honolulu,11/johnston,11/rarotonga,11/tahiti" + }; + + var _build$1 = + /*#__PURE__*/ + Object.freeze({ + 'default': _build + }); //prefixes for iana names.. + + + var _prefixes = ['africa', 'america', 'asia', 'atlantic', 'australia', 'brazil', 'canada', 'chile', 'europe', 'indian', 'mexico', 'pacific', 'antarctica', 'etc']; + var data$1 = getCjsExportFromNamespace(_build$1); + var all = {}; + Object.keys(data$1).forEach(function (k) { + var split = k.split('|'); + var obj = { + offset: Number(split[0]), + hem: split[1] + }; + + if (split[2]) { + obj.dst = split[2]; + } + + var names = data$1[k].split(','); + names.forEach(function (str) { + str = str.replace(/(^[0-9]+)\//, function (before, num) { + num = Number(num); + return _prefixes[num] + '/'; + }); + all[str] = obj; + }); + }); + all['utc'] = { + offset: 0, + hem: 'n' //(sorry) + + }; //add etc/gmt+n + + for (var i = -14; i <= 14; i += 0.5) { + var num = i; + + if (num > 0) { + num = '+' + num; + } + + var name = 'etc/gmt' + num; + all[name] = { + offset: i * -1, + //they're negative! + hem: 'n' //(sorry) + + }; + name = 'utc/gmt' + num; //this one too, why not. + + all[name] = { + offset: i * -1, + hem: 'n' + }; + } // console.log(all) + // console.log(Object.keys(all).length) + + + var unpack = all; //find the implicit iana code for this machine. + //safely query the Intl object + //based on - https://bitbucket.org/pellepim/jstimezonedetect/src + + var fallbackTZ = 'utc'; // + //this Intl object is not supported often, yet + + var safeIntl = function safeIntl() { + if (typeof Intl === 'undefined' || typeof Intl.DateTimeFormat === 'undefined') { + return null; + } + + var format = Intl.DateTimeFormat(); + + if (typeof format === 'undefined' || typeof format.resolvedOptions === 'undefined') { + return null; + } + + var timezone = format.resolvedOptions().timeZone; + + if (!timezone) { + return null; + } + + return timezone.toLowerCase(); + }; + + var guessTz = function guessTz() { + var timezone = safeIntl(); + + if (timezone === null) { + return fallbackTZ; + } + + return timezone; + }; //do it once per computer + + + var guessTz_1 = guessTz; + var isOffset = /(\-?[0-9]+)h(rs)?/i; + var isNumber = /(\-?[0-9]+)/; + var utcOffset = /utc([\-+]?[0-9]+)/i; + var gmtOffset = /gmt([\-+]?[0-9]+)/i; + + var toIana = function toIana(num) { + num = Number(num); + + if (num > -13 && num < 13) { + num = num * -1; //it's opposite! + + num = (num > 0 ? '+' : '') + num; //add plus sign + + return 'etc/gmt' + num; + } + + return null; + }; + + var parseOffset = function parseOffset(tz) { + // '+5hrs' + var m = tz.match(isOffset); + + if (m !== null) { + return toIana(m[1]); + } // 'utc+5' + + + m = tz.match(utcOffset); + + if (m !== null) { + return toIana(m[1]); + } // 'GMT-5' (not opposite) + + + m = tz.match(gmtOffset); + + if (m !== null) { + var _num = Number(m[1]) * -1; + + return toIana(_num); + } // '+5' + + + m = tz.match(isNumber); + + if (m !== null) { + return toIana(m[1]); + } + + return null; + }; + + var parseOffset_1 = parseOffset; + var local = guessTz_1(); //add all the city names by themselves + + var cities = Object.keys(unpack).reduce(function (h, k) { + var city = k.split('/')[1] || ''; + city = city.replace(/_/g, ' '); + h[city] = k; + return h; + }, {}); //try to match these against iana form + + var normalize$1 = function normalize(tz) { + tz = tz.replace(/ time/g, ''); + tz = tz.replace(/ (standard|daylight|summer)/g, ''); + tz = tz.replace(/\b(east|west|north|south)ern/g, '$1'); + tz = tz.replace(/\b(africa|america|australia)n/g, '$1'); + tz = tz.replace(/\beuropean/g, 'europe'); + tz = tz.replace(/\islands/g, 'island'); + return tz; + }; // try our best to reconcile the timzone to this given string + + + var lookupTz = function lookupTz(str, zones) { + if (!str) { + return local; + } + + var tz = str.trim(); + var split = str.split('/'); //support long timezones like 'America/Argentina/Rio_Gallegos' + + if (split.length > 2 && zones.hasOwnProperty(tz) === false) { + tz = split[0] + '/' + split[1]; + } + + tz = tz.toLowerCase(); + + if (zones.hasOwnProperty(tz) === true) { + return tz; + } //lookup more loosely.. + + + tz = normalize$1(tz); + + if (zones.hasOwnProperty(tz) === true) { + return tz; + } //try city-names + + + if (cities.hasOwnProperty(tz) === true) { + return cities[tz]; + } // //try to parse '-5h' + + + if (/[0-9]/.test(tz) === true) { + var id = parseOffset_1(tz); + + if (id) { + return id; + } + } + + throw new Error("Spacetime: Cannot find timezone named: '" + str + "'. Please enter an IANA timezone id."); + }; + + var find = lookupTz; + var o = { + millisecond: 1 + }; + o.second = 1000; + o.minute = 60000; + o.hour = 3.6e6; // dst is supported post-hoc + + o.day = 8.64e7; // + + o.date = o.day; + o.month = 8.64e7 * 29.5; //(average) + + o.week = 6.048e8; + o.year = 3.154e10; // leap-years are supported post-hoc + //add plurals + + Object.keys(o).forEach(function (k) { + o[k + 's'] = o[k]; + }); + var milliseconds = o; //basically, step-forward/backward until js Date object says we're there. + + var walk = function walk(s, n, fn, unit, previous) { + var current = s.d[fn](); + + if (current === n) { + return; //already there + } + + var startUnit = previous === null ? null : s.d[previous](); + var original = s.epoch; //try to get it as close as we can + + var diff = n - current; + s.epoch += milliseconds[unit] * diff; //DST edge-case: if we are going many days, be a little conservative + + if (unit === 'day' && Math.abs(diff) > 28) { + //but don't push it over a month + if (n < 28) { + s.epoch += milliseconds.hour; + } + } //repair it if we've gone too far or something + //(go by half-steps, just in case) + + + var halfStep = milliseconds[unit] / 2; + + while (s.d[fn]() < n) { + s.epoch += halfStep; + } + + while (s.d[fn]() > n) { + s.epoch -= halfStep; + } //oops, did we change previous unit? revert it. + + + if (previous !== null && startUnit !== s.d[previous]()) { + // console.warn('spacetime warning: missed setting ' + unit) + s.epoch = original; // i mean, but make it close... + + s.epoch += milliseconds[unit] * diff * 0.89; // i guess? + } + }; //find the desired date by a increment/check while loop + + + var units = { + year: { + valid: function valid(n) { + return n > -4000 && n < 4000; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getFullYear', 'year', null); + } + }, + month: { + valid: function valid(n) { + return n >= 0 && n <= 11; + }, + walkTo: function walkTo(s, n) { + var d = s.d; + var current = d.getMonth(); + var original = s.epoch; + var startUnit = d.getFullYear(); + + if (current === n) { + return; + } //try to get it as close as we can.. + + + var diff = n - current; + s.epoch += milliseconds.day * (diff * 28); //special case + //oops, did we change the year? revert it. + + if (startUnit !== s.d.getFullYear()) { + s.epoch = original; + } //incriment by day + + + while (s.d.getMonth() < n) { + s.epoch += milliseconds.day; + } + + while (s.d.getMonth() > n) { + s.epoch -= milliseconds.day; + } + } + }, + date: { + valid: function valid(n) { + return n > 0 && n <= 31; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getDate', 'day', 'getMonth'); + } + }, + hour: { + valid: function valid(n) { + return n >= 0 && n < 24; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getHours', 'hour', 'getDate'); + } + }, + minute: { + valid: function valid(n) { + return n >= 0 && n < 60; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getMinutes', 'minute', 'getHours'); + } + }, + second: { + valid: function valid(n) { + return n >= 0 && n < 60; + }, + walkTo: function walkTo(s, n) { + //do this one directly + s.epoch = s.seconds(n).epoch; + } + }, + millisecond: { + valid: function valid(n) { + return n >= 0 && n < 1000; + }, + walkTo: function walkTo(s, n) { + //do this one directly + s.epoch = s.milliseconds(n).epoch; + } + } + }; + + var walkTo = function walkTo(s, wants) { + var keys = Object.keys(units); + var old = s.clone(); + + for (var _i = 0; _i < keys.length; _i++) { + var k = keys[_i]; + var n = wants[k]; + + if (n === undefined) { + n = old[k](); + } + + if (typeof n === 'string') { + n = parseInt(n, 10); + } //make-sure it's valid + + + if (!units[k].valid(n)) { + s.epoch = null; + + if (s.silent === false) { + console.warn('invalid ' + k + ': ' + n); + } + + return; + } // console.log(k, n) + + + units[k].walkTo(s, n); + } + + return; + }; + + var walk_1 = walkTo; + var shortMonths = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sept', 'oct', 'nov', 'dec']; + var longMonths = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; + + function buildMapping() { + var obj = { + sep: 8 //support this format + + }; + + for (var _i2 = 0; _i2 < shortMonths.length; _i2++) { + obj[shortMonths[_i2]] = _i2; + } + + for (var _i3 = 0; _i3 < longMonths.length; _i3++) { + obj[longMonths[_i3]] = _i3; + } + + return obj; + } + + var months = { + "short": function short() { + return shortMonths; + }, + "long": function long() { + return longMonths; + }, + mapping: function mapping() { + return buildMapping(); + }, + set: function set(i18n) { + shortMonths = i18n["short"] || shortMonths; + longMonths = i18n["long"] || longMonths; + } + }; //pull-apart ISO offsets, like "+0100" + + var parseOffset$1 = function parseOffset$1(s, offset) { + if (!offset) { + return s; + } //this is a fancy-move + + + if (offset === 'Z') { + offset = '+0000'; + } // according to ISO8601, tz could be hh:mm, hhmm or hh + // so need few more steps before the calculation. + + + var num = 0; // for (+-)hh:mm + + if (/^[\+-]?[0-9]{2}:[0-9]{2}$/.test(offset)) { + //support "+01:00" + if (/:00/.test(offset) === true) { + offset = offset.replace(/:00/, ''); + } //support "+01:30" + + + if (/:30/.test(offset) === true) { + offset = offset.replace(/:30/, '.5'); + } + } // for (+-)hhmm + + + if (/^[\+-]?[0-9]{4}$/.test(offset)) { + offset = offset.replace(/30$/, '.5'); + } + + num = parseFloat(offset); //divide by 100 or 10 - , "+0100", "+01" + + if (Math.abs(num) > 100) { + num = num / 100; + } //okay, try to match it to a utc timezone + //remember - this is opposite! a -5 offset maps to Etc/GMT+5 ¯\_(:/)_/¯ + //https://askubuntu.com/questions/519550/why-is-the-8-timezone-called-gmt-8-in-the-filesystem + + + num *= -1; + + if (num >= 0) { + num = '+' + num; + } + + var tz = 'etc/gmt' + num; + var zones = s.timezones; + + if (zones[tz]) { + // log a warning if we're over-writing a given timezone? + // console.log('changing timezone to: ' + tz) + s.tz = tz; + } + + return s; + }; + + var parseOffset_1$1 = parseOffset$1; + + var parseTime = function parseTime(s) { + var str = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + str = str.replace(/^\s+/, '').toLowerCase(); //trim + //formal time formats - 04:30.23 + + var arr = str.match(/([0-9]{1,2}):([0-9]{1,2}):?([0-9]{1,2})?[:\.]?([0-9]{1,4})?/); + + if (arr !== null) { + //validate it a little + var h = Number(arr[1]); + + if (h < 0 || h > 24) { + return s.startOf('day'); + } + + var m = Number(arr[2]); //don't accept '5:3pm' + + if (arr[2].length < 2 || m < 0 || m > 59) { + return s.startOf('day'); + } + + s = s.hour(h); + s = s.minute(m); + s = s.seconds(arr[3] || 0); + s = s.millisecond(arr[4] || 0); //parse-out am/pm + + var ampm = str.match(/[\b0-9](am|pm)\b/); + + if (ampm !== null && ampm[1]) { + s = s.ampm(ampm[1]); + } + + return s; + } //try an informal form - 5pm (no minutes) + + + arr = str.match(/([0-9]+) ?(am|pm)/); + + if (arr !== null && arr[1]) { + var _h = Number(arr[1]); //validate it a little.. + + + if (_h > 12 || _h < 1) { + return s.startOf('day'); + } + + s = s.hour(arr[1] || 0); + s = s.ampm(arr[2]); + s = s.startOf('hour'); + return s; + } //no time info found, use start-of-day + + + s = s.startOf('day'); + return s; + }; + + var parseTime_1 = parseTime; + var monthLengths = [31, // January - 31 days + 28, // February - 28 days in a common year and 29 days in leap years + 31, // March - 31 days + 30, // April - 30 days + 31, // May - 31 days + 30, // June - 30 days + 31, // July - 31 days + 31, // August - 31 days + 30, // September - 30 days + 31, // October - 31 days + 30, // November - 30 days + 31 // December - 31 days + ]; + var monthLengths_1 = monthLengths; + var isLeapYear = fns.isLeapYear; //given a month, return whether day number exists in it + + var hasDate = function hasDate(obj) { + //invalid values + if (monthLengths_1.hasOwnProperty(obj.month) !== true) { + return false; + } //support leap-year in february + + + if (obj.month === 1) { + if (isLeapYear(obj.year) && obj.date <= 29) { + return true; + } else { + return obj.date <= 28; + } + } //is this date too-big for this month? + + + var max = monthLengths_1[obj.month] || 0; + + if (obj.date <= max) { + return true; + } + + return false; + }; + + var hasDate_1 = hasDate; + var months$1 = months.mapping(); + + var parseYear = function parseYear() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + //support '18 -> 2018 + // str = str.replace(/^'([0-9]{2})/, '20$1') + // str = str.replace('([0-9]+) ?b\.?c\.?$', '-$1') + var year = parseInt(str.trim(), 10); + year = year || new Date().getFullYear(); + return year; + }; + + var strFmt = [//iso-this 1998-05-30T22:00:00:000Z, iso-that 2017-04-03T08:00:00-0700 + { + reg: /^(\-?0?0?[0-9]{3,4})-([0-9]{1,2})-([0-9]{1,2})[T| ]([0-9.:]+)(Z|[0-9\-\+:]+)?$/, + parse: function parse(s, arr, givenTz, options) { + var month = parseInt(arr[2], 10) - 1; + var obj = { + year: arr[1], + month: month, + date: arr[3] + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + parseOffset_1$1(s, arr[5]); + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } + }, //iso "2015-03-25" or "2015/03/25" or "2015/03/25 12:26:14 PM" + { + reg: /^([0-9]{4})[\-\/]([0-9]{1,2})[\-\/]([0-9]{1,2}),?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i, + parse: function parse(s, arr) { + var obj = { + year: arr[1], + month: parseInt(arr[2], 10) - 1, + date: parseInt(arr[3], 10) + }; + + if (obj.month >= 12) { + //support yyyy/dd/mm (weird, but ok) + obj.date = parseInt(arr[2], 10); + obj.month = parseInt(arr[3], 10) - 1; + } + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } + }, //mm/dd/yyyy - uk/canada "6/28/2019, 12:26:14 PM" + { + reg: /^([0-9]{1,2})[\-\/]([0-9]{1,2})[\-\/]?([0-9]{4})?,?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i, + parse: function parse(s, arr) { + var month = parseInt(arr[1], 10) - 1; + var date = parseInt(arr[2], 10); //support dd/mm/yyy + + if (s.british || month >= 12) { + date = parseInt(arr[1], 10); + month = parseInt(arr[2], 10) - 1; + } + + var year = arr[3] || new Date().getFullYear(); + var obj = { + year: year, + month: month, + date: date + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } + }, //common british format - "25-feb-2015" + { + reg: /^([0-9]{1,2})[\-\/]([a-z]+)[\-\/]?([0-9]{4})?$/i, + parse: function parse(s, arr) { + var month = months$1[arr[2].toLowerCase()]; + var year = parseYear(arr[3]); + var obj = { + year: year, + month: month, + date: fns.toCardinal(arr[1] || '') + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } + }, //Long "Mar 25 2015" + //February 22, 2017 15:30:00 + { + reg: /^([a-z]+) ([0-9]{1,2}(?:st|nd|rd|th)?),?( [0-9]{4})?( ([0-9:]+( ?am| ?pm| ?gmt)?))?$/i, + parse: function parse(s, arr) { + var month = months$1[arr[1].toLowerCase()]; + var year = parseYear(arr[3]); + var obj = { + year: year, + month: month, + date: fns.toCardinal(arr[2] || '') + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } + }, //February 2017 (implied date) + { + reg: /^([a-z]+) ([0-9]{4})$/i, + parse: function parse(s, arr) { + var month = months$1[arr[1].toLowerCase()]; + var year = parseYear(arr[2]); + var obj = { + year: year, + month: month, + date: 1 + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } + }, //Long "25 Mar 2015" + { + reg: /^([0-9]{1,2}(?:st|nd|rd|th)?) ([a-z]+),?( [0-9]{4})?,? ?([0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i, + parse: function parse(s, arr) { + var month = months$1[arr[2].toLowerCase()]; + + if (!month) { + return null; + } + + var year = parseYear(arr[3]); + var obj = { + year: year, + month: month, + date: fns.toCardinal(arr[1]) + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } + }, { + // '200bc' + reg: /^[0-9,]+ ?b\.?c\.?$/i, + parse: function parse(s, arr) { + var str = arr[0] || ''; //make negative-year + + str = str.replace(/^([0-9,]+) ?b\.?c\.?$/i, '-$1'); //remove commas + + str = str.replace(/,/g, ''); + var year = parseInt(str.trim(), 10); + var d = new Date(); + var obj = { + year: year, + month: d.getMonth(), + date: d.getDate() + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s); + return s; + } + }, { + // '200ad' + reg: /^[0-9,]+ ?(a\.?d\.?|c\.?e\.?)$/i, + parse: function parse(s, arr) { + var str = arr[0] || ''; //remove commas + + str = str.replace(/,/g, ''); + var year = parseInt(str.trim(), 10); + var d = new Date(); + var obj = { + year: year, + month: d.getMonth(), + date: d.getDate() + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s); + return s; + } + }, { + // '1992' + reg: /^[0-9]{4}( ?a\.?d\.?)?$/i, + parse: function parse(s, arr) { + var year = parseYear(arr[0]); + var d = new Date(); + var obj = { + year: year, + month: d.getMonth(), + date: d.getDate() + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s); + return s; + } + }]; + var strParse = strFmt; + var dates$1 = { + now: function now(s) { + s.epoch = Date.now(); + return s; + }, + tonight: function tonight(s) { + s.epoch = Date.now(); + s = s.hour(18); + return s; + }, + today: function today(s) { + s.epoch = Date.now(); + return s; + }, + tomorrow: function tomorrow(s) { + s.epoch = Date.now(); + s = s.add(1, 'day'); + s = s.startOf('day'); + return s; + }, + yesterday: function yesterday(s) { + s.epoch = Date.now(); + s = s.subtract(1, 'day'); + s = s.startOf('day'); + return s; + }, + christmas: function christmas(s) { + var year = new Date().getFullYear(); + s = s.set([year, 11, 25, 18, 0, 0]); // Dec 25 + + return s; + }, + 'new years': function newYears(s) { + var year = new Date().getFullYear(); + s = s.set([year, 11, 31, 18, 0, 0]); // Dec 31 + + return s; + } + }; + dates$1['new years eve'] = dates$1['new years']; + var namedDates = dates$1; //we have to actually parse these inputs ourselves + // - can't use built-in js parser ;( + //========================================= + // ISO Date "2015-03-25" + // Short Date "03/25/2015" or "2015/03/25" + // Long Date "Mar 25 2015" or "25 Mar 2015" + // Full Date "Wednesday March 25 2015" + //========================================= + //-- also - + // if the given epoch is really small, they've probably given seconds and not milliseconds + // anything below this number is likely (but not necessarily) a mistaken input. + // this may seem like an arbitrary number, but it's 'within jan 1970' + // this is only really ambiguous until 2054 or so + + var minimumEpoch = 2500000000; + var defaults = { + year: new Date().getFullYear(), + month: 0, + date: 1 + }; //support [2016, 03, 01] format + + var handleArray = function handleArray(s, arr) { + var order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond']; + + for (var _i4 = 0; _i4 < order.length; _i4++) { + var _num2 = arr[_i4] || defaults[order[_i4]] || 0; + + s = s[order[_i4]](_num2); + } + + return s; + }; //support {year:2016, month:3} format + + + var handleObject = function handleObject(s, obj) { + obj = Object.assign({}, defaults, obj); + var keys = Object.keys(obj); + + for (var _i5 = 0; _i5 < keys.length; _i5++) { + var unit = keys[_i5]; //make sure we have this method + + if (s[unit] === undefined || typeof s[unit] !== 'function') { + continue; + } //make sure the value is a number + + + if (obj[unit] === null || obj[unit] === undefined || obj[unit] === '') { + continue; + } + + var _num3 = obj[unit] || defaults[unit] || 0; + + s = s[unit](_num3); + } + + return s; + }; //find the epoch from different input styles + + + var parseInput = function parseInput(s, input, givenTz) { + //if we've been given a epoch number, it's easy + if (typeof input === 'number') { + if (input > 0 && input < minimumEpoch && s.silent === false) { + console.warn(' - Warning: You are setting the date to January 1970.'); + console.warn(' - did input seconds instead of milliseconds?'); + } + + s.epoch = input; + return s; + } //set tmp time + + + s.epoch = Date.now(); + + if (input === null || input === undefined) { + return s; //k, we're good. + } //support input of Date() object + + + if (fns.isDate(input) === true) { + s.epoch = input.getTime(); + return s; + } //support [2016, 03, 01] format + + + if (fns.isArray(input) === true) { + s = handleArray(s, input); + return s; + } //support {year:2016, month:3} format + + + if (fns.isObject(input) === true) { + //support spacetime object as input + if (input.epoch) { + s.epoch = input.epoch; + s.tz = input.tz; + return s; + } + + s = handleObject(s, input); + return s; + } //input as a string.. + + + if (typeof input !== 'string') { + return s; + } //little cleanup.. + + + input = input.replace(/\b(mon|tues|wed|wednes|thu|thurs|fri|sat|satur|sun)(day)?\b/i, ''); + input = input.replace(/,/g, ''); + input = input.replace(/ +/g, ' ').trim(); //try some known-words, like 'now' + + if (namedDates.hasOwnProperty(input) === true) { + s = namedDates[input](s); + return s; + } //try each text-parse template, use the first good result + + + for (var _i6 = 0; _i6 < strParse.length; _i6++) { + var m = input.match(strParse[_i6].reg); + + if (m) { + var res = strParse[_i6].parse(s, m, givenTz); + + if (res !== null) { + return res; + } + } + } + + if (s.silent === false) { + console.warn("Warning: couldn't parse date-string: '" + input + "'"); + } + + s.epoch = null; + return s; + }; + + var input = parseInput; + var shortDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; + var longDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']; + var days = { + "short": function short() { + return shortDays; + }, + "long": function long() { + return longDays; + }, + set: function set(i18n) { + shortDays = i18n["short"] || shortDays; + longDays = i18n["long"] || longDays; + } + }; // create the timezone offset part of an iso timestamp + // it's kind of nuts how involved this is + // "+01:00", "+0100", or simply "+01" + + var isoOffset = function isoOffset(s) { + var offset = s.timezone().current.offset; + var isNegative = offset < 0; + var minute = '00'; //handle 5.5 → '5:30' + + if (Math.abs(offset % 1) === 0.5) { + minute = '30'; + + if (offset >= 0) { + offset = Math.floor(offset); + } else { + offset = Math.ceil(offset); + } + } + + if (isNegative) { + //handle negative sign + offset *= -1; + offset = fns.zeroPad(offset, 2); + offset = '-' + offset; + } else { + offset = fns.zeroPad(offset, 2); + offset = '+' + offset; + } + + offset = offset + ':' + minute; //'Z' means 00 + + if (offset === '+00:00') { + offset = 'Z'; + } + + return offset; + }; + + var _offset = isoOffset; + var format = { + day: function day(s) { + return fns.titleCase(s.dayName()); + }, + 'day-short': function dayShort(s) { + return fns.titleCase(days["short"]()[s.day()]); + }, + 'day-number': function dayNumber(s) { + return s.day(); + }, + 'day-ordinal': function dayOrdinal(s) { + return fns.ordinal(s.day()); + }, + 'day-pad': function dayPad(s) { + return fns.zeroPad(s.day()); + }, + date: function date(s) { + return s.date(); + }, + 'date-ordinal': function dateOrdinal(s) { + return fns.ordinal(s.date()); + }, + 'date-pad': function datePad(s) { + return fns.zeroPad(s.date()); + }, + month: function month(s) { + return fns.titleCase(s.monthName()); + }, + 'month-short': function monthShort(s) { + return fns.titleCase(months["short"]()[s.month()]); + }, + 'month-number': function monthNumber(s) { + return s.month(); + }, + 'month-ordinal': function monthOrdinal(s) { + return fns.ordinal(s.month()); + }, + 'month-pad': function monthPad(s) { + return fns.zeroPad(s.month()); + }, + 'iso-month': function isoMonth(s) { + return fns.zeroPad(s.month() + 1); + }, + //1-based months + year: function year(s) { + var year = s.year(); + + if (year > 0) { + return year; + } + + year = Math.abs(year); + return year + ' BC'; + }, + 'year-short': function yearShort(s) { + var year = s.year(); + + if (year > 0) { + return "'".concat(String(s.year()).substr(2, 4)); + } + + year = Math.abs(year); + return year + ' BC'; + }, + 'iso-year': function isoYear(s) { + var year = s.year(); + var isNegative = year < 0; + var str = fns.zeroPad(Math.abs(year), 4); //0-padded + + if (isNegative) { + //negative years are for some reason 6-digits ('-00008') + str = fns.zeroPad(str, 6); + str = '-' + str; + } + + return str; + }, + time: function time(s) { + return s.time(); + }, + 'time-24': function time24(s) { + return "".concat(s.hour24(), ":").concat(fns.zeroPad(s.minute())); + }, + hour: function hour(s) { + return s.hour12(); + }, + 'hour-pad': function hourPad(s) { + return fns.zeroPad(s.hour12()); + }, + 'hour-24': function hour24(s) { + return s.hour24(); + }, + 'hour-24-pad': function hour24Pad(s) { + return fns.zeroPad(s.hour24()); + }, + minute: function minute(s) { + return s.minute(); + }, + 'minute-pad': function minutePad(s) { + return fns.zeroPad(s.minute()); + }, + second: function second(s) { + return s.second(); + }, + 'second-pad': function secondPad(s) { + return fns.zeroPad(s.second()); + }, + ampm: function ampm(s) { + return s.ampm(); + }, + quarter: function quarter(s) { + return 'Q' + s.quarter(); + }, + season: function season(s) { + return s.season(); + }, + era: function era(s) { + return s.era(); + }, + json: function json(s) { + return s.json(); + }, + timezone: function timezone(s) { + return s.timezone().name; + }, + offset: function offset(s) { + return _offset(s); + }, + numeric: function numeric(s) { + return "".concat(s.year(), "/").concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date())); + }, + // yyyy/mm/dd + 'numeric-us': function numericUs(s) { + return "".concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date()), "/").concat(s.year()); + }, + // mm/dd/yyyy + 'numeric-uk': function numericUk(s) { + return "".concat(fns.zeroPad(s.date()), "/").concat(fns.zeroPad(s.month() + 1), "/").concat(s.year()); + }, + //dd/mm/yyyy + 'mm/dd': function mmDd(s) { + return "".concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date())); + }, + //mm/dd + // ... https://en.wikipedia.org/wiki/ISO_8601 ;((( + iso: function iso(s) { + var year = s.format('iso-year'); + var month = fns.zeroPad(s.month() + 1); //1-based months + + var date = fns.zeroPad(s.date()); + var hour = fns.zeroPad(s.h24()); + var minute = fns.zeroPad(s.minute()); + var second = fns.zeroPad(s.second()); + var ms = fns.zeroPad(s.millisecond(), 3); + + var offset = _offset(s); + + return "".concat(year, "-").concat(month, "-").concat(date, "T").concat(hour, ":").concat(minute, ":").concat(second, ".").concat(ms).concat(offset); //2018-03-09T08:50:00.000-05:00 + }, + 'iso-short': function isoShort(s) { + var month = fns.zeroPad(s.month() + 1); //1-based months + + var date = fns.zeroPad(s.date()); + return "".concat(s.year(), "-").concat(month, "-").concat(date); //2017-02-15 + }, + 'iso-utc': function isoUtc(s) { + return new Date(s.epoch).toISOString(); //2017-03-08T19:45:28.367Z + }, + //i made these up + nice: function nice(s) { + return "".concat(months["short"]()[s.month()], " ").concat(fns.ordinal(s.date()), ", ").concat(s.time()); + }, + 'nice-year': function niceYear(s) { + return "".concat(months["short"]()[s.month()], " ").concat(fns.ordinal(s.date()), ", ").concat(s.year()); + }, + 'nice-day': function niceDay(s) { + return "".concat(days["short"]()[s.day()], " ").concat(fns.titleCase(months["short"]()[s.month()]), " ").concat(fns.ordinal(s.date())); + }, + 'nice-full': function niceFull(s) { + return "".concat(s.dayName(), " ").concat(fns.titleCase(s.monthName()), " ").concat(fns.ordinal(s.date()), ", ").concat(s.time()); + } + }; //aliases + + var aliases = { + 'day-name': 'day', + 'month-name': 'month', + 'iso 8601': 'iso', + 'time-h24': 'time-24', + 'time-12': 'time', + 'time-h12': 'time', + tz: 'timezone', + 'day-num': 'day-number', + 'month-num': 'month-number', + 'month-iso': 'iso-month', + 'year-iso': 'iso-year', + 'nice-short': 'nice', + mdy: 'numeric-us', + dmy: 'numeric-uk', + ymd: 'numeric', + 'yyyy/mm/dd': 'numeric', + 'mm/dd/yyyy': 'numeric-us', + 'dd/mm/yyyy': 'numeric-us', + 'little-endian': 'numeric-uk', + 'big-endian': 'numeric', + 'day-nice': 'nice-day' + }; + Object.keys(aliases).forEach(function (k) { + return format[k] = format[aliases[k]]; + }); + + var printFormat = function printFormat(s) { + var str = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + + //don't print anything if it's an invalid date + if (s.isValid() !== true) { + return ''; + } //support .format('month') + + + if (format.hasOwnProperty(str)) { + var out = format[str](s) || ''; + + if (str !== 'json') { + out = String(out); + + if (str !== 'ampm') { + out = fns.titleCase(out); + } + } + + return out; + } //support '{hour}:{minute}' notation + + + if (str.indexOf('{') !== -1) { + var sections = /\{(.+?)\}/g; + str = str.replace(sections, function (_, fmt) { + fmt = fmt.toLowerCase().trim(); + + if (format.hasOwnProperty(fmt)) { + return String(format[fmt](s) || ''); + } + + return ''; + }); + return str; + } + + return s.format('iso-short'); + }; + + var format_1 = printFormat; + var pad = fns.zeroPad; + var formatTimezone = fns.formatTimezone; //parse this insane unix-time-templating thing, from the 19th century + //http://unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns + //time-symbols we support + + var mapping = { + G: function G(s) { + return s.era(); + }, + GG: function GG(s) { + return s.era(); + }, + GGG: function GGG(s) { + return s.era(); + }, + GGGG: function GGGG(s) { + return s.era() === 'AD' ? 'Anno Domini' : 'Before Christ'; + }, + //year + y: function y(s) { + return s.year(); + }, + yy: function yy(s) { + //last two chars + return parseInt(String(s.year()).substr(2, 4), 10); + }, + yyy: function yyy(s) { + return s.year(); + }, + yyyy: function yyyy(s) { + return s.year(); + }, + yyyyy: function yyyyy(s) { + return '0' + s.year(); + }, + // u: (s) => {},//extended non-gregorian years + //quarter + Q: function Q(s) { + return s.quarter(); + }, + QQ: function QQ(s) { + return s.quarter(); + }, + QQQ: function QQQ(s) { + return s.quarter(); + }, + QQQQ: function QQQQ(s) { + return s.quarter(); + }, + //month + M: function M(s) { + return s.month() + 1; + }, + MM: function MM(s) { + return pad(s.month() + 1); + }, + MMM: function MMM(s) { + return s.format('month-short'); + }, + MMMM: function MMMM(s) { + return s.format('month'); + }, + //week + w: function w(s) { + return s.week(); + }, + ww: function ww(s) { + return pad(s.week()); + }, + //week of month + // W: (s) => s.week(), + //date of month + d: function d(s) { + return s.date(); + }, + dd: function dd(s) { + return pad(s.date()); + }, + //date of year + D: function D(s) { + return s.dayOfYear(); + }, + DD: function DD(s) { + return pad(s.dayOfYear()); + }, + DDD: function DDD(s) { + return pad(s.dayOfYear(), 3); + }, + // F: (s) => {},//date of week in month + // g: (s) => {},//modified julian day + //day + E: function E(s) { + return s.format('day-short'); + }, + EE: function EE(s) { + return s.format('day-short'); + }, + EEE: function EEE(s) { + return s.format('day-short'); + }, + EEEE: function EEEE(s) { + return s.format('day'); + }, + EEEEE: function EEEEE(s) { + return s.format('day')[0]; + }, + e: function e(s) { + return s.day(); + }, + ee: function ee(s) { + return s.day(); + }, + eee: function eee(s) { + return s.format('day-short'); + }, + eeee: function eeee(s) { + return s.format('day'); + }, + eeeee: function eeeee(s) { + return s.format('day')[0]; + }, + //am/pm + a: function a(s) { + return s.ampm().toUpperCase(); + }, + aa: function aa(s) { + return s.ampm().toUpperCase(); + }, + aaa: function aaa(s) { + return s.ampm().toUpperCase(); + }, + aaaa: function aaaa(s) { + return s.ampm().toUpperCase(); + }, + //hour + h: function h(s) { + return s.h12(); + }, + hh: function hh(s) { + return pad(s.h12()); + }, + H: function H(s) { + return s.hour(); + }, + HH: function HH(s) { + return pad(s.hour()); + }, + // j: (s) => {},//weird hour format + m: function m(s) { + return s.minute(); + }, + mm: function mm(s) { + return pad(s.minute()); + }, + s: function s(_s) { + return _s.second(); + }, + ss: function ss(s) { + return pad(s.second()); + }, + //milliseconds in the day + A: function A(s) { + return s.epoch - s.startOf('day').epoch; + }, + //timezone + z: function z(s) { + return s.timezone().name; + }, + zz: function zz(s) { + return s.timezone().name; + }, + zzz: function zzz(s) { + return s.timezone().name; + }, + zzzz: function zzzz(s) { + return s.timezone().name; + }, + Z: function Z(s) { + return formatTimezone(s.timezone().current.offset); + }, + ZZ: function ZZ(s) { + return formatTimezone(s.timezone().current.offset); + }, + ZZZ: function ZZZ(s) { + return formatTimezone(s.timezone().current.offset); + }, + ZZZZ: function ZZZZ(s) { + return formatTimezone(s.timezone().current.offset, ':'); + } + }; + + var addAlias = function addAlias(_char, to, n) { + var name = _char; + var toName = to; + + for (var _i7 = 0; _i7 < n; _i7 += 1) { + mapping[name] = mapping[toName]; + name += _char; + toName += to; + } + }; + + addAlias('q', 'Q', 4); + addAlias('L', 'M', 4); + addAlias('Y', 'y', 4); + addAlias('c', 'e', 4); + addAlias('k', 'H', 2); + addAlias('K', 'h', 2); + addAlias('S', 's', 2); + addAlias('v', 'z', 4); + addAlias('V', 'Z', 4); + + var unixFmt = function unixFmt(s, str) { + var chars = str.split(''); //combine consecutive chars, like 'yyyy' as one. + + var arr = [chars[0]]; + var quoteOn = false; + + for (var _i8 = 1; _i8 < chars.length; _i8 += 1) { + //support quoted substrings + if (chars[_i8] === "'") { + quoteOn = !quoteOn; //support '', meaning one tick + + if (quoteOn === true && chars[_i8 + 1] && chars[_i8 + 1] === "'") { + quoteOn = true; + } else { + continue; + } + } //merge it with the last one + + + if (quoteOn === true || chars[_i8] === arr[arr.length - 1][0]) { + arr[arr.length - 1] += chars[_i8]; + } else { + arr.push(chars[_i8]); + } + } + + return arr.reduce(function (txt, c) { + if (mapping[c] !== undefined) { + txt += mapping[c](s) || ''; + } else { + txt += c; + } + + return txt; + }, ''); + }; + + var unixFmt_1 = unixFmt; + var units$1 = ['year', 'season', 'quarter', 'month', 'week', 'day', 'quarterHour', 'hour', 'minute']; + + var doUnit = function doUnit(s, k) { + var start = s.clone().startOf(k); + var end = s.clone().endOf(k); + var duration = end.epoch - start.epoch; + var percent = (s.epoch - start.epoch) / duration; + return parseFloat(percent.toFixed(2)); + }; //how far it is along, from 0-1 + + + var progress = function progress(s, unit) { + if (unit) { + unit = fns.normalize(unit); + return doUnit(s, unit); + } + + var obj = {}; + units$1.forEach(function (k) { + obj[k] = doUnit(s, k); + }); + return obj; + }; + + var progress_1 = progress; //round to either current, or +1 of this unit + + var nearest = function nearest(s, unit) { + //how far have we gone? + var prog = s.progress(); + unit = fns.normalize(unit); //fix camel-case for this one + + if (unit === 'quarterhour') { + unit = 'quarterHour'; + } + + if (prog[unit] !== undefined) { + // go forward one? + if (prog[unit] > 0.5) { + s = s.add(1, unit); + } // go to start + + + s = s.startOf(unit); + } else if (s.silent === false) { + console.warn("no known unit '" + unit + "'"); + } + + return s; + }; + + var nearest_1 = nearest; //increment until dates are the same + + var climb = function climb(a, b, unit) { + var i = 0; + a = a.clone(); + + while (a.isBefore(b)) { + //do proper, expensive increment to catch all-the-tricks + a = a.add(1, unit); + i += 1; + } //oops, we went too-far.. + + + if (a.isAfter(b, unit)) { + i -= 1; + } + + return i; + }; // do a thurough +=1 on the unit, until they match + // for speed-reasons, only used on day, month, week. + + + var diffOne = function diffOne(a, b, unit) { + if (a.isBefore(b)) { + return climb(a, b, unit); + } else { + return climb(b, a, unit) * -1; //reverse it + } + }; + + var one = diffOne; // don't do anything too fancy here. + // 2020 - 2019 may be 1 year, or 0 years + // - '1 year difference' means 366 days during a leap year + + var fastYear = function fastYear(a, b) { + var years = b.year() - a.year(); // should we decrement it by 1? + + a = a.year(b.year()); + + if (a.isAfter(b)) { + years -= 1; + } + + return years; + }; // use a waterfall-method for computing a diff of any 'pre-knowable' units + // compute years, then compute months, etc.. + // ... then ms-math for any very-small units + + + var diff = function diff(a, b) { + // an hour is always the same # of milliseconds + // so these units can be 'pre-calculated' + var msDiff = b.epoch - a.epoch; + var obj = { + milliseconds: msDiff, + seconds: parseInt(msDiff / 1000, 10) + }; + obj.minutes = parseInt(obj.seconds / 60, 10); + obj.hours = parseInt(obj.minutes / 60, 10); //do the year + + var tmp = a.clone(); + obj.years = fastYear(tmp, b); + tmp = a.add(obj.years, 'year'); //there's always 12 months in a year... + + obj.months = obj.years * 12; + tmp = a.add(obj.months, 'month'); + obj.months += one(tmp, b, 'month'); // there's always atleast 52 weeks in a year.. + // (month * 4) isn't as close + + obj.weeks = obj.years * 52; + tmp = a.add(obj.weeks, 'week'); + obj.weeks += one(tmp, b, 'week'); // there's always atleast 7 days in a week + + obj.days = obj.weeks * 7; + tmp = a.add(obj.days, 'day'); + obj.days += one(tmp, b, 'day'); + return obj; + }; + + var waterfall = diff; + + var reverseDiff = function reverseDiff(obj) { + Object.keys(obj).forEach(function (k) { + obj[k] *= -1; + }); + return obj; + }; // this method counts a total # of each unit, between a, b. + // '1 month' means 28 days in february + // '1 year' means 366 days in a leap year + + + var main = function main(a, b, unit) { + b = fns.beADate(b, a); //reverse values, if necessary + + var reversed = false; + + if (a.isAfter(b)) { + var tmp = a; + a = b; + b = tmp; + reversed = true; + } //compute them all (i know!) + + + var obj = waterfall(a, b); + + if (reversed) { + obj = reverseDiff(obj); + } //return just the requested unit + + + if (unit) { + //make sure it's plural-form + unit = fns.normalize(unit); + + if (/s$/.test(unit) !== true) { + unit += 's'; + } + + if (unit === 'dates') { + unit = 'days'; + } + + return obj[unit]; + } + + return obj; + }; + + var diff$1 = main; //by spencermountain + Shaun Grady + //our conceptual 'break-points' for each unit + + var qualifiers = { + months: { + almost: 10, + over: 4 + }, + days: { + almost: 25, + over: 10 + }, + hours: { + almost: 20, + over: 8 + }, + minutes: { + almost: 50, + over: 20 + }, + seconds: { + almost: 50, + over: 20 + } + }; //get number of hours/minutes... between the two dates + + function getDiff(a, b) { + var isBefore = a.isBefore(b); + var later = isBefore ? b : a; + var earlier = isBefore ? a : b; + earlier = earlier.clone(); + var diff = { + years: 0, + months: 0, + days: 0, + hours: 0, + minutes: 0, + seconds: 0 + }; + Object.keys(diff).forEach(function (unit) { + if (earlier.isSame(later, unit)) { + return; + } + + var max = earlier.diff(later, unit); + earlier = earlier.add(max, unit); + diff[unit] = max; + }); //reverse it, if necessary + + if (isBefore) { + Object.keys(diff).forEach(function (u) { + if (diff[u] !== 0) { + diff[u] *= -1; + } + }); + } + + return diff; + } // Expects a plural unit arg + + + function pluralize(value, unit) { + if (value === 1) { + unit = unit.slice(0, -1); + } + + return value + ' ' + unit; + } //create the human-readable diff between the two dates + + + var since = function since(start, end) { + end = fns.beADate(end, start); + var diff = getDiff(start, end); + var isNow = Object.keys(diff).every(function (u) { + return !diff[u]; + }); + + if (isNow === true) { + return { + diff: diff, + rounded: 'now', + qualified: 'now', + precise: 'now' + }; + } + + var rounded; + var qualified; + var precise; + var englishValues = []; //go through each value and create its text-representation + + Object.keys(diff).forEach(function (unit, i, units) { + var value = Math.abs(diff[unit]); + + if (value === 0) { + return; + } + + var englishValue = pluralize(value, unit); + englishValues.push(englishValue); + + if (!rounded) { + rounded = qualified = englishValue; + + if (i > 4) { + return; + } //is it a 'almost' something, etc? + + + var nextUnit = units[i + 1]; + var nextValue = Math.abs(diff[nextUnit]); + + if (nextValue > qualifiers[nextUnit].almost) { + rounded = pluralize(value + 1, unit); + qualified = 'almost ' + rounded; + } else if (nextValue > qualifiers[nextUnit].over) qualified = 'over ' + englishValue; + } + }); //make them into a string + + precise = englishValues.splice(0, 2).join(', '); //handle before/after logic + + if (start.isAfter(end) === true) { + rounded += ' ago'; + qualified += ' ago'; + precise += ' ago'; + } else { + rounded = 'in ' + rounded; + qualified = 'in ' + qualified; + precise = 'in ' + precise; + } + + return { + diff: diff, + rounded: rounded, + qualified: qualified, + precise: precise + }; + }; + + var since_1 = since; //https://www.timeanddate.com/calendar/aboutseasons.html + // Spring - from March 1 to May 31; + // Summer - from June 1 to August 31; + // Fall (autumn) - from September 1 to November 30; and, + // Winter - from December 1 to February 28 (February 29 in a leap year). + + var seasons$1 = { + north: [['spring', 2, 1], //spring march 1 + ['summer', 5, 1], //june 1 + ['fall', 8, 1], //sept 1 + ['autumn', 8, 1], //sept 1 + ['winter', 11, 1] //dec 1 + ], + south: [['fall', 2, 1], //march 1 + ['autumn', 2, 1], //march 1 + ['winter', 5, 1], //june 1 + ['spring', 8, 1], //sept 1 + ['summer', 11, 1] //dec 1 + ] + }; + var quarters = [null, [0, 1], //jan 1 + [3, 1], //apr 1 + [6, 1], //july 1 + [9, 1] //oct 1 + ]; + var units$2 = { + minute: function minute(s) { + walk_1(s, { + second: 0, + millisecond: 0 + }); + return s; + }, + quarterhour: function quarterhour(s) { + var minute = s.minutes(); + + if (minute >= 45) { + s = s.minutes(45); + } else if (minute >= 30) { + s = s.minutes(30); + } else if (minute >= 15) { + s = s.minutes(15); + } else { + s = s.minutes(0); + } + + walk_1(s, { + second: 0, + millisecond: 0 + }); + return s; + }, + hour: function hour(s) { + walk_1(s, { + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + day: function day(s) { + walk_1(s, { + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + week: function week(s) { + var original = s.clone(); + s = s.day(s._weekStart); //monday + + if (s.isAfter(original)) { + s = s.subtract(1, 'week'); + } + + walk_1(s, { + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + month: function month(s) { + walk_1(s, { + date: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + quarter: function quarter(s) { + var q = s.quarter(); + + if (quarters[q]) { + walk_1(s, { + month: quarters[q][0], + date: quarters[q][1], + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + } + + return s; + }, + season: function season(s) { + var current = s.season(); + var hem = 'north'; + + if (s.hemisphere() === 'South') { + hem = 'south'; + } + + for (var _i9 = 0; _i9 < seasons$1[hem].length; _i9++) { + if (seasons$1[hem][_i9][0] === current) { + //winter goes between years + var year = s.year(); + + if (current === 'winter' && s.month() < 3) { + year -= 1; + } + + walk_1(s, { + year: year, + month: seasons$1[hem][_i9][1], + date: seasons$1[hem][_i9][2], + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + } + } + + return s; + }, + year: function year(s) { + walk_1(s, { + month: 0, + date: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + decade: function decade(s) { + s = s.startOf('year'); + var year = s.year(); + var decade = parseInt(year / 10, 10) * 10; + s = s.year(decade); + return s; + }, + century: function century(s) { + s = s.startOf('year'); + var year = s.year(); // near 0AD goes '-1 | +1' + + var decade = parseInt(year / 100, 10) * 100; + s = s.year(decade); + return s; + } + }; + units$2.date = units$2.day; + + var startOf = function startOf(a, unit) { + var s = a.clone(); + unit = fns.normalize(unit); + + if (units$2[unit]) { + return units$2[unit](s); + } + + if (unit === 'summer' || unit === 'winter') { + s = s.season(unit); + return units$2.season(s); + } + + return s; + }; //piggy-backs off startOf + + + var endOf = function endOf(a, unit) { + var s = a.clone(); + unit = fns.normalize(unit); + + if (units$2[unit]) { + s = units$2[unit](s); + s = s.add(1, unit); + s = s.subtract(1, 'milliseconds'); + return s; + } + + return s; + }; + + var startOf_1 = { + startOf: startOf, + endOf: endOf + }; //is it 'wednesday'? + + var isDay = function isDay(unit) { + if (days["short"]().find(function (s) { + return s === unit; + })) { + return true; + } + + if (days["long"]().find(function (s) { + return s === unit; + })) { + return true; + } + + return false; + }; // return a list of the weeks/months/days between a -> b + // returns spacetime objects in the timezone of the input + + + var every = function every(start) { + var unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var end = arguments.length > 2 ? arguments[2] : undefined; + + if (!unit || !end) { + return []; + } //cleanup unit param + + + unit = fns.normalize(unit); //cleanup to param + + end = start.clone().set(end); //swap them, if they're backwards + + if (start.isAfter(end)) { + var tmp = start; + start = end; + end = tmp; + } //support 'every wednesday' + + + var d = start.clone(); + + if (isDay(unit)) { + d = d.next(unit); + unit = 'week'; + } else { + d = d.next(unit); + } //okay, actually start doing it + + + var result = []; + + while (d.isBefore(end)) { + result.push(d); + d = d.add(1, unit); + } + + return result; + }; + + var every_1 = every; + + var parseDst = function parseDst(dst) { + if (!dst) { + return []; + } + + return dst.split('->'); + }; + + var titleCase = function titleCase(str) { + str = str[0].toUpperCase() + str.substr(1); + str = str.replace(/\/gmt/, '/GMT'); + str = str.replace(/[\/_]([a-z])/gi, function (s) { + return s.toUpperCase(); + }); + return str; + }; //get metadata about this timezone + + + var timezone = function timezone(s) { + var zones = s.timezones; + var tz = s.tz; + + if (zones.hasOwnProperty(tz) === false) { + tz = find(s.tz, zones); + } + + if (tz === null) { + if (s.silent === false) { + console.warn("Warn: could not find given or local timezone - '" + s.tz + "'"); + } + + return { + current: { + epochShift: 0 + } + }; + } + + var found = zones[tz]; + var result = { + name: titleCase(tz), + hasDst: Boolean(found.dst), + default_offset: found.offset, + //do north-hemisphere version as default (sorry!) + hemisphere: found.hem === 's' ? 'South' : 'North', + current: {} + }; + + if (result.hasDst) { + var arr = parseDst(found.dst); + result.change = { + start: arr[0], + back: arr[1] + }; + } //find the offsets for summer/winter times + //(these variable names are north-centric) + + + var summer = found.offset; // (july) + + var winter = summer; // (january) assume it's the same for now + + if (result.hasDst === true) { + if (result.hemisphere === 'North') { + winter = summer - 1; + } else { + //southern hemisphere + winter = found.offset + 1; + } + } //find out which offset to use right now + //use 'summer' time july-time + + + if (result.hasDst === false) { + result.current.offset = summer; + result.current.isDST = false; + } else if (summerTime(s.epoch, result.change.start, result.change.back, summer) === true) { + result.current.offset = summer; + result.current.isDST = result.hemisphere === 'North'; //dst 'on' in winter in north + } else { + //use 'winter' january-time + result.current.offset = winter; + result.current.isDST = result.hemisphere === 'South'; //dst 'on' in summer in south + } + + return result; + }; + + var timezone_1 = timezone; + var units$3 = ['century', 'decade', 'year', 'month', 'date', 'day', 'hour', 'minute', 'second', 'millisecond']; //the spacetime instance methods (also, the API) + + var methods$1 = { + set: function set(input$1, tz) { + var s = this.clone(); + s = input(s, input$1); + + if (tz) { + this.tz = find(tz); + } + + return s; + }, + timezone: function timezone() { + return timezone_1(this); + }, + isDST: function isDST() { + return timezone_1(this).current.isDST; + }, + hasDST: function hasDST() { + return timezone_1(this).hasDst; + }, + offset: function offset() { + return timezone_1(this).current.offset * 60; + }, + hemisphere: function hemisphere() { + return timezone_1(this).hemisphere; + }, + format: function format(fmt) { + return format_1(this, fmt); + }, + unixFmt: function unixFmt(fmt) { + return unixFmt_1(this, fmt); + }, + startOf: function startOf(unit) { + return startOf_1.startOf(this, unit); + }, + endOf: function endOf(unit) { + return startOf_1.endOf(this, unit); + }, + leapYear: function leapYear() { + var year = this.year(); + return fns.isLeapYear(year); + }, + progress: function progress(unit) { + return progress_1(this, unit); + }, + nearest: function nearest(unit) { + return nearest_1(this, unit); + }, + diff: function diff(d, unit) { + return diff$1(this, d, unit); + }, + since: function since(d) { + if (!d) { + d = this.clone().set(); + } + + return since_1(this, d); + }, + next: function next(unit) { + var s = this.add(1, unit); + return s.startOf(unit); + }, + //the start of the previous year/week/century + last: function last(unit) { + var s = this.subtract(1, unit); + return s.startOf(unit); + }, + isValid: function isValid() { + //null/undefined epochs + if (!this.epoch && this.epoch !== 0) { + return false; + } + + return !isNaN(this.d.getTime()); + }, + //travel to this timezone + "goto": function goto(tz) { + var s = this.clone(); + s.tz = find(tz, s.timezones); //science! + + return s; + }, + //get each week/month/day between a -> b + every: function every(unit, to) { + return every_1(this, unit, to); + }, + isAwake: function isAwake() { + var hour = this.hour(); //10pm -> 8am + + if (hour < 8 || hour > 22) { + return false; + } + + return true; + }, + isAsleep: function isAsleep() { + return !this.isAwake(); + }, + //pretty-printing + log: function log() { + console.log(''); + console.log(format_1(this, 'nice-short')); + return this; + }, + logYear: function logYear() { + console.log(''); + console.log(format_1(this, 'full-short')); + return this; + }, + json: function json() { + var _this = this; + + return units$3.reduce(function (h, unit) { + h[unit] = _this[unit](); + return h; + }, {}); + }, + debug: function debug() { + var tz = this.timezone(); + var date = this.format('MM') + ' ' + this.format('date-ordinal') + ' ' + this.year(); + date += '\n - ' + this.format('time'); + console.log('\n\n', date + '\n - ' + tz.name + ' (' + tz.current.offset + ')'); + return this; + }, + //alias of 'since' but opposite - like moment.js + from: function from(d) { + d = this.clone().set(d); + return d.since(this); + }, + fromNow: function fromNow() { + var d = this.clone().set(Date.now()); + return d.since(this); + }, + weekStart: function weekStart(input) { + //accept a number directly + if (typeof input === 'number') { + this._weekStart = input; + return this; + } + + if (typeof input === 'string') { + // accept 'wednesday' + input = input.toLowerCase().trim(); + + var _num4 = days["short"]().indexOf(input); + + if (_num4 === -1) { + _num4 = days["long"]().indexOf(input); + } + + if (_num4 === -1) { + _num4 = 1; //go back to default + } + + this._weekStart = _num4; + } else { + console.warn('Spacetime Error: Cannot understand .weekStart() input:', input); + } + + return this; + } + }; // aliases + + methods$1.inDST = methods$1.isDST; + methods$1.round = methods$1.nearest; + methods$1.each = methods$1.every; + var methods_1 = methods$1; // javascript setX methods like setDate() can't be used because of the local bias + //these methods wrap around them. + + var validate = function validate(n) { + //handle number as a string + if (typeof n === 'string') { + n = parseInt(n, 10); + } + + return n; + }; + + var order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond']; //reduce hostile micro-changes when moving dates by millisecond + + var confirm = function confirm(s, tmp, unit) { + var n = order.indexOf(unit); + var arr = order.slice(n, order.length); + + for (var _i10 = 0; _i10 < arr.length; _i10++) { + var want = tmp[arr[_i10]](); + + s[arr[_i10]](want); + } + + return s; + }; + + var set = { + milliseconds: function milliseconds(s, n) { + n = validate(n); + var current = s.millisecond(); + var diff = current - n; //milliseconds to shift by + + return s.epoch - diff; + }, + seconds: function seconds(s, n) { + n = validate(n); + var diff = s.second() - n; + var shift = diff * milliseconds.second; + return s.epoch - shift; + }, + minutes: function minutes(s, n) { + n = validate(n); + var old = s.clone(); + var diff = s.minute() - n; + var shift = diff * milliseconds.minute; + s.epoch -= shift; + confirm(s, old, 'second'); + return s.epoch; + }, + hours: function hours(s, n) { + n = validate(n); + + if (n >= 24) { + n = 24; + } else if (n < 0) { + n = 0; + } + + var old = s.clone(); + var diff = s.hour() - n; + var shift = diff * milliseconds.hour; + s.epoch -= shift; + walk_1(s, { + hour: n + }); + confirm(s, old, 'minute'); + return s.epoch; + }, + //support setting time by '4:25pm' - this isn't very-well developed.. + time: function time(s, str) { + var m = str.match(/([0-9]{1,2}):([0-9]{1,2})(am|pm)?/); + + if (!m) { + //fallback to support just '2am' + m = str.match(/([0-9]{1,2})(am|pm)/); + + if (!m) { + return s.epoch; + } + + m.splice(2, 0, '0'); //add implicit 0 minutes + } + + var h24 = false; + var hour = parseInt(m[1], 10); + var minute = parseInt(m[2], 10); + + if (hour > 12) { + h24 = true; + } //make the hour into proper 24h time + + + if (h24 === false) { + if (m[3] === 'am' && hour === 12) { + //12am is midnight + hour = 0; + } + + if (m[3] === 'pm' && hour < 12) { + //12pm is noon + hour += 12; + } + } + + s = s.hour(hour); + s = s.minute(minute); + s = s.second(0); + s = s.millisecond(0); + return s.epoch; + }, + date: function date(s, n) { + n = validate(n); //avoid setting february 31st + + if (n > 28) { + var max = monthLengths_1[s.month()]; + + if (n > max) { + n = max; + } + } //avoid setting < 0 + + + if (n <= 0) { + n = 1; + } + + walk_1(s, { + date: n + }); + return s.epoch; + }, + //this one's tricky + month: function month(s, n) { + if (typeof n === 'string') { + n = months.mapping()[n.toLowerCase()]; + } + + n = validate(n); //don't go past december + + if (n >= 12) { + n = 11; + } + + if (n <= 0) { + n = 0; + } + + var date = s.date(); //there's no 30th of february, etc. + + if (date > monthLengths_1[n]) { + //make it as close as we can.. + date = monthLengths_1[n]; + } + + walk_1(s, { + month: n, + date: date + }); + return s.epoch; + }, + year: function year(s, n) { + n = validate(n); + walk_1(s, { + year: n + }); + return s.epoch; + }, + dayOfYear: function dayOfYear(s, n) { + n = validate(n); + var old = s.clone(); + n -= 1; //days are 1-based + + if (n <= 0) { + n = 0; + } else if (n >= 365) { + n = 364; + } + + s = s.startOf('year'); + s = s.add(n, 'day'); + confirm(s, old, 'hour'); + return s.epoch; + } + }; + var methods$1$1 = { + millisecond: function millisecond(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.milliseconds(s, num); + return s; + } + + return this.d.getMilliseconds(); + }, + second: function second(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.seconds(s, num); + return s; + } + + return this.d.getSeconds(); + }, + minute: function minute(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.minutes(s, num); + return s; + } + + return this.d.getMinutes(); + }, + hour: function hour(num) { + var d = this.d; + + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.hours(s, num); + return s; + } + + return d.getHours(); + }, + //'3:30' is 3.5 + hourFloat: function hourFloat(num) { + if (num !== undefined) { + var s = this.clone(); + + var _minute = num % 1; + + _minute = _minute * 60; + + var _hour = parseInt(num, 10); + + s.epoch = set.hours(s, _hour); + s.epoch = set.minutes(s, _minute); + return s; + } + + var d = this.d; + var hour = d.getHours(); + var minute = d.getMinutes(); + minute = minute / 60; + return hour + minute; + }, + // hour in 12h format + hour12: function hour12(str) { + var d = this.d; + + if (str !== undefined) { + var s = this.clone(); + str = '' + str; + var m = str.match(/^([0-9]+)(am|pm)$/); + + if (m) { + var hour = parseInt(m[1], 10); + + if (m[2] === 'pm') { + hour += 12; + } + + s.epoch = set.hours(s, hour); + } + + return s; + } //get the hour + + + var hour12 = d.getHours(); + + if (hour12 > 12) { + hour12 = hour12 - 12; + } + + if (hour12 === 0) { + hour12 = 12; + } + + return hour12; + }, + //some ambiguity here with 12/24h + time: function time(str) { + if (str !== undefined) { + var s = this.clone(); + s.epoch = set.time(s, str); + return s; + } + + return "".concat(this.h12(), ":").concat(fns.zeroPad(this.minute())).concat(this.ampm()); + }, + // either 'am' or 'pm' + ampm: function ampm(input) { + var which = 'am'; + var hour = this.hour(); + + if (hour >= 12) { + which = 'pm'; + } + + if (typeof input !== 'string') { + return which; + } //okay, we're doing a setter + + + var s = this.clone(); + input = input.toLowerCase().trim(); //ampm should never change the day + // - so use `.hour(n)` instead of `.minus(12,'hour')` + + if (hour >= 12 && input === 'am') { + //noon is 12pm + hour -= 12; + return s.hour(hour); + } + + if (hour < 12 && input === 'pm') { + hour += 12; + return s.hour(hour); + } + + return s; + }, + //some hard-coded times of day, like 'noon' + dayTime: function dayTime(str) { + if (str !== undefined) { + var times = { + morning: '7:00am', + breakfast: '7:00am', + noon: '12:00am', + lunch: '12:00pm', + afternoon: '2:00pm', + evening: '6:00pm', + dinner: '6:00pm', + night: '11:00pm', + midnight: '23:59pm' + }; + var s = this.clone(); + str = str || ''; + str = str.toLowerCase(); + + if (times.hasOwnProperty(str) === true) { + s = s.time(times[str]); + } + + return s; + } + + var h = this.hour(); + + if (h < 6) { + return 'night'; + } + + if (h < 12) { + //until noon + return 'morning'; + } + + if (h < 17) { + //until 5pm + return 'afternoon'; + } + + if (h < 22) { + //until 10pm + return 'evening'; + } + + return 'night'; + }, + //parse a proper iso string + iso: function iso(num) { + if (num !== undefined) { + return this.set(num); + } + + return this.format('iso'); + } + }; + var _01Time = methods$1$1; + var methods$2 = { + // # day in the month + date: function date(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.date(s, num); + return s; + } + + return this.d.getDate(); + }, + //like 'wednesday' (hard!) + day: function day(input) { + if (input === undefined) { + return this.d.getDay(); + } + + var original = this.clone(); + var want = input; // accept 'wednesday' + + if (typeof input === 'string') { + input = input.toLowerCase(); + want = days["short"]().indexOf(input); + + if (want === -1) { + want = days["long"]().indexOf(input); + } + } //move approx + + + var day = this.d.getDay(); + var diff = day - want; + var s = this.subtract(diff * 24, 'hours'); //tighten it back up + + walk_1(s, { + hour: original.hour(), + minute: original.minute(), + second: original.second() + }); + return s; + }, + //these are helpful name-wrappers + dayName: function dayName(input) { + if (input === undefined) { + return days["long"]()[this.day()]; + } + + var s = this.clone(); + s = s.day(input); + return s; + }, + //either name or number + month: function month(input) { + if (input !== undefined) { + var s = this.clone(); + s.epoch = set.month(s, input); + return s; + } + + return this.d.getMonth(); + } + }; + var _02Date = methods$2; + + var clearMinutes = function clearMinutes(s) { + s = s.minute(0); + s = s.second(0); + s = s.millisecond(1); + return s; + }; + + var methods$3 = { + // day 0-366 + dayOfYear: function dayOfYear(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.dayOfYear(s, num); + return s; + } //days since newyears - jan 1st is 1, jan 2nd is 2... + + + var sum = 0; + var month = this.d.getMonth(); + var tmp; //count the num days in each month + + for (var _i11 = 1; _i11 <= month; _i11++) { + tmp = new Date(); + tmp.setDate(1); + tmp.setFullYear(this.d.getFullYear()); //the year matters, because leap-years + + tmp.setHours(1); + tmp.setMinutes(1); + tmp.setMonth(_i11); + tmp.setHours(-2); //the last day of the month + + sum += tmp.getDate(); + } + + return sum + this.d.getDate(); + }, + //since the start of the year + week: function week(num) { + // week-setter + if (num !== undefined) { + var s = this.clone(); + s = s.month(0); + s = s.date(1); + s = s.day('monday'); + s = clearMinutes(s); //don't go into last-year + + if (s.monthName() === 'december') { + s = s.add(1, 'week'); + } + + num -= 1; //1-based + + s = s.add(num, 'weeks'); + return s; + } //find-out which week it is + + + var tmp = this.clone(); + tmp = tmp.month(0); + tmp = tmp.date(1); + tmp = clearMinutes(tmp); + tmp = tmp.day('monday'); //don't go into last-year + + if (tmp.monthName() === 'december') { + tmp = tmp.add(1, 'week'); + } // is first monday the 1st? + + + var toAdd = 1; + + if (tmp.date() === 1) { + toAdd = 0; + } + + tmp = tmp.minus(1, 'second'); + var thisOne = this.epoch; //if the week technically hasn't started yet + + if (tmp.epoch > thisOne) { + return 1; + } //speed it up, if we can + + + var i = 0; + var skipWeeks = this.month() * 4; + tmp.epoch += milliseconds.week * skipWeeks; + i += skipWeeks; + + for (; i < 52; i++) { + if (tmp.epoch > thisOne) { + return i + toAdd; + } + + tmp = tmp.add(1, 'week'); + } + + return 52; + }, + //'january' + monthName: function monthName(input) { + if (input === undefined) { + return months["long"]()[this.month()]; + } + + var s = this.clone(); + s = s.month(input); + return s; + }, + //q1, q2, q3, q4 + quarter: function quarter(num) { + if (num !== undefined) { + if (typeof num === 'string') { + num = num.replace(/^q/i, ''); + num = parseInt(num, 10); + } + + if (quarters[num]) { + var s = this.clone(); + var _month = quarters[num][0]; + s = s.month(_month); + s = s.date(1); + s = s.startOf('day'); + return s; + } + } + + var month = this.d.getMonth(); + + for (var _i12 = 1; _i12 < quarters.length; _i12++) { + if (month < quarters[_i12][0]) { + return _i12 - 1; + } + } + + return 4; + }, + //spring, summer, winter, fall + season: function season(input) { + var hem = 'north'; + + if (this.hemisphere() === 'South') { + hem = 'south'; + } + + if (input !== undefined) { + var s = this.clone(); + + for (var _i13 = 0; _i13 < seasons$1[hem].length; _i13++) { + if (input === seasons$1[hem][_i13][0]) { + s = s.month(seasons$1[hem][_i13][1]); + s = s.date(1); + s = s.startOf('day'); + } + } + + return s; + } + + var month = this.d.getMonth(); + + for (var _i14 = 0; _i14 < seasons$1[hem].length - 1; _i14++) { + if (month >= seasons$1[hem][_i14][1] && month < seasons$1[hem][_i14 + 1][1]) { + return seasons$1[hem][_i14][0]; + } + } + + return 'winter'; + }, + //the year number + year: function year(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.year(s, num); + return s; + } + + return this.d.getFullYear(); + }, + //bc/ad years + era: function era(str) { + if (str !== undefined) { + var s = this.clone(); + str = str.toLowerCase(); //TODO: there is no year-0AD i think. may have off-by-1 error here + + var year = s.d.getFullYear(); //make '1992' into 1992bc.. + + if (str === 'bc' && year > 0) { + s.epoch = set.year(s, year * -1); + } //make '1992bc' into '1992' + + + if (str === 'ad' && year < 0) { + s.epoch = set.year(s, year * -1); + } + + return s; + } + + if (this.d.getFullYear() < 0) { + return 'BC'; + } + + return 'AD'; + }, + // 2019 -> 2010 + decade: function decade(input) { + if (input !== undefined) { + input = String(input); + input = input.replace(/([0-9])'?s$/, '$1'); //1950's + + input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals + + if (!input) { + console.warn('Spacetime: Invalid decade input'); + return this; + } // assume 20th century?? for '70s'. + + + if (input.length === 2 && /[0-9][0-9]/.test(input)) { + input = '19' + input; + } + + var year = Number(input); + + if (isNaN(year)) { + return this; + } // round it down to the decade + + + year = Math.floor(year / 10) * 10; + return this.year(year); //.startOf('decade') + } + + return this.startOf('decade').year(); + }, + // 1950 -> 19+1 + century: function century(input) { + if (input !== undefined) { + if (typeof input === 'string') { + input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals + + input = input.replace(/([0-9]+) ?(b\.?c\.?|a\.?d\.?)/i, function (a, b, c) { + if (c.match(/b\.?c\.?/i)) { + b = '-' + b; + } + + return b; + }); + input = input.replace(/c$/, ''); //20thC + } + + var year = Number(input); + + if (isNaN(input)) { + console.warn('Spacetime: Invalid century input'); + return this; + } // there is no century 0 + + + if (year === 0) { + year = 1; + } + + if (year >= 0) { + year = (year - 1) * 100; + } else { + year = (year + 1) * 100; + } + + return this.year(year); + } // century getter + + + var num = this.startOf('century').year(); + num = Math.floor(num / 100); + + if (num < 0) { + return num - 1; + } + + return num + 1; + }, + // 2019 -> 2+1 + millenium: function millenium(input) { + if (input !== undefined) { + if (typeof input === 'string') { + input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals + + input = Number(input); + + if (isNaN(input)) { + console.warn('Spacetime: Invalid millenium input'); + return this; + } + } + + if (input > 0) { + input -= 1; + } + + var year = input * 1000; // there is no year 0 + + if (year === 0) { + year = 1; + } + + return this.year(year); + } // get the current millenium + + + var num = Math.floor(this.year() / 1000); + + if (num >= 0) { + num += 1; + } + + return num; + } + }; + var _03Year = methods$3; + var methods$4 = Object.assign({}, _01Time, _02Date, _03Year); //aliases + + methods$4.milliseconds = methods$4.millisecond; + methods$4.seconds = methods$4.second; + methods$4.minutes = methods$4.minute; + methods$4.hours = methods$4.hour; + methods$4.hour24 = methods$4.hour; + methods$4.h12 = methods$4.hour12; + methods$4.h24 = methods$4.hour24; + methods$4.days = methods$4.day; + + var addMethods = function addMethods(Space) { + //hook the methods into prototype + Object.keys(methods$4).forEach(function (k) { + Space.prototype[k] = methods$4[k]; + }); + }; + + var query = addMethods; + var order$1 = ['millisecond', 'second', 'minute', 'hour', 'date', 'month']; + var keep = { + second: order$1.slice(0, 1), + minute: order$1.slice(0, 2), + quarterhour: order$1.slice(0, 2), + hour: order$1.slice(0, 3), + date: order$1.slice(0, 4), + month: order$1.slice(0, 4), + quarter: order$1.slice(0, 4), + season: order$1.slice(0, 4), + year: order$1, + decade: order$1, + century: order$1 + }; + keep.week = keep.hour; + keep.season = keep.date; + keep.quarter = keep.date; // Units need to be dst adjuested + + var dstAwareUnits = { + year: true, + quarter: true, + season: true, + month: true, + week: true, + day: true + }; + var keepDate = { + month: true, + quarter: true, + season: true, + year: true + }; //month is the only thing we 'model/compute' + //- because ms-shifting can be off by enough + + var rollMonth = function rollMonth(want, old) { + //increment year + if (want.month > 0) { + var years = parseInt(want.month / 12, 10); + want.year = old.year() + years; + want.month = want.month % 12; + } else if (want.month < 0) { + //decrement year + var _years = Math.floor(Math.abs(want.month) / 13, 10); + + _years = Math.abs(_years) + 1; + want.year = old.year() - _years; //ignore extras + + want.month = want.month % 12; + want.month = want.month + 12; + + if (want.month === 12) { + want.month = 0; + } + } + + return want; + }; + + var addMethods$1 = function addMethods$1(SpaceTime) { + SpaceTime.prototype.add = function (num, unit) { + var s = this.clone(); + + if (!unit || num === 0) { + return s; //don't bother + } + + var old = this.clone(); + unit = fns.normalize(unit); //move forward by the estimated milliseconds (rough) + + if (milliseconds[unit]) { + s.epoch += milliseconds[unit] * num; + } else if (unit === 'week') { + s.epoch += milliseconds.day * (num * 7); + } else if (unit === 'quarter' || unit === 'season') { + s.epoch += milliseconds.month * (num * 4); + } else if (unit === 'season') { + s.epoch += milliseconds.month * (num * 4); + } else if (unit === 'quarterhour') { + s.epoch += milliseconds.minute * 15 * num; + } //now ensure our milliseconds/etc are in-line + + + var want = {}; + + if (keep[unit]) { + keep[unit].forEach(function (u) { + want[u] = old[u](); + }); + } + + if (dstAwareUnits[unit]) { + var _diff = old.timezone().current.offset - s.timezone().current.offset; + + s.epoch += _diff * 3600 * 1000; + } //ensure month/year has ticked-over + + + if (unit === 'month') { + want.month = old.month() + num; //month is the one unit we 'model' directly + + want = rollMonth(want, old); + } //support coercing a week, too + + + if (unit === 'week') { + var sum = old.date() + num * 7; + + if (sum <= 28 && sum > 1) { + want.date = sum; + } + } //support 25-hour day-changes on dst-changes + else if (unit === 'date') { + //specify a naive date number, if it's easy to do... + var _sum = old.date() + num; + + if (_sum <= 28 && _sum > 1) { + want.date = _sum; + } //or if we haven't moved at all.. + else if (num !== 0 && old.isSame(s, 'day')) { + want.date = old.date() + num; + } + } //ensure year has changed (leap-years) + else if (unit === 'year' && s.year() === old.year()) { + s.epoch += milliseconds.week; + } //these are easier + else if (unit === 'decade') { + want.year = s.year() + 10; + } else if (unit === 'century') { + want.year = s.year() + 100; + } //keep current date, unless the month doesn't have it. + + + if (keepDate[unit]) { + var max = monthLengths_1[want.month]; + want.date = old.date(); + + if (want.date > max) { + want.date = max; + } + } + + walk_1(s, want); + return s; + }; //subtract is only add *-1 + + + SpaceTime.prototype.subtract = function (num, unit) { + var s = this.clone(); + return s.add(num * -1, unit); + }; //add aliases + + + SpaceTime.prototype.minus = SpaceTime.prototype.subtract; + SpaceTime.prototype.plus = SpaceTime.prototype.add; + }; + + var add = addMethods$1; //make a string, for easy comparison between dates + + var print = { + millisecond: function millisecond(s) { + return s.epoch; + }, + second: function second(s) { + return [s.year(), s.month(), s.date(), s.hour(), s.minute(), s.second()].join('-'); + }, + minute: function minute(s) { + return [s.year(), s.month(), s.date(), s.hour(), s.minute()].join('-'); + }, + hour: function hour(s) { + return [s.year(), s.month(), s.date(), s.hour()].join('-'); + }, + day: function day(s) { + return [s.year(), s.month(), s.date()].join('-'); + }, + week: function week(s) { + return [s.year(), s.week()].join('-'); + }, + month: function month(s) { + return [s.year(), s.month()].join('-'); + }, + quarter: function quarter(s) { + return [s.year(), s.quarter()].join('-'); + }, + year: function year(s) { + return s.year(); + } + }; + print.date = print.day; + + var addMethods$2 = function addMethods$2(SpaceTime) { + SpaceTime.prototype.isSame = function (b, unit) { + var a = this; + + if (!unit) { + return null; + } + + if (typeof b === 'string' || typeof b === 'number') { + b = new SpaceTime(b, this.timezone.name); + } //support 'seconds' aswell as 'second' + + + unit = unit.replace(/s$/, ''); + + if (print[unit]) { + return print[unit](a) === print[unit](b); + } + + return null; + }; + }; + + var same = addMethods$2; + + var addMethods$3 = function addMethods$3(SpaceTime) { + var methods = { + isAfter: function isAfter(d) { + d = fns.beADate(d, this); + var epoch = fns.getEpoch(d); + + if (epoch === null) { + return null; + } + + return this.epoch > epoch; + }, + isBefore: function isBefore(d) { + d = fns.beADate(d, this); + var epoch = fns.getEpoch(d); + + if (epoch === null) { + return null; + } + + return this.epoch < epoch; + }, + isEqual: function isEqual(d) { + d = fns.beADate(d, this); + var epoch = fns.getEpoch(d); + + if (epoch === null) { + return null; + } + + return this.epoch === epoch; + }, + isBetween: function isBetween(start, end) { + start = fns.beADate(start, this); + end = fns.beADate(end, this); + var startEpoch = fns.getEpoch(start); + + if (startEpoch === null) { + return null; + } + + var endEpoch = fns.getEpoch(end); + + if (endEpoch === null) { + return null; + } + + return startEpoch < this.epoch && this.epoch < endEpoch; + } + }; //hook them into proto + + Object.keys(methods).forEach(function (k) { + SpaceTime.prototype[k] = methods[k]; + }); + }; + + var compare = addMethods$3; + + var addMethods$4 = function addMethods$4(SpaceTime) { + var methods = { + i18n: function i18n(data) { + //change the day names + if (fns.isObject(data.days)) { + days.set(data.days); + } //change the month names + + + if (fns.isObject(data.months)) { + months.set(data.months); + } + } + }; //hook them into proto + + Object.keys(methods).forEach(function (k) { + SpaceTime.prototype[k] = methods[k]; + }); + }; + + var i18n = addMethods$4; + var timezones = unpack; //fake timezone-support, for fakers (es5 class) + + var SpaceTime = function SpaceTime(input$1, tz) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + //the holy moment + this.epoch = null; //the shift for the given timezone + + this.tz = find(tz, timezones); //whether to output warnings to console + + this.silent = options.silent || true; // favour british interpretation of 02/02/2018, etc + + this.british = options.dmy || options.british; //does the week start on sunday, or monday: + + this._weekStart = 1; //default to monday + + if (options.weekStart !== undefined) { + this._weekStart = options.weekStart; + } //add getter/setters + + + Object.defineProperty(this, 'd', { + //return a js date object + get: function get() { + var offset = quick(this); //every computer is somewhere- get this computer's built-in offset + + var bias = new Date(this.epoch).getTimezoneOffset() || 0; //movement + + var shift = bias + offset * 60; //in minutes + + shift = shift * 60 * 1000; //in ms + //remove this computer's offset + + var epoch = this.epoch + shift; + var d = new Date(epoch); + return d; + } + }); //add this data on the object, to allow adding new timezones + + Object.defineProperty(this, 'timezones', { + get: function get() { + return timezones; + }, + set: function set(obj) { + timezones = obj; + return obj; + } + }); //parse the various formats + + if (input$1 !== undefined || input$1 === null) { + var tmp = input(this, input$1, tz); + this.epoch = tmp.epoch; + } + }; //(add instance methods to prototype) + + + Object.keys(methods_1).forEach(function (k) { + SpaceTime.prototype[k] = methods_1[k]; + }); // ¯\_(ツ)_/¯ + + SpaceTime.prototype.clone = function () { + return new SpaceTime(this.epoch, this.tz, { + silent: this.silent, + weekStart: this._weekStart + }); + }; //append more methods + + + query(SpaceTime); + add(SpaceTime); + same(SpaceTime); + compare(SpaceTime); + i18n(SpaceTime); + var spacetime = SpaceTime; // const timezones = require('../data'); + + var whereIts = function whereIts(a, b) { + var start = new spacetime(null); + var end = new spacetime(null); + start = start.time(a); //if b is undefined, use as 'within one hour' + + if (b) { + end = end.time(b); + } else { + end = start.add(59, 'minutes'); + } + + var startHour = start.hour(); + var endHour = end.hour(); + var tzs = Object.keys(start.timezones).filter(function (tz) { + if (tz.indexOf('/') === -1) { + return false; + } + + var m = new spacetime(null, tz); + var hour = m.hour(); //do 'calendar-compare' not real-time-compare + + if (hour >= startHour && hour <= endHour) { + //test minutes too, if applicable + if (hour === startHour && m.minute() < start.minute()) { + return false; + } + + if (hour === endHour && m.minute() > end.minute()) { + return false; + } + + return true; + } + + return false; + }); + return tzs; + }; + + var whereIts_1 = whereIts; + var _version = '6.3.0'; + + var main$1 = function main$1(input, tz, options) { + return new spacetime(input, tz, options); + }; //some helper functions on the main method + + + main$1.now = function (tz, options) { + return new spacetime(new Date().getTime(), tz, options); + }; + + main$1.today = function (tz, options) { + var s = new spacetime(new Date().getTime(), tz, options); + return s.startOf('day'); + }; + + main$1.tomorrow = function (tz, options) { + var s = new spacetime(new Date().getTime(), tz, options); + return s.add(1, 'day').startOf('day'); + }; + + main$1.yesterday = function (tz, options) { + var s = new spacetime(new Date().getTime(), tz, options); + return s.subtract(1, 'day').startOf('day'); + }; + + main$1.extend = function (obj) { + Object.keys(obj).forEach(function (k) { + spacetime.prototype[k] = obj[k]; + }); + return this; + }; //find tz by time + + + main$1.whereIts = whereIts_1; + main$1.version = _version; //aliases: + + main$1.plugin = main$1.extend; + var src = main$1; + + var spacetime$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': src + }); + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule$1(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + function getCjsExportFromNamespace$1 (n) { + return n && n['default'] || n; + } + + var require$$0 = getCjsExportFromNamespace$1(spacetime$1); + + var halfPast = function halfPast(m, s) { + var hour = m.match('#Cardinal$').text('reduced'); + var term = m.match('(half|quarter|25|15|10|5)'); + var mins = term.text('reduced'); + + if (term.has('half')) { + mins = '30'; + } + + if (term.has('quarter')) { + mins = '15'; + } + + var behind = m.has('to'); // apply it + + s = s.hour(hour); + s = s.startOf('hour'); + + if (behind) { + s = s.subtract(mins, 'minutes'); + } else { + s = s.add(mins, 'minutes'); + } + + return s; + }; + + var parseTime$1 = function parseTime(doc) { + var time = doc.match('(at|by|for|before)? #Time+'); + + if (time.found) { + doc.remove(time); + } // get the main part of the time + + + time = time.not('(at|by|for|before|sharp)'); + time = time.not('on the dot'); + var s = require$$0.now(); + var now = s.clone(); // '5 oclock' + + var m = time.match('^#Cardinal oclock (am|pm)?'); + + if (m.found) { + m = m.not('oclock'); + s = s.hour(m.text('reduced')); + + if (s.isValid() && !s.isEqual(now)) { + return s.time(); + } + } // 'quarter to two' + + + m = time.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal'); + + if (m.found) { + s = halfPast(m, s); + + if (s.isValid() && !s.isEqual(now)) { + return s.time(); + } + } // parse random a time like '4:54pm' + + + var str = time.text('reduced'); + s = s.time(str); + + if (s.isValid() && !s.isEqual(now)) { + return s.time(); + } + + return null; + }; + + var _02Time = parseTime$1; + + // interpret 'this halloween' or 'next june' + var parseRelative = function parseRelative(doc) { + var rel = null; + + if (doc.has('^this? (next|upcoming)')) { + rel = 'next'; + } + + if (doc.has('^this? (last|previous)')) { + rel = 'last'; + } + + if (doc.has('^(this|current)')) { + rel = 'this'; + } // finally, remove it from our text + + + doc.remove('^(this|current|next|upcoming|last|previous)'); + return rel; + }; + + var _03Relative = parseRelative; + + var Unit = + /*#__PURE__*/ + function () { + function Unit(str, unit) { + _classCallCheck(this, Unit); + + this.str = str; + this.unit = unit || 'day'; // set it to the beginning of the given unit + + var d = require$$0(str); // set to beginning + + if (d.isValid()) { + d = d.startOf(unit); + } + + Object.defineProperty(this, 'd', { + enumerable: false, + writable: true, + value: d + }); + } // make a new one + + + _createClass(Unit, [{ + key: "clone", + value: function clone() { + var d = new Unit(this.str); + d.unit = this.unit; + return d; + } + }, { + key: "applyShift", + value: function applyShift(obj) { + var _this = this; + + Object.keys(obj).forEach(function (k) { + _this.d = _this.d.add(obj[k], k); + }); + return this; + } + }, { + key: "applyTime", + value: function applyTime(str) { + if (str) { + this.d = this.d.time(str); + } else { + this.d = this.d.startOf('day'); //zero-out time + } + + return this; + } + }, { + key: "format", + value: function format(fmt) { + return this.d.format(fmt); + } + }, { + key: "start", + value: function start() { + this.d = this.d.startOf(this.unit); + return this; + } + }, { + key: "end", + value: function end() { + this.d = this.d.endOf(this.unit); + return this; + } // 'before 2019' + + }, { + key: "before", + value: function before() { + this.d = require$$0.now(); // ??? + + return this; + } // 'after 2019' + + }, { + key: "after", + value: function after() { + this.d = this.d.add(1, this.unit); + this.d = this.d.startOf(this.unit); + return this; + } // tricky: 'next june' 'next tuesday' + + }, { + key: "next", + value: function next() { + this.d = this.d.add(1, this.unit); + this.d = this.d.startOf(this.unit); + return this; + } // tricky: 'last june' 'last tuesday' + + }, { + key: "last", + value: function last() { + this.d = this.d.minus(1, this.unit); + this.d = this.d.startOf(this.unit); + return this; + } + }]); + + return Unit; + }(); + + var Unit_1 = Unit; + + var Day = + /*#__PURE__*/ + function (_Unit) { + _inherits(Day, _Unit); + + function Day(str, unit) { + var _this; + + _classCallCheck(this, Day); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Day).call(this, str, unit)); + _this.unit = 'day'; + return _this; + } + + return Day; + }(Unit_1); + + var Month = + /*#__PURE__*/ + function (_Unit2) { + _inherits(Month, _Unit2); + + function Month(str, unit) { + var _this2; + + _classCallCheck(this, Month); + + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Month).call(this, str, unit)); + _this2.unit = 'month'; + return _this2; + } + + return Month; + }(Unit_1); + + var Quarter = + /*#__PURE__*/ + function (_Unit3) { + _inherits(Quarter, _Unit3); + + function Quarter(str, unit) { + var _this3; + + _classCallCheck(this, Quarter); + + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(Quarter).call(this, str, unit)); + _this3.unit = 'quarter'; + return _this3; + } + + return Quarter; + }(Unit_1); + + var Year = + /*#__PURE__*/ + function (_Unit4) { + _inherits(Year, _Unit4); + + function Year(str, unit) { + var _this4; + + _classCallCheck(this, Year); + + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(Year).call(this, str, unit)); + _this4.unit = 'year'; + return _this4; + } + + return Year; + }(Unit_1); + + var WeekDay = + /*#__PURE__*/ + function (_Unit5) { + _inherits(WeekDay, _Unit5); + + function WeekDay(str, unit) { + var _this5; + + _classCallCheck(this, WeekDay); + + _this5 = _possibleConstructorReturn(this, _getPrototypeOf(WeekDay).call(this, str, unit)); + _this5.unit = 'week'; + _this5.d = _this5.d.day(str); //assume a wednesday in the future + + if (_this5.d.date() < require$$0.now().date()) { + _this5.d = _this5.d.add(7, 'days'); + } + + return _this5; + } + + _createClass(WeekDay, [{ + key: "next", + value: function next() { + this.d = this.d.add(7, 'days'); + this.d = this.d.day(this.str); + return this; + } + }, { + key: "last", + value: function last() { + this.d = this.d.minus(7, 'days'); + this.d = this.d.day(this.str); + return this; + } + }]); + + return WeekDay; + }(Unit_1); // like 'feb 2' + + + var CalendarDate = + /*#__PURE__*/ + function (_Unit6) { + _inherits(CalendarDate, _Unit6); + + function CalendarDate(str, unit) { + var _this6; + + _classCallCheck(this, CalendarDate); + + _this6 = _possibleConstructorReturn(this, _getPrototypeOf(CalendarDate).call(this, str, unit)); + _this6.unit = 'day'; + return _this6; + } + + _createClass(CalendarDate, [{ + key: "next", + value: function next() { + this.d = this.d.add(1, 'year'); + return this; + } + }, { + key: "last", + value: function last() { + this.d = this.d.minus(1, 'year'); + return this; + } + }]); + + return CalendarDate; + }(Unit_1); + + var units$4 = { + Unit: Unit_1, + Day: Day, + Month: Month, + Quarter: Quarter, + Year: Year, + WeekDay: WeekDay, + CalendarDate: CalendarDate + }; + + var mapping$1 = { + week: units$4.Week, + month: units$4.Month, + quarter: units$4.Quarter, + year: units$4.Year, + season: units$4.Season + }; // when a unit of time is spoken of as 'this month' - instead of 'february' + + var namedUnit = function namedUnit(doc) { + //this month, last quarter, next year + var m = doc.match('(weekday|week|month|quarter|season|year)'); + + if (m.found === true) { + var str = m.lastTerm().text('reduced'); + + if (mapping$1.hasOwnProperty(str)) { + var Model = mapping$1[str]; + + if (!Model) { + return null; + } + + var unit = new Model(null, str); + return unit; + } + } //try this version - 'next friday, last thursday' + + + m = doc.match('(monday|tuesday|wednesday|thursday|friday|saturday|sunday)'); + + if (m.found === true) { + var _str = m.lastTerm().text('reduced'); + + var _unit = new units$4.WeekDay(_str); + + return _unit; + } + + return null; + }; + + var _01NamedUnit = namedUnit; + + var spacetimeHoliday = createCommonjsModule$1(function (module, exports) { + (function (global, factory) { + module.exports = factory(require$$0) ; + })(commonjsGlobal, function (spacetime) { + + spacetime = spacetime && spacetime.hasOwnProperty('default') ? spacetime['default'] : spacetime; //yep, + + var jan = 'january'; + var feb = 'february'; + var mar = 'march'; + var apr = 'april'; + var may = 'may'; + var jun = 'june'; + var jul = 'july'; + var aug = 'august'; + var sep = 'september'; + var oct = 'october'; + var nov = 'november'; + var dec = 'december'; + var fixedHolidays = { + 'new years eve': [dec, 31], + 'new years': [jan, 1], + 'new years day': [jan, 1], + 'inauguration day': [jan, 20], + 'australia day': [jan, 26], + 'national freedom day': [feb, 1], + 'groundhog day': [feb, 2], + 'rosa parks day': [feb, 4], + 'valentines day': [feb, 14], + 'saint valentines day': [feb, 14], + 'st valentines day ': [feb, 14], + 'saint patricks day': [mar, 17], + 'st patricks day': [mar, 17], + 'april fools': [apr, 1], + 'april fools day': [apr, 1], + 'emancipation day': [apr, 16], + 'tax day': [apr, 15], + //US + 'labour day': [may, 1], + 'cinco de mayo': [may, 5], + 'national nurses day': [may, 6], + 'harvey milk day': [may, 22], + 'victoria day': [may, 24], + juneteenth: [jun, 19], + 'canada day': [jul, 1], + 'independence day': [jul, 4], + 'independents day': [jul, 4], + 'bastille day': [jul, 14], + 'purple heart day': [aug, 7], + 'womens equality day': [aug, 26], + '16 de septiembre': [sep, 16], + 'dieciseis de septiembre': [sep, 16], + 'grito de dolores': [sep, 16], + halloween: [oct, 31], + 'all hallows eve': [oct, 31], + 'day of the dead': [oct, 31], + // Ranged holiday [nov, 2], + 'dia de muertos': [oct, 31], + // Ranged holiday [nov, 2], + 'veterans day': [nov, 11], + 'st andrews day': [nov, 30], + 'saint andrews day': [nov, 30], + 'all saints day': [nov, 1], + 'all sts day': [nov, 1], + 'armistice day': [nov, 11], + 'rememberance day': [nov, 11], + 'christmas eve': [dec, 24], + christmas: [dec, 25], + xmas: [dec, 25], + 'boxing day': [dec, 26], + 'st stephens day': [dec, 26], + 'saint stephens day': [dec, 26], + // Fixed religious and cultural holidays + // Catholic + Christian + epiphany: [jan, 6], + 'orthodox christmas day': [jan, 7], + 'orthodox new year': [jan, 14], + 'assumption of mary': [aug, 15], + 'all souls day': [nov, 2], + 'feast of the immaculate conception': [dec, 8], + 'feast of our lady of guadalupe': [dec, 12], + // Kwanzaa + kwanzaa: [dec, 26], + // Ranged holiday [jan, 1], + // Pagan / metal 🤘 + imbolc: [feb, 2], + beltaine: [may, 1], + lughnassadh: [aug, 1], + samhain: [oct, 31] + }; + + var fixedDates = function fixedDates(str, normal, year) { + if (fixedHolidays.hasOwnProperty(str) || fixedHolidays.hasOwnProperty(normal)) { + var arr = fixedHolidays[str] || fixedHolidays[normal] || []; + var s = spacetime.now(); + s = s.year(year); + s = s.startOf('year'); + s = s.month(arr[0]); + s = s.date(arr[1]); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _01FixedDates = fixedDates; //these are holidays on the 'nth weekday of month' + + var jan$1 = 'january'; + var feb$1 = 'february'; + var mar$1 = 'march'; // const apr = 'april' + + var may$1 = 'may'; + var jun$1 = 'june'; // const jul = 'july' + // const aug = 'august' + + var sep$1 = 'september'; + var oct$1 = 'october'; + var nov$1 = 'november'; // const dec = 'december' + + var mon = 'monday'; // const tues = 'tuesday' + // const wed = 'wednesday' + + var thurs = 'thursday'; + var fri = 'friday'; // const sat = 'saturday' + + var sun = 'sunday'; + var holidays = { + 'martin luther king day': [3, mon, jan$1], + //[third monday in january], + 'presidents day': [3, mon, feb$1], + //[third monday in february], + 'commonwealth day': [2, mon, mar$1], + //[second monday in march], + 'mothers day': [2, sun, may$1], + //[second Sunday in May], + 'fathers day': [3, sun, jun$1], + //[third Sunday in June], + 'labor day': [1, mon, sep$1], + //[first monday in september], + 'columbus day': [2, mon, oct$1], + //[second monday in october], + 'canadian thanksgiving': [2, mon, oct$1], + //[second monday in october], + thanksgiving: [4, thurs, nov$1], + // [fourth Thursday in November], + 'black friday': [4, fri, nov$1] //[fourth friday in november], + // 'memorial day': [may], //[last monday in may], + // 'us election': [nov], // [Tuesday following the first Monday in November], + // 'cyber monday': [nov] + // 'advent': [] // fourth Sunday before Christmas + + }; // add aliases + + holidays['turday day'] = holidays.thanksgiving; + holidays['indigenous peoples day'] = holidays['columbus day']; + holidays['mlk day'] = holidays['martin luther king day']; + var calendarHolidays = holidays; + + var fixedDates$1 = function fixedDates(str, normal, year) { + if (calendarHolidays.hasOwnProperty(str) || calendarHolidays.hasOwnProperty(normal)) { + var arr = calendarHolidays[str] || calendarHolidays[normal] || []; + var s = spacetime.now(); + s = s.year(year); // [3rd, 'monday', 'january'] + + s = s.month(arr[2]); + s = s.startOf('month'); // make it january + + var month = s.month(); // make it the 1st monday + + s = s.day(arr[1]); + + if (s.month() !== month) { + s = s.add(1, 'week'); + } // make it nth monday + + + if (arr[0] > 1) { + s = s.add(arr[0] - 1, 'week'); + } + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _02NthWeekday = fixedDates$1; // https://www.timeanddate.com/calendar/determining-easter-date.html + + var dates = { + easter: 0, + 'ash wednesday': -46, + // (46 days before easter) + 'palm sunday': 7, + // (1 week before easter) + 'maundy thursday': -3, + // (3 days before easter) + 'good friday': -2, + // (2 days before easter) + 'holy saturday': -1, + // (1 days before easter) + 'easter saturday': -1, + // (1 day before easter) + 'easter monday': 1, + // (1 day after easter) + 'ascension day': 39, + // (39 days after easter) + 'whit sunday': 49, + // / pentecost (49 days after easter) + 'whit monday': 50, + // (50 days after easter) + 'trinity sunday': 65, + // (56 days after easter) + 'corpus christi': 60, + // (60 days after easter) + 'mardi gras': -47 //(47 days before easter) + + }; + dates['easter sunday'] = dates.easter; + dates['pentecost'] = dates['whit sunday']; + dates['whitsun'] = dates['whit sunday']; + var easterHolidays = dates; // by John Dyer + // based on the algorithm by Oudin (1940) from http://www.tondering.dk/claus/cal/easter.php + + var calcEaster = function calcEaster(year) { + var f = Math.floor, + // Golden Number - 1 + G = year % 19, + C = f(year / 100), + // related to Epact + H = (C - f(C / 4) - f((8 * C + 13) / 25) + 19 * G + 15) % 30, + // number of days from 21 March to the Paschal full moon + I = H - f(H / 28) * (1 - f(29 / (H + 1)) * f((21 - G) / 11)), + // weekday for the Paschal full moon + J = (year + f(year / 4) + I + 2 - C + f(C / 4)) % 7, + // number of days from 21 March to the Sunday on or before the Paschal full moon + L = I - J, + month = 3 + f((L + 40) / 44), + date = L + 28 - 31 * f(month / 4); + month = month === 4 ? 'April' : 'March'; + return month + ' ' + date; + }; + + var calcEaster_1 = calcEaster; + + var easterDates = function easterDates(str, normal, year) { + if (easterHolidays.hasOwnProperty(str) || easterHolidays.hasOwnProperty(normal)) { + var days = easterHolidays[str] || easterHolidays[normal] || []; + var date = calcEaster_1(year); + + if (!date) { + return null; //no easter for this year + } + + var e = spacetime(date); + e = e.year(year); + var s = e.add(days, 'day'); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _03EasterDates = easterDates; // http://www.astropixels.com/ephemeris/soleq2001.html + // years 2000-2100 + + var exceptions = { + spring: [2003, 2007, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 2072, 2076, 2077, 2080, 2081, 2084, 2085, 2088, 2089, 2092, 2093, 2096, 2097], + summer: [2021, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2041, 2044, 2045, 2048, 2049, 2052, 2053, 2056, 2057, 2060, 2061, 2064, 2065, 2068, 2069, 2070, 2072, 2073, 2074, 2076, 2077, 2078, 2080, 2081, 2082, 2084, 2085, 2086, 2088, 2089, 2090, 2092, 2093, 2094, 2096, 2097, 2098, 2099], + fall: [2002, 2003, 2004, 2006, 2007, 2010, 2011, 2014, 2015, 2018, 2019, 2022, 2023, 2026, 2027, 2031, 2035, 2039, 2043, 2047, 2051, 2055, 2059, 2092, 2096], + winter: [2002, 2003, 2006, 2007, 2011, 2015, 2019, 2023, 2027, 2031, 2035, 2039, 2043, 2080, 2084, 2088, 2092, 2096] + }; + var winter20th = [2080, 2084, 2088, 2092, 2096]; + + var calcSeasons = function calcSeasons(year) { + // most common defaults + var res = { + spring: 'March 20 ' + year, + summer: 'June 21 ' + year, + fall: 'Sept 22 ' + year, + winter: 'Dec 21 ' + year + }; + + if (exceptions.spring.indexOf(year) !== -1) { + res.spring = 'March 19 ' + year; + } + + if (exceptions.summer.indexOf(year) !== -1) { + res.summer = 'June 20 ' + year; + } + + if (exceptions.fall.indexOf(year) !== -1) { + res.fall = 'Sept 21 ' + year; + } // winter can be 20th, 21st, or 22nd + + + if (exceptions.winter.indexOf(year) !== -1) { + res.winter = 'Dec 22 ' + year; + } + + if (winter20th.indexOf(year) !== -1) { + res.winter = 'Dec 20 ' + year; + } + + return res; + }; + + var seasons = calcSeasons; // these are properly calculated in ./lib/seasons + + var dates$1 = { + 'spring equinox': 'spring', + 'summer solistice': 'summer', + 'fall equinox': 'fall', + 'winter solstice': 'winter' + }; // aliases + + dates$1['march equinox'] = dates$1['spring equinox']; + dates$1['vernal equinox'] = dates$1['spring equinox']; + dates$1['ostara'] = dates$1['spring equinox']; + dates$1['june solstice'] = dates$1['summer solistice']; + dates$1['litha'] = dates$1['summer solistice']; + dates$1['autumn equinox'] = dates$1['fall equinox']; + dates$1['autumnal equinox'] = dates$1['fall equinox']; + dates$1['september equinox'] = dates$1['fall equinox']; + dates$1['sept equinox'] = dates$1['fall equinox']; + dates$1['mabon'] = dates$1['fall equinox']; + dates$1['december solstice'] = dates$1['winter solistice']; + dates$1['dec solstice'] = dates$1['winter solistice']; + dates$1['yule'] = dates$1['winter solistice']; + var astroHolidays = dates$1; + + var astroDates = function astroDates(str, normal, year) { + if (astroHolidays.hasOwnProperty(str) || astroHolidays.hasOwnProperty(normal)) { + var season = astroHolidays[str] || astroHolidays[normal]; + var seasons$1 = seasons(year); + + if (!season || !seasons$1 || !seasons$1[season]) { + return null; // couldn't figure it out + } + + var s = spacetime(seasons$1[season]); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _04Astronomical = astroDates; + var dates$2 = { + // Muslim holidays + 'isra and miraj': 'april 13', + 'lailat al-qadr': 'june 10', + 'eid al-fitr': 'june 15', + 'id al-Fitr': 'june 15', + 'eid ul-Fitr': 'june 15', + ramadan: 'may 16', + // Range holiday + 'eid al-adha': 'sep 22', + muharram: 'sep 12', + 'prophets birthday': 'nov 21' + }; + var lunarHolidays = dates$2; + var dayDiff = -10.64; + + var lunarDates = function lunarDates(str, normal, year) { + if (lunarHolidays.hasOwnProperty(str) || lunarHolidays.hasOwnProperty(normal)) { + var date = lunarHolidays[str] || lunarHolidays[normal] || []; + + if (!date) { + return null; + } // start at 2018 + + + var s = spacetime(date + ' 2018'); + var diff = year - 2018; + var toAdd = diff * dayDiff; + s = s.add(toAdd, 'day'); + s = s.startOf('day'); // now set the correct year + + s = s.year(year); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _05LunarDates = lunarDates; + var nowYear = spacetime.now().year(); + + var spacetimeHoliday = function spacetimeHoliday(str, year) { + year = year || nowYear; + str = str || ''; + str = String(str); + str = str.trim().toLowerCase(); + str = str.replace(/'s/, 's'); // 'mother's day' + + var normal = str.replace(/ day$/, ''); + normal = normal.replace(/^the /, ''); + normal = normal.replace(/^orthodox /, ''); //orthodox good friday + // try easier, unmoving holidays + + var s = _01FixedDates(str, normal, year); + + if (s !== null) { + return s; + } // try 'nth monday' holidays + + + s = _02NthWeekday(str, normal, year); + + if (s !== null) { + return s; + } // easter-based holidays + + + s = _03EasterDates(str, normal, year); + + if (s !== null) { + return s; + } // solar-based holidays + + + s = _04Astronomical(str, normal, year); + + if (s !== null) { + return s; + } // mostly muslim holidays + + + s = _05LunarDates(str, normal, year); + + if (s !== null) { + return s; + } + + return null; + }; + + var src = spacetimeHoliday; + return src; + }); + }); + + var parseHoliday = function parseHoliday(doc) { + var d = null; + var str = doc.match('#Holiday+').text('reduced'); + var year = 2020; //change me! + + var s = spacetimeHoliday(str, year); + + if (s !== null) { + d = new units$4.CalendarDate(s); + } + + return d; + }; + + var _02Holidays = parseHoliday; + + var Unit$1 = units$4.Unit; // parse things like 'june 5th 2019' + + var parseExplicit = function parseExplicit(doc) { + if (doc.has('#Number of #Month')) ; + + var str = doc.text('reduced'); // spacetime does the heavy-lifting + + var d = new Unit$1(str); // did we find a date? + + if (d.d.isValid() === false) { + return null; + } + + return d; + }; + + var _03Explicit = parseExplicit; + + var Unit$2 = units$4.Unit; + + var parseDate = function parseDate(doc) { + var shift = _01Shift(doc); + var time = _02Time(doc); + var rel = _03Relative(doc); + var d = null; // let str = doc.text('reduced') + // console.log(str, ' - ', rel, ' - ', shift, ' - ', time) + // do we have just a time? + + if (doc.found === false && time !== null) { + d = new Unit$2(); // choose today + } // this month + + + d = d || _01NamedUnit(doc); // this haloween + + d = d || _02Holidays(doc); // this june 2nd + + d = d || _03Explicit(doc); + + if (!d) { + return null; + } // // apply relative + + + if (rel === 'last') { + d.last(); + } + + if (rel === 'next') { + d.next(); + } // apply shift + + + if (shift) { + d.applyShift(shift); + } // apply time + + + d.applyTime(time); + return d; + }; + + var toDate = parseDate; + + var logic = function logic(doc, context) { + // two explicit dates - 'between friday and sunday' + var m = doc.match('between * and *'); + + if (m.found) { + var start = m.match('between [.*] and').not('^between').not('and$'); + start = toDate(start); + var end = m.match('and *').not('^and'); + end = toDate(end); + + if (start) { + return { + start: start, + end: end + }; + } + } // two months, one year - 'june 5 to june 7 1998' + + + m = doc.match('#Month #Value to #Month #Value of? #Year'); + + if (m.found) ; // two months, no year - 'june 5 to june 7' + + + m = doc.match('#Month #Value to #Month #Value'); + + if (m.found) ; // one month, one year, first form - 'january 5 to 7 1998' + + + m = doc.match('#Month #Value to #Value of? #Year'); + + if (m.found) ; // one month, one year, second form - '5 to 7 of january 1998' + + + m = doc.match('#Value to #Value of? #Month of? #Year'); + + if (m.found) ; // one month, no year - '5 to 7 of january' + + + m = doc.match('#Value to #Value of? #Month'); + + if (m.found) ; // one month, no year - 'january 5 to 7' + + + m = doc.match('#Month #Value to #Value'); + + if (m.found) ; // 'from A to B' + + + m = doc.match('from? * (to|@hasHyphen|until|upto) [*]'); + + if (m.found) ; // 'before june' + + + m = doc.match('^due (by|before|on|in)? [*]'); + + if (m.found) ; // 'after june' + + + m = doc.match('^(after|following|from) [*]'); + + if (m.found) ; // 'in june' + + + m = doc.match('^(on|during|in) [*]'); + + if (m.found) { + var _d = toDate(m); + + if (_d) { + return { + start: _d, + end: _d.clone().end() + }; + } + } //else, try whole thing + + + var d = toDate(doc); + return { + start: d, + end: null + }; + }; + + var _02Ranges = logic; + + var parse = function parse(doc, context) { + doc = _01Normalize(doc); + return _02Ranges(doc); + }; + + var parse_1 = parse; + + var arr = [['mon', 'monday'], ['tue', 'tuesday'], ['tues', 'tuesday'], ['wed', 'wednesday'], ['thu', 'thursday'], ['thurs', 'thursday'], ['fri', 'friday'], ['sat', 'saturday'], ['sun', 'sunday'], ['jan', 'january'], ['feb', 'february'], ['mar', 'march'], ['apr', 'april'], ['jun', 'june'], ['jul', 'july'], ['aug', 'august'], ['sep', 'september'], ['sept', 'september'], ['oct', 'october'], ['nov', 'november'], ['dec', 'december']]; + arr = arr.map(function (a) { + return { + "short": a[0], + "long": a[1] + }; + }); + var abbrevs = arr; + + var addMethods$5 = function addMethods(Doc, world) { + // our new tags + world.addTags(tags); // add info for the date plugin + + world.addWords(words); // run our tagger + + world.postProcess(tagger); + /** */ + + var Dates = + /*#__PURE__*/ + function (_Doc) { + _inherits(Dates, _Doc); + + function Dates(list, from, w) { + var _this; + + _classCallCheck(this, Dates); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Dates).call(this, list, from, w)); + _this.context = {}; + return _this; + } + /** overload the original json with noun information */ + + + _createClass(Dates, [{ + key: "json", + value: function json(options) { + var _this2 = this; + + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + terms: false + }; + var res = []; + var format = options.format || 'iso'; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var obj = parse_1(doc, _this2.context); + var start = obj.start ? obj.start.format(format) : null; + var end = obj.end ? obj.end.format(format) : null; // set iso strings to json result + + json.date = { + start: start, + end: end + }; // add duration + + if (start && end) { + json.date.duration = obj.start.d.diff(obj.end.d); // we don't need these + + delete json.date.duration.milliseconds; + delete json.date.duration.seconds; + } + + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + } + /** render all dates according to a specific format */ + + }, { + key: "format", + value: function format(fmt) { + var _this3 = this; + + this.forEach(function (doc) { + var obj = parse_1(doc, _this3.context); + var str = ''; + + if (obj.start) { + str = obj.start.format(fmt); + + if (obj.end) { + str += ' to ' + obj.start.format(fmt); + } + + doc.replaceWith(str, true); + } + }); + return this; + } + /** replace 'Fri' with 'Friday', etc*/ + + }, { + key: "toLongForm", + value: function toLongForm() { + var _this4 = this; + + abbrevs.forEach(function (a) { + _this4.replace(a["short"], a["long"], true, true); + }); + return this; + } + /** replace 'Friday' with 'Fri', etc*/ + + }, { + key: "toShortForm", + value: function toShortForm() { + var _this5 = this; + + abbrevs.forEach(function (a) { + _this5.replace(a["long"], a["short"], true, true); + }); + return this; + } + }]); + + return Dates; + }(Doc); + + Doc.prototype.dates = function (n) { + var context = {}; + + if (n && _typeof(n) === 'object') { + context = n; + n = null; + } + + var r = this.clauses(); + var dates = r.match('#Date+'); + + if (typeof n === 'number') { + dates = dates.get(n); + } + + if (typeof n === 'number') { + dates = dates.get(n); + } + + var d = new Dates(dates.list, this, this.world); + d.context = context; + return d; + }; + }; + + var src$1 = addMethods$5; + + return src$1; + +}))); +//# sourceMappingURL=compromise-dates.js.map diff --git a/plugins/dates/builds/compromise-dates.js.map b/plugins/dates/builds/compromise-dates.js.map new file mode 100644 index 000000000..e0732c831 --- /dev/null +++ b/plugins/dates/builds/compromise-dates.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-dates.js","sources":["../src/tagger/00-basic.js","../src/tagger/01-values.js","../src/tagger/02-dates.js","../src/tagger/03-sections.js","../src/tagger/04-time.js","../src/tagger/05-shifts.js","../src/tagger/06-fixup.js","../src/tagger/index.js","../src/tags.js","../src/words/dates.js","../src/words/durations.js","../src/words/holidays.js","../src/words/times.js","../src/words/index.js","../src/parse/01-normalize.js","../src/parse/toDate/tokenize/01-shift.js","../node_modules/spacetime/builds/spacetime.mjs","../src/parse/toDate/tokenize/02-time.js","../src/parse/toDate/tokenize/03-relative.js","../src/parse/toDate/units/Unit.js","../src/parse/toDate/units/index.js","../src/parse/toDate/01-namedUnit.js","../node_modules/spacetime-holiday/builds/spacetime-holiday.js","../src/parse/toDate/02-holidays.js","../src/parse/toDate/03-explicit.js","../src/parse/toDate/index.js","../src/parse/02-ranges.js","../src/parse/index.js","../src/abbrevs.js","../src/index.js"],"sourcesContent":["//ambiguous 'may' and 'march'\nconst preps = '(in|by|before|during|on|until|after|of|within|all)' //6\nconst thisNext = '(last|next|this|previous|current|upcoming|coming)' //2\nconst sections = '(start|end|middle|starting|ending|midpoint|beginning)' //2\nconst seasons = '(spring|summer|winter|fall|autumn)'\n\n//ensure a year is approximately typical for common years\n//please change in one thousand years\nconst tagYear = (m, reason) => {\n if (m.found !== true) {\n return\n }\n let term = m.termList()[0]\n if (term) {\n let num = parseInt(term.clean, 10)\n if (num && num > 1000 && num < 3000) {\n m.tag('Year', reason)\n }\n }\n}\n//same, but for less-confident values\nconst tagYearSafe = (m, reason) => {\n if (m.found !== true) {\n return\n }\n let term = m.termList()[0]\n if (term) {\n let num = parseInt(term.clean, 10)\n if (num && num > 1900 && num < 2030) {\n m.tag('Year', reason)\n }\n }\n}\n\nconst fixDates = function(doc) {\n doc.match('in the (night|evening|morning|afternoon|day|daytime)').tag('Time', 'in-the-night')\n doc.match('(#Value|#Time) (am|pm)').tag('Time', 'value-ampm')\n\n //months:\n let month = doc.if('#Month')\n if (month.found === true) {\n //June 5-7th\n month.match(`#Month #DateRange+`).tag('Date', 'correction-numberRange')\n //5th of March\n month.match('#Value of #Month').tag('Date', 'value-of-month')\n //5 March\n month.match('#Cardinal #Month').tag('Date', 'cardinal-month')\n //march 5 to 7\n month.match('#Month #Value to #Value').tag('Date', 'value-to-value')\n //march the 12th\n month.match('#Month the #Value').tag('Date', 'month-the-value')\n }\n\n //months:\n let val = doc.if('#Value')\n if (val.found === true) {\n //june 7\n val\n .match('(#WeekDay|#Month) #Value')\n .ifNo('#Money')\n .tag('Date', 'date-value')\n\n //7 june\n val\n .match('#Value (#WeekDay|#Month)')\n .ifNo('#Money')\n .tag('Date', 'value-date')\n\n //may twenty five\n val\n .match('#TextValue #TextValue')\n .if('#Date')\n .tag('#Date', 'textvalue-date')\n\n //eg 'year'\n let duration = val.if('#Duration')\n if (duration.found === true) {\n //for 4 months\n duration.match('for #Value #Duration').tag('Date', 'for-x-duration')\n //two days before\n duration.match('#Value #Duration #Conjunction').tag('Date', 'val-duration-conjunction')\n //for four days\n duration.match(`${preps}? #Value #Duration`).tag('Date', 'value-duration')\n //two years old\n duration.match('#Value #Duration old').unTag('Date', 'val-years-old')\n }\n }\n\n //seasons\n let season = doc.if(seasons)\n if (season.found === true) {\n season.match(`${preps}? ${thisNext} ${seasons}`).tag('Date', 'thisNext-season')\n season.match(`the? ${sections} of ${seasons}`).tag('Date', 'section-season')\n season.match(`${seasons} ${preps}? #Cardinal`).tag('Date', 'season-year')\n }\n\n //rest-dates\n let date = doc.if('#Date')\n if (date.found === true) {\n //june the 5th\n date.match('#Date the? #Ordinal').tag('Date', 'correction')\n //last month\n date.match(`${thisNext} #Date`).tag('Date', 'thisNext')\n //by 5 March\n date.match('due? (by|before|after|until) #Date').tag('Date', 'by')\n //next feb\n date\n .match('(last|next|this|previous|current|upcoming|coming|the) #Date')\n .tag('Date', 'next-feb')\n //start of june\n date.match(`the? ${sections} of #Date`).tag('Date', 'section-of')\n //fifth week in 1998\n date.match('#Ordinal #Duration in #Date').tag('Date', 'duration-in')\n //early in june\n date.match('(early|late) (at|in)? the? #Date').tag('Time', 'early-evening')\n //tomorrow before 3\n date\n .match('#Date (by|before|after|at|@|about) #Cardinal')\n .not('^#Date')\n .tag('Time', 'date-before-Cardinal')\n //saturday am\n date\n .match('#Date [(am|pm)]')\n .unTag('Verb')\n .unTag('Copula')\n .tag('Time', 'date-am')\n //feb to june\n date\n .match('#Date (#Preposition|to) #Date')\n .ifNo('#Duration')\n .tag('Date', 'date-prep-date')\n }\n\n //year/cardinal tagging\n let cardinal = doc.if('#Cardinal')\n if (cardinal.found === true) {\n let v = cardinal.match(`#Date #Value [#Cardinal]`)\n tagYear(v, 'date-value-year')\n //scoops up a bunch\n v = cardinal.match(`#Date+ [#Cardinal]`)\n tagYear(v, 'date-year')\n //feb 8 2018\n v = cardinal.match(`#Month #Value [#Cardinal]`)\n tagYear(v, 'month-value-year')\n //feb 8 to 10th 2018\n v = cardinal.match(`#Month #Value to #Value [#Cardinal]`)\n tagYear(v, 'month-range-year')\n //in 1998\n v = cardinal.match(`(in|of|by|during|before|starting|ending|for|year) [#Cardinal]`)\n tagYear(v, 'in-year')\n //q2 2009\n v = cardinal.match('(q1|q2|q3|q4) [#Cardinal]')\n tagYear(v, 'in-year')\n //2nd quarter 2009\n v = cardinal.match('#Ordinal quarter [#Cardinal]')\n tagYear(v, 'in-year')\n //in the year 1998\n v = cardinal.match('the year [#Cardinal]')\n tagYear(v, 'in-year')\n //it was 1998\n v = cardinal.match('it (is|was) [#Cardinal]')\n tagYearSafe(v, 'in-year')\n }\n\n let time = doc.if('#Time')\n if (time.found === true) {\n //by 6pm\n time.match('(by|before|after|at|@|about) #Time').tag('Time', 'preposition-time')\n //7 7pm\n time\n .match('#Cardinal #Time')\n .not('#Year')\n .tag('Time', 'value-time')\n //2pm est\n time.match('#Time [(eastern|pacific|central|mountain)]').tag('Time', 'timezone')\n //6pm est\n time.match('#Time [(est|pst|gmt)]').tag('Time', 'timezone abbr')\n }\n\n return doc\n}\nmodule.exports = fixDates\n","const here = 'date-values'\n//\nconst values = function(doc) {\n if (doc.has('#Value')) {\n //june 5 to 7th\n doc.match('#Month #Value to #Value of? #Year?').tag('Date', here);\n //5 to 7th june\n doc.match('#Value to #Value of? #Month #Year?').tag('Date', here);\n //third week of may\n doc.match('#Value #Duration of #Date').tag('Date', here);\n //two days after\n doc.match('#Value+ #Duration (after|before|into|later|afterwards|ago)?').tag('Date', here);\n //two days\n doc.match('#Value #Date').tag('Date', here);\n //june 5th\n doc.match('#Date #Value').tag('Date', here);\n //tuesday at 5\n doc.match('#Date #Preposition #Value').tag('Date', here);\n //tomorrow before 3\n doc.match('#Date (after|before|during|on|in) #Value').tag('Date', here);\n //a year and a half\n doc.match('#Value (year|month|week|day) and a half').tag('Date', here);\n //5 and a half years\n doc.match('#Value and a half (years|months|weeks|days)').tag('Date', here);\n //on the fifth\n doc.match('on the #Ordinal').tag('Date', here);\n }\n return doc\n}\nmodule.exports = values\n","const here = 'date-tagger'\n//\nconst dateTagger = function(doc) {\n\n doc.match('(spring|summer|winter|fall|autumn|springtime|wintertime|summertime)').match('#Noun').tag('Season', here)\n doc.match('(q1|q2|q3|q4)').tag('FinancialQuarter', here)\n doc.match('(this|next|last|current) quarter').tag('FinancialQuarter', here)\n doc.match('(this|next|last|current) season').tag('Season', here)\n\n if (doc.has('#Date')) {\n //friday to sunday\n doc.match('#Date #Preposition #Date').tag('Date', here);\n //once a day..\n doc.match('(once|twice) (a|an|each) #Date').tag('Date', here);\n //TODO:fixme\n doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here);\n //tuesday\n doc.match('#Date+').tag('Date', here);\n //by June\n doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here);\n //a year after..\n doc.match('a #Duration').tag('Date', here);\n //between x and y\n doc.match('(between|from) #Date').tag('Date', here);\n doc.match('(to|until|upto) #Date').tag('Date', here);\n doc.match('#Date and #Date').tag('Date', here);\n //during this june\n doc.match('(by|until|after|before|during|on|in|following) (next|this|last)? (#Date|#Date)').tag('Date', here);\n //day after next\n doc.match('the? #Date after next one?').tag('Date', here);\n //approximately...\n doc.match('(about|approx|approximately|around) #Date').tag('Date', here);\n }\n return doc\n}\nmodule.exports = dateTagger\n","const here = 'section-tagger'\n//\nconst sectionTagger = function(doc) {\n if (doc.has('#Date')) {\n // //next september\n doc.match('this? (last|next|past|this|previous|current|upcoming|coming|the) #Date').tag('Date', here);\n //starting this june\n doc.match('(starting|beginning|ending) #Date').tag('Date', here);\n //start of june\n doc.match('the? (start|end|middle|beginning) of (last|next|this|the) (#Date|#Date)').tag('Date', here);\n //this coming june\n doc.match('(the|this) #Date').tag('Date', here);\n }\n return doc\n}\nmodule.exports = sectionTagger\n","const here = 'time-tagger'\n\n//\nconst timeTagger = function(doc) {\n if (doc.has('#Time')) {\n //eastern daylight time\n doc.match('#Noun (standard|daylight|central|mountain)? time').tag('Timezone', here)\n }\n // https://raw.githubusercontent.com/davispuh/TimezoneParser/master/data/abbreviations.yml\n if (doc.has('#Acronym')) {\n let abbr =\n '(acdt|acst|ace|dmt|ist|tse|addt|adt|aedt|aest|ahdt|ahst|akdt|akst|amt|nst|apt|awt|gmt|awdt|awst|bdst|bst|bdt|nwt|bmt|wet|bost|cddt|cdt|cet|cmt|cpt|cst|cwt|chst|gst|eat|eddt|edt|eest|eet|emt|ept|ewt|est|ffmt|fmt|hdt|hst|hkst|hkt|hmt|iddt|idt|jmt|imt|jdt|jst|kdt|kst|kmt|lst|mddt|mdst|msd|msk|mdt|mmt|mpt|pdt|pst|mst|mwt|nddt|ndt|npt|nzdt|nzmt|nzst|pddt|pkst|pkt|plmt|pmmt|pmt|ppmt|ppt|pwt|qmt|rmt|sast|sdmt|set|sjmt|smt|sst|tbmt|tmt|utc|wast|wemt|wib|wit|wita|wmt|yddt|ydt|ypt|ywt|yst)'\n doc.match(abbr).tag('Timezone', here)\n }\n // quarter to seven\n if (doc.has('#Cardinal')) {\n doc.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal').tag('Time')\n }\n return doc\n}\nmodule.exports = timeTagger\n","const here = 'shift-tagger'\n//\nconst shiftTagger = function(doc) {\n if (doc.has('#Date')) {\n //two weeks before\n doc.match('#Cardinal #Duration (before|after)').tag('#DateShift', here)\n //two weeks and three days before\n doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here)\n doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here)\n doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here)\n }\n return doc\n}\nmodule.exports = shiftTagger\n","const here = 'fix-tagger'\n//\nconst fixUp = function(doc) {\n //fixups\n if (doc.has('#Date')) {\n //first day by monday\n let oops = doc.match('#Date+ by #Date+')\n if (oops.found && !oops.has('^due')) {\n oops.match('^#Date+').unTag('Date', 'by-monday')\n }\n\n let d = doc.match('#Date+')\n //'spa day'\n d.match('^day$').unTag('Date', 'spa-day')\n\n let knownDate = '(yesterday|today|tomorrow)'\n if (d.has(knownDate)) {\n //yesterday 7\n d.match(`${knownDate} [#Value]$`).unTag('Date', 'yesterday-7')\n //7 yesterday\n d.match(`^[#Value] ${knownDate}$`).unTag('Date', '7 yesterday')\n //friday yesterday\n d.match(`#WeekDay+ ${knownDate}$`)\n .unTag('Date')\n .lastTerm()\n .tag('Date', 'fri-yesterday')\n\n // yesterday yesterday\n // d.match(`${knownDate}+ ${knownDate}$`)\n // .unTag('Date')\n // .lastTerm()\n // .tag('Date', here)\n d.match(`(this|last|next) #Date ${knownDate}$`)\n .unTag('Date')\n .lastTerm()\n .tag('Date', 'this month yesterday')\n }\n //tomorrow on 5\n d.match(`on #Cardinal$`).unTag('Date', here)\n //this tomorrow\n d.match(`this tomorrow`)\n .terms(0)\n .unTag('Date', 'this-tomorrow')\n //q2 2019\n d.match(`(q1|q2|q3|q4) #Year`).tag('Date', here)\n //5 tuesday\n // d.match(`^#Value #WeekDay`).terms(0).unTag('Date');\n //5 next week\n d.match(`^#Value (this|next|last)`)\n .terms(0)\n .unTag('Date', here)\n\n if (d.has('(last|this|next)')) {\n //this month 7\n d.match(`(last|this|next) #Duration #Value`)\n .terms(2)\n .unTag('Date', here)\n //7 this month\n d.match(`!#Month #Value (last|this|next) #Date`)\n .terms(0)\n .unTag('Date', here)\n }\n //january 5 5\n if (d.has('(#Year|#Time|#TextValue|#NumberRange)') === false) {\n d.match('(#Month|#WeekDay) #Value #Value')\n .terms(2)\n .unTag('Date', here)\n }\n //between june\n if (d.has('^between') && !d.has('and .')) {\n d.unTag('Date', here)\n }\n //june june\n if (d.has('#Month #Month') && !d.has('@hasHyphen') && !d.has('@hasComma')) {\n d.match('#Month')\n .lastTerm()\n .unTag('Date', 'month-month')\n }\n }\n return doc\n}\nmodule.exports = fixUp\n","const methods = [\n require('./00-basic'),\n require('./01-values'),\n require('./02-dates'),\n require('./03-sections'),\n require('./04-time'),\n require('./05-shifts'),\n require('./06-fixup'),\n]\n// run each of the taggers\nconst tagDate = function(doc) {\n methods.forEach(fn => fn(doc))\n return doc\n}\nmodule.exports = tagDate\n","module.exports = {\n FinancialQuarter: {\n isA: 'Date',\n },\n // 'summer'\n Season: {\n isA: 'Date',\n },\n // '1982'\n Year: {\n isA: ['Date'],\n notA: 'RomanNumeral',\n },\n // 'months'\n Duration: {\n isA: ['Date', 'Noun'],\n },\n // '9:20pm'\n Time: {\n isA: ['Date'],\n },\n // 'easter'\n Holiday: {\n isA: ['Date', 'Noun'],\n },\n // 'PST'\n Timezone: {\n isA: ['Date', 'Noun'],\n },\n // 'two weeks before'\n DateShift: {\n isA: ['Date'],\n },\n}\n","module.exports = [\n 'weekend',\n 'weekday',\n\n 'summer',\n 'winter',\n 'autumn',\n\n 'some day',\n 'one day',\n 'all day',\n 'some point',\n\n 'eod',\n 'eom',\n 'standard time',\n 'daylight time',\n\n 'today',\n 'tomorrow',\n 'tmr',\n 'tmrw',\n 'yesterday',\n]\n","module.exports = [\n 'centuries',\n 'century',\n 'day',\n 'days',\n 'decade',\n 'decades',\n 'hour',\n 'hours',\n 'millisecond',\n 'milliseconds',\n 'minute',\n 'minutes',\n 'month',\n 'months',\n 'seconds',\n 'week',\n 'weeks',\n 'year',\n 'years',\n]\n","module.exports = [\n 'all hallows eve',\n 'all saints day',\n 'all sts day',\n 'april fools',\n 'armistice day',\n 'australia day',\n 'bastille day',\n 'boxing day',\n 'canada day',\n 'christmas eve',\n 'christmas',\n 'cinco de mayo',\n 'day of the dead',\n 'dia de muertos',\n 'dieciseis de septiembre',\n 'emancipation day',\n 'grito de dolores',\n 'groundhog day',\n 'halloween',\n 'harvey milk day',\n 'inauguration day',\n 'independence day',\n 'independents day',\n 'juneteenth',\n 'labour day',\n 'national freedom day',\n 'national nurses day',\n 'new years eve',\n 'new years',\n 'purple heart day',\n 'rememberance day',\n 'rosa parks day',\n 'saint andrews day',\n 'saint patricks day',\n 'saint stephens day',\n 'saint valentines day',\n 'st andrews day',\n 'st patricks day',\n 'st stephens day',\n 'st valentines day ',\n 'valentines day',\n 'valentines',\n 'veterans day',\n 'victoria day',\n 'womens equality day',\n 'xmas',\n // Fixed religious and cultural holidays\n // Catholic + Christian\n 'epiphany',\n 'orthodox christmas day',\n 'orthodox new year',\n 'assumption of mary',\n 'all souls day',\n 'feast of the immaculate conception',\n 'feast of our lady of guadalupe',\n\n // Kwanzaa\n 'kwanzaa',\n // Pagan / metal 🤘\n 'imbolc',\n 'beltaine',\n 'lughnassadh',\n 'samhain',\n 'martin luther king day',\n 'mlk day',\n 'presidents day',\n 'mardi gras',\n 'tax day',\n 'commonwealth day',\n 'mothers day',\n 'memorial day',\n 'fathers day',\n 'columbus day',\n 'indigenous peoples day',\n 'canadian thanksgiving',\n 'election day',\n 'thanksgiving',\n 't-day',\n 'turkey day',\n 'black friday',\n 'cyber monday',\n // Astronomical religious and cultural holidays\n 'ash wednesday',\n 'palm sunday',\n 'maundy thursday',\n 'good friday',\n 'holy saturday',\n 'easter',\n 'easter sunday',\n 'easter monday',\n 'orthodox good friday',\n 'orthodox holy saturday',\n 'orthodox easter',\n 'orthodox easter monday',\n 'ascension day',\n 'pentecost',\n 'whitsunday',\n 'whit sunday',\n 'whit monday',\n 'trinity sunday',\n 'corpus christi',\n 'advent',\n // Jewish\n 'tu bishvat',\n 'tu bshevat',\n 'purim',\n 'passover',\n 'yom hashoah',\n 'lag baomer',\n 'shavuot',\n 'tisha bav',\n 'rosh hashana',\n 'yom kippur',\n 'sukkot',\n 'shmini atzeret',\n 'simchat torah',\n 'chanukah',\n 'hanukkah',\n // Muslim\n 'isra and miraj',\n 'lailat al-qadr',\n 'eid al-fitr',\n 'id al-Fitr',\n 'eid ul-Fitr',\n 'ramadan',\n 'eid al-adha',\n 'muharram',\n 'the prophets birthday',\n 'ostara',\n 'march equinox',\n 'vernal equinox',\n 'litha',\n 'june solistice',\n 'summer solistice',\n 'mabon',\n 'september equinox',\n 'fall equinox',\n 'autumnal equinox',\n 'yule',\n 'december solstice',\n 'winter solstice',\n // Additional important holidays\n 'chinese new year',\n 'diwali',\n]\n","module.exports = [\n 'noon',\n 'midnight',\n 'now',\n 'morning',\n 'tonight',\n 'evening',\n 'afternoon',\n 'night',\n 'breakfast time',\n 'lunchtime',\n 'dinnertime',\n 'ago',\n 'sometime',\n 'eod',\n 'oclock',\n 'oclock',\n 'all day',\n 'at night',\n]\n","let lex = {}\n\nconst data = [\n [require('./dates'), ['#Date']],\n [require('./durations'), ['#Duration']],\n [require('./holidays'), ['#Holiday']],\n [require('./times'), ['#Time']],\n]\ndata.forEach(a => {\n for (let i = 0; i < a[0].length; i++) {\n lex[a[0][i]] = a[1]\n }\n})\n\nmodule.exports = lex\n","const normalize = function(doc) {\n doc = doc.clone()\n\n if (!doc.numbers) {\n console.warn(\"Compromise: compromise-dates cannot find plugin dependency 'compromise-number'\")\n } else {\n // convert 'two' to 2\n let num = doc.numbers()\n num.toNumber()\n num.toCardinal()\n }\n // remove adverbs\n doc.adverbs().remove()\n return doc\n}\nmodule.exports = normalize\n","const knownUnits = {\n second: true,\n minute: true,\n hour: true,\n day: true,\n week: true,\n month: true,\n season: true,\n quarter: true,\n year: true,\n}\n\n//turn '5 weeks before' to {weeks:5}\nconst parseShift = function(doc) {\n let result = {}\n\n let m = doc.match('#DateShift+')\n if (m.found === false) {\n return result\n }\n m.match('#Cardinal #Duration').forEach(ts => {\n let num = ts.match('#Cardinal').text('normal')\n num = parseFloat(num)\n if (num && typeof num === 'number') {\n let unit = ts.match('#Duration').text('normal')\n unit = unit.replace(/s$/, '')\n if (unit && knownUnits.hasOwnProperty(unit)) {\n result[unit] = num\n }\n }\n })\n //is it 2 weeks before? → -2\n if (m.has('before$') === true) {\n Object.keys(result).forEach(k => (result[k] *= -1))\n }\n // finally, remove it from our text\n doc.remove('#DateShift')\n return result\n}\nmodule.exports = parseShift\n","function createCommonjsModule(fn, module) {\n\treturn module = { exports: {} }, fn(module, module.exports), module.exports;\n}\n\nfunction getCjsExportFromNamespace (n) {\n\treturn n && n['default'] || n;\n}\n\nvar fns = createCommonjsModule(function (module, exports) {\n//git:blame @JuliasCaesar https://www.timeanddate.com/date/leapyear.html\nexports.isLeapYear = year => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n// unsurprisingly-nasty `typeof date` call\nexports.isDate = d => Object.prototype.toString.call(d) === '[object Date]' && !isNaN(d.valueOf());\nexports.isArray = input => Object.prototype.toString.call(input) === '[object Array]';\nexports.isObject = input => Object.prototype.toString.call(input) === '[object Object]';\n\nexports.zeroPad = (str, len = 2) => {\n let pad = '0';\n str = str + '';\n return str.length >= len ? str : new Array(len - str.length + 1).join(pad) + str\n};\n\nexports.titleCase = str => {\n if (!str) {\n return ''\n }\n return str[0].toUpperCase() + str.substr(1)\n};\n\nexports.ordinal = i => {\n let j = i % 10;\n let k = i % 100;\n if (j === 1 && k !== 11) {\n return i + 'st'\n }\n if (j === 2 && k !== 12) {\n return i + 'nd'\n }\n if (j === 3 && k !== 13) {\n return i + 'rd'\n }\n return i + 'th'\n};\n\n//strip 'st' off '1st'..\nexports.toCardinal = str => {\n str = String(str);\n str = str.replace(/([0-9])(st|nd|rd|th)$/i, '$1');\n return parseInt(str, 10)\n};\n\n//used mostly for cleanup of unit names, like 'months'\nexports.normalize = (str = '') => {\n str = str.toLowerCase().trim();\n str = str.replace(/ies$/, 'y'); //'centuries'\n str = str.replace(/s$/, '');\n str = str.replace(/-/g, '');\n if (str === 'day') {\n return 'date'\n }\n return str\n};\n\nexports.getEpoch = tmp => {\n //support epoch\n if (typeof tmp === 'number') {\n return tmp\n }\n //suport date objects\n if (exports.isDate(tmp)) {\n return tmp.getTime()\n }\n if (tmp.epoch) {\n return tmp.epoch\n }\n return null\n};\n\n//make sure this input is a spacetime obj\nexports.beADate = (d, s) => {\n if (exports.isObject(d) === false) {\n return s.clone().set(d)\n }\n return d\n};\n\nexports.formatTimezone = (offset, delimiter = '') => {\n const absOffset = Math.abs(offset);\n const sign = offset > 0 ? '+' : '-';\n return `${sign}${exports.zeroPad(absOffset)}${delimiter}00`\n};\n});\nvar fns_1 = fns.isLeapYear;\nvar fns_2 = fns.isDate;\nvar fns_3 = fns.isArray;\nvar fns_4 = fns.isObject;\nvar fns_5 = fns.zeroPad;\nvar fns_6 = fns.titleCase;\nvar fns_7 = fns.ordinal;\nvar fns_8 = fns.toCardinal;\nvar fns_9 = fns.normalize;\nvar fns_10 = fns.getEpoch;\nvar fns_11 = fns.beADate;\nvar fns_12 = fns.formatTimezone;\n\nconst zeroPad = fns.zeroPad;\n\nconst toString = d =>\n zeroPad(d.getMonth() + 1) + '/' + zeroPad(d.getDate()) + ':' + zeroPad(d.getHours());\n\n// a timezone will begin with a specific offset in january\n// then some will switch to something else between november-march\nconst shouldChange = (epoch, start, end, defaultOffset) => {\n //note: this has a cray order-of-operations issue\n //we can't get the date, without knowing the timezone, and vice-versa\n //it's possible that we can miss a dst-change by a few hours.\n let d = new Date(epoch);\n //(try to mediate this a little?)\n let bias = d.getTimezoneOffset() || 0;\n let shift = bias + defaultOffset * 60; //in minutes\n shift = shift * 60 * 1000; //in ms\n d = new Date(epoch + shift);\n\n let current = toString(d);\n //eg. is it after ~november?\n if (current >= start) {\n //eg. is it before ~march~ too?\n if (current < end) {\n return true\n }\n }\n return false\n};\nvar summerTime = shouldChange;\n\n// this method avoids having to do a full dst-calculation on every operation\n// it reproduces some things in ./index.js, but speeds up spacetime considerably\nconst quickOffset = s => {\n let zones = s.timezones;\n let obj = zones[s.tz];\n if (obj === undefined) {\n console.warn(\"Warning: couldn't find timezone \" + s.tz);\n return 0\n }\n if (obj.dst === undefined) {\n return obj.offset\n }\n\n //get our two possible offsets\n let jul = obj.offset;\n let dec = obj.offset + 1; // assume it's the same for now\n if (obj.hem === 'n') {\n dec = jul - 1;\n }\n let split = obj.dst.split('->');\n let inSummer = summerTime(s.epoch, split[0], split[1], jul);\n if (inSummer === true) {\n return jul\n }\n return dec\n};\nvar quick = quickOffset;\n\nvar _build = {\n\t\"9|s\": \"2/dili,2/jayapura\",\n\t\"9|n\": \"2/chita,2/khandyga,2/pyongyang,2/seoul,2/tokyo,11/palau\",\n\t\"9.5|s|04/07:03->10/06:02\": \"4/adelaide,4/broken_hill,4/south,4/yancowinna\",\n\t\"9.5|s\": \"4/darwin,4/north\",\n\t\"8|s\": \"12/casey,2/kuala_lumpur,2/makassar,2/singapore,4/perth,4/west\",\n\t\"8|n|03/25:03->09/29:23\": \"2/ulan_bator\",\n\t\"8|n\": \"2/brunei,2/choibalsan,2/chongqing,2/chungking,2/harbin,2/hong_kong,2/irkutsk,2/kuching,2/macao,2/macau,2/manila,2/shanghai,2/taipei,2/ujung_pandang,2/ulaanbaatar\",\n\t\"8.75|s\": \"4/eucla\",\n\t\"7|s\": \"12/davis,2/jakarta,9/christmas\",\n\t\"7|n\": \"2/bangkok,2/barnaul,2/ho_chi_minh,2/hovd,2/krasnoyarsk,2/novokuznetsk,2/novosibirsk,2/phnom_penh,2/pontianak,2/saigon,2/tomsk,2/vientiane\",\n\t\"6|s\": \"12/vostok\",\n\t\"6|n\": \"2/almaty,2/bishkek,2/dacca,2/dhaka,2/kashgar,2/omsk,2/qyzylorda,2/thimbu,2/thimphu,2/urumqi,9/chagos\",\n\t\"6.5|n\": \"2/rangoon,9/cocos\",\n\t\"5|s\": \"12/mawson,9/kerguelen\",\n\t\"5|n\": \"2/aqtau,2/aqtobe,2/ashgabat,2/ashkhabad,2/atyrau,2/baku,2/dushanbe,2/karachi,2/oral,2/samarkand,2/tashkent,2/yekaterinburg,9/maldives\",\n\t\"5.75|n\": \"2/kathmandu,2/katmandu\",\n\t\"5.5|n\": \"2/calcutta,2/colombo,2/kolkata\",\n\t\"4|s\": \"9/reunion\",\n\t\"4|n\": \"2/dubai,2/muscat,2/tbilisi,2/yerevan,8/astrakhan,8/samara,8/saratov,8/ulyanovsk,8/volgograd,2/volgograd,9/mahe,9/mauritius\",\n\t\"4.5|n|03/22:00->09/21:24\": \"2/tehran\",\n\t\"4.5|n\": \"2/kabul\",\n\t\"3|s\": \"12/syowa,9/antananarivo\",\n\t\"3|n|03/31:03->10/27:04\": \"2/nicosia,8/athens,8/bucharest,8/helsinki,8/kiev,8/mariehamn,8/nicosia,8/riga,8/sofia,8/tallinn,8/uzhgorod,8/vilnius,8/zaporozhye\",\n\t\"3|n|03/31:02->10/27:03\": \"8/chisinau,8/tiraspol\",\n\t\"3|n|03/31:00->10/26:24\": \"2/beirut\",\n\t\"3|n|03/29:02->10/27:02\": \"2/jerusalem,2/tel_aviv\",\n\t\"3|n|03/29:00->10/26:01\": \"2/gaza,2/hebron\",\n\t\"3|n|03/29:00->10/25:01\": \"2/amman\",\n\t\"3|n|03/29:00->10/24:24\": \"2/damascus\",\n\t\"3|n\": \"0/addis_ababa,0/asmara,0/asmera,0/dar_es_salaam,0/djibouti,0/juba,0/kampala,0/mogadishu,0/nairobi,2/aden,2/baghdad,2/bahrain,2/istanbul,2/kuwait,2/qatar,2/riyadh,8/istanbul,8/kirov,8/minsk,8/moscow,8/simferopol,9/comoro,9/mayotte\",\n\t\"2|s|03/31:02->10/27:02\": \"12/troll\",\n\t\"2|s\": \"0/gaborone,0/harare,0/johannesburg,0/lubumbashi,0/lusaka,0/maputo,0/maseru,0/mbabane\",\n\t\"2|n|03/31:02->10/27:03\": \"0/ceuta,arctic/longyearbyen,3/jan_mayen,8/amsterdam,8/andorra,8/belgrade,8/berlin,8/bratislava,8/brussels,8/budapest,8/busingen,8/copenhagen,8/gibraltar,8/ljubljana,8/luxembourg,8/madrid,8/malta,8/monaco,8/oslo,8/paris,8/podgorica,8/prague,8/rome,8/san_marino,8/sarajevo,8/skopje,8/stockholm,8/tirane,8/vaduz,8/vatican,8/vienna,8/warsaw,8/zagreb,8/zurich\",\n\t\"2|n\": \"0/blantyre,0/bujumbura,0/cairo,0/khartoum,0/kigali,0/tripoli,8/kaliningrad\",\n\t\"1|s|04/02:01->09/03:03\": \"0/windhoek\",\n\t\"1|s\": \"0/kinshasa,0/luanda\",\n\t\"1|n|05/05:03->06/09:02\": \"0/casablanca,0/el_aaiun\",\n\t\"1|n|03/31:01->10/27:02\": \"3/canary,3/faeroe,3/faroe,3/madeira,8/belfast,8/dublin,8/guernsey,8/isle_of_man,8/jersey,8/lisbon,8/london\",\n\t\"1|n\": \"0/algiers,0/bangui,0/brazzaville,0/douala,0/lagos,0/libreville,0/malabo,0/ndjamena,0/niamey,0/porto-novo,0/tunis\",\n\t\"14|n\": \"11/kiritimati\",\n\t\"13|s|04/07:04->09/29:03\": \"11/apia\",\n\t\"13|s|01/15:02->11/05:03\": \"11/tongatapu\",\n\t\"13|n\": \"11/enderbury,11/fakaofo\",\n\t\"12|s|04/07:03->09/29:02\": \"12/mcmurdo,12/south_pole,11/auckland\",\n\t\"12|s|01/13:03->11/10:02\": \"11/fiji\",\n\t\"12|n\": \"2/anadyr,2/kamchatka,2/srednekolymsk,11/funafuti,11/kwajalein,11/majuro,11/nauru,11/tarawa,11/wake,11/wallis\",\n\t\"12.75|s|04/07:03->09/29:02\": \"11/chatham\",\n\t\"11|s\": \"12/macquarie,11/bougainville\",\n\t\"11|n\": \"2/magadan,2/sakhalin,11/efate,11/guadalcanal,11/kosrae,11/noumea,11/pohnpei,11/ponape\",\n\t\"11.5|n\": \"11/norfolk\",\n\t\"10|s|04/07:03->10/06:02\": \"4/act,4/canberra,4/currie,4/hobart,4/melbourne,4/nsw,4/sydney,4/tasmania,4/victoria\",\n\t\"10|s\": \"12/dumontdurville,4/brisbane,4/lindeman,4/queensland\",\n\t\"10|n\": \"2/ust-nera,2/vladivostok,2/yakutsk,11/chuuk,11/guam,11/port_moresby,11/saipan,11/truk,11/yap\",\n\t\"10.5|s|04/07:01->10/06:02\": \"4/lhi,4/lord_howe\",\n\t\"0|n|03/31:00->10/27:01\": \"1/scoresbysund,3/azores\",\n\t\"0|n\": \"0/abidjan,0/accra,0/bamako,0/banjul,0/bissau,0/conakry,0/dakar,0/freetown,0/lome,0/monrovia,0/nouakchott,0/ouagadougou,0/sao_tome,0/timbuktu,1/danmarkshavn,3/reykjavik,3/st_helena,13/gmt,13/gmt+0,13/gmt-0,13/gmt0,13/greenwich,13/utc,13/universal,13/zulu\",\n\t\"-9|n|03/10:02->11/03:02\": \"1/adak,1/atka\",\n\t\"-9|n\": \"11/gambier\",\n\t\"-9.5|n\": \"11/marquesas\",\n\t\"-8|n|03/10:02->11/03:02\": \"1/anchorage,1/juneau,1/metlakatla,1/nome,1/sitka,1/yakutat\",\n\t\"-8|n\": \"11/pitcairn\",\n\t\"-7|n|03/10:02->11/03:02\": \"1/dawson,1/ensenada,1/los_angeles,1/santa_isabel,1/tijuana,1/vancouver,1/whitehorse,6/pacific,6/yukon,10/bajanorte\",\n\t\"-7|n\": \"1/creston,1/dawson_creek,1/hermosillo,1/phoenix\",\n\t\"-6|s|04/06:22->09/07:22\": \"7/easterisland,11/easter\",\n\t\"-6|n|04/07:02->10/27:02\": \"1/chihuahua,1/mazatlan,10/bajasur\",\n\t\"-6|n|03/10:02->11/03:02\": \"1/boise,1/cambridge_bay,1/denver,1/edmonton,1/inuvik,1/ojinaga,1/shiprock,1/yellowknife,6/mountain\",\n\t\"-6|n\": \"1/belize,1/costa_rica,1/el_salvador,1/guatemala,1/managua,1/regina,1/swift_current,1/tegucigalpa,6/east-saskatchewan,6/saskatchewan,11/galapagos\",\n\t\"-5|s\": \"1/lima,1/rio_branco,5/acre\",\n\t\"-5|n|04/07:02->10/27:02\": \"1/bahia_banderas,1/merida,1/mexico_city,1/monterrey,10/general\",\n\t\"-5|n|03/12:03->11/05:01\": \"1/north_dakota\",\n\t\"-5|n|03/10:02->11/03:02\": \"1/chicago,1/knox_in,1/matamoros,1/menominee,1/rainy_river,1/rankin_inlet,1/resolute,1/winnipeg,6/central\",\n\t\"-5|n\": \"1/atikokan,1/bogota,1/cancun,1/cayman,1/coral_harbour,1/eirunepe,1/guayaquil,1/jamaica,1/panama,1/porto_acre\",\n\t\"-4|s|05/13:23->08/13:01\": \"12/palmer\",\n\t\"-4|s|04/06:24->09/08:00\": \"1/santiago,7/continental\",\n\t\"-4|s|03/23:24->10/06:00\": \"1/asuncion\",\n\t\"-4|s|02/16:24->11/03:00\": \"1/campo_grande,1/cuiaba\",\n\t\"-4|s\": \"1/la_paz,1/manaus,5/west\",\n\t\"-4|n|03/12:03->11/05:01\": \"1/indiana,1/kentucky\",\n\t\"-4|n|03/10:02->11/03:02\": \"1/detroit,1/fort_wayne,1/grand_turk,1/indianapolis,1/iqaluit,1/louisville,1/montreal,1/nassau,1/new_york,1/nipigon,1/pangnirtung,1/port-au-prince,1/thunder_bay,1/toronto,6/eastern\",\n\t\"-4|n|03/10:00->11/03:01\": \"1/havana\",\n\t\"-4|n\": \"1/anguilla,1/antigua,1/aruba,1/barbados,1/blanc-sablon,1/boa_vista,1/caracas,1/curacao,1/dominica,1/grenada,1/guadeloupe,1/guyana,1/kralendijk,1/lower_princes,1/marigot,1/martinique,1/montserrat,1/port_of_spain,1/porto_velho,1/puerto_rico,1/santo_domingo,1/st_barthelemy,1/st_kitts,1/st_lucia,1/st_thomas,1/st_vincent,1/tortola,1/virgin\",\n\t\"-3|s\": \"1/argentina,1/buenos_aires,1/cordoba,1/fortaleza,1/montevideo,1/punta_arenas,1/sao_paulo,12/rothera,3/stanley,5/east\",\n\t\"-3|n|03/10:02->11/03:02\": \"1/glace_bay,1/goose_bay,1/halifax,1/moncton,1/thule,3/bermuda,6/atlantic\",\n\t\"-3|n\": \"1/araguaina,1/bahia,1/belem,1/catamarca,1/cayenne,1/jujuy,1/maceio,1/mendoza,1/paramaribo,1/recife,1/rosario,1/santarem\",\n\t\"-2|s\": \"5/denoronha\",\n\t\"-2|n|03/30:22->10/26:23\": \"1/godthab\",\n\t\"-2|n|03/10:02->11/03:02\": \"1/miquelon\",\n\t\"-2|n\": \"1/noronha,3/south_georgia\",\n\t\"-2.5|n|03/10:02->11/03:02\": \"1/st_johns,6/newfoundland\",\n\t\"-1|n\": \"3/cape_verde\",\n\t\"-11|n\": \"11/midway,11/niue,11/pago_pago,11/samoa\",\n\t\"-10|n\": \"11/honolulu,11/johnston,11/rarotonga,11/tahiti\"\n};\n\nvar _build$1 = /*#__PURE__*/Object.freeze({\n\t'default': _build\n});\n\n//prefixes for iana names..\nvar _prefixes = [\n 'africa',\n 'america',\n 'asia',\n 'atlantic',\n 'australia',\n 'brazil',\n 'canada',\n 'chile',\n 'europe',\n 'indian',\n 'mexico',\n 'pacific',\n 'antarctica',\n 'etc'\n];\n\nvar data = getCjsExportFromNamespace(_build$1);\n\nlet all = {};\nObject.keys(data).forEach(k => {\n let split = k.split('|');\n let obj = {\n offset: Number(split[0]),\n hem: split[1]\n };\n if (split[2]) {\n obj.dst = split[2];\n }\n let names = data[k].split(',');\n names.forEach(str => {\n str = str.replace(/(^[0-9]+)\\//, (before, num) => {\n num = Number(num);\n return _prefixes[num] + '/'\n });\n all[str] = obj;\n });\n});\n\nall['utc'] = {\n offset: 0,\n hem: 'n' //(sorry)\n};\n\n//add etc/gmt+n\nfor (let i = -14; i <= 14; i += 0.5) {\n let num = i;\n if (num > 0) {\n num = '+' + num;\n }\n let name = 'etc/gmt' + num;\n all[name] = {\n offset: i * -1, //they're negative!\n hem: 'n' //(sorry)\n };\n name = 'utc/gmt' + num; //this one too, why not.\n all[name] = {\n offset: i * -1,\n hem: 'n'\n };\n}\n// console.log(all)\n\n// console.log(Object.keys(all).length)\nvar unpack = all;\n\n//find the implicit iana code for this machine.\n//safely query the Intl object\n//based on - https://bitbucket.org/pellepim/jstimezonedetect/src\nconst fallbackTZ = 'utc'; //\n\n//this Intl object is not supported often, yet\nconst safeIntl = () => {\n if (typeof Intl === 'undefined' || typeof Intl.DateTimeFormat === 'undefined') {\n return null\n }\n let format = Intl.DateTimeFormat();\n if (typeof format === 'undefined' || typeof format.resolvedOptions === 'undefined') {\n return null\n }\n let timezone = format.resolvedOptions().timeZone;\n if (!timezone) {\n return null\n }\n return timezone.toLowerCase()\n};\n\nconst guessTz = () => {\n let timezone = safeIntl();\n if (timezone === null) {\n return fallbackTZ\n }\n return timezone\n};\n//do it once per computer\nvar guessTz_1 = guessTz;\n\nconst isOffset = /(\\-?[0-9]+)h(rs)?/i;\nconst isNumber = /(\\-?[0-9]+)/;\nconst utcOffset = /utc([\\-+]?[0-9]+)/i;\nconst gmtOffset = /gmt([\\-+]?[0-9]+)/i;\n\nconst toIana = function(num) {\n num = Number(num);\n if (num > -13 && num < 13) {\n num = num * -1; //it's opposite!\n num = (num > 0 ? '+' : '') + num; //add plus sign\n return 'etc/gmt' + num\n }\n return null\n};\n\nconst parseOffset = function(tz) {\n // '+5hrs'\n let m = tz.match(isOffset);\n if (m !== null) {\n return toIana(m[1])\n }\n // 'utc+5'\n m = tz.match(utcOffset);\n if (m !== null) {\n return toIana(m[1])\n }\n // 'GMT-5' (not opposite)\n m = tz.match(gmtOffset);\n if (m !== null) {\n let num = Number(m[1]) * -1;\n return toIana(num)\n }\n // '+5'\n m = tz.match(isNumber);\n if (m !== null) {\n return toIana(m[1])\n }\n return null\n};\nvar parseOffset_1 = parseOffset;\n\nconst local = guessTz_1();\n\n//add all the city names by themselves\nconst cities = Object.keys(unpack).reduce((h, k) => {\n let city = k.split('/')[1] || '';\n city = city.replace(/_/g, ' ');\n h[city] = k;\n return h\n}, {});\n\n//try to match these against iana form\nconst normalize = tz => {\n tz = tz.replace(/ time/g, '');\n tz = tz.replace(/ (standard|daylight|summer)/g, '');\n tz = tz.replace(/\\b(east|west|north|south)ern/g, '$1');\n tz = tz.replace(/\\b(africa|america|australia)n/g, '$1');\n tz = tz.replace(/\\beuropean/g, 'europe');\n tz = tz.replace(/\\islands/g, 'island');\n return tz\n};\n\n// try our best to reconcile the timzone to this given string\nconst lookupTz = (str, zones) => {\n if (!str) {\n return local\n }\n let tz = str.trim();\n let split = str.split('/');\n //support long timezones like 'America/Argentina/Rio_Gallegos'\n if (split.length > 2 && zones.hasOwnProperty(tz) === false) {\n tz = split[0] + '/' + split[1];\n }\n tz = tz.toLowerCase();\n if (zones.hasOwnProperty(tz) === true) {\n return tz\n }\n //lookup more loosely..\n tz = normalize(tz);\n if (zones.hasOwnProperty(tz) === true) {\n return tz\n }\n //try city-names\n if (cities.hasOwnProperty(tz) === true) {\n return cities[tz]\n }\n // //try to parse '-5h'\n if (/[0-9]/.test(tz) === true) {\n let id = parseOffset_1(tz);\n if (id) {\n return id\n }\n }\n\n throw new Error(\n \"Spacetime: Cannot find timezone named: '\" + str + \"'. Please enter an IANA timezone id.\"\n )\n};\nvar find = lookupTz;\n\nlet o = {\n millisecond: 1\n};\no.second = 1000;\no.minute = 60000;\no.hour = 3.6e6; // dst is supported post-hoc\no.day = 8.64e7; //\no.date = o.day;\no.month = 8.64e7 * 29.5; //(average)\no.week = 6.048e8;\no.year = 3.154e10; // leap-years are supported post-hoc\n//add plurals\nObject.keys(o).forEach(k => {\n o[k + 's'] = o[k];\n});\nvar milliseconds = o;\n\n//basically, step-forward/backward until js Date object says we're there.\nconst walk = (s, n, fn, unit, previous) => {\n let current = s.d[fn]();\n if (current === n) {\n return //already there\n }\n let startUnit = previous === null ? null : s.d[previous]();\n let original = s.epoch;\n //try to get it as close as we can\n let diff = n - current;\n s.epoch += milliseconds[unit] * diff;\n\n //DST edge-case: if we are going many days, be a little conservative\n if (unit === 'day' && Math.abs(diff) > 28) {\n //but don't push it over a month\n if (n < 28) {\n s.epoch += milliseconds.hour;\n }\n }\n //repair it if we've gone too far or something\n //(go by half-steps, just in case)\n const halfStep = milliseconds[unit] / 2;\n while (s.d[fn]() < n) {\n s.epoch += halfStep;\n }\n while (s.d[fn]() > n) {\n s.epoch -= halfStep;\n }\n //oops, did we change previous unit? revert it.\n if (previous !== null && startUnit !== s.d[previous]()) {\n // console.warn('spacetime warning: missed setting ' + unit)\n s.epoch = original;\n // i mean, but make it close...\n s.epoch += milliseconds[unit] * diff * 0.89; // i guess?\n }\n};\n//find the desired date by a increment/check while loop\nconst units = {\n year: {\n valid: n => n > -4000 && n < 4000,\n walkTo: (s, n) => walk(s, n, 'getFullYear', 'year', null)\n },\n month: {\n valid: n => n >= 0 && n <= 11,\n walkTo: (s, n) => {\n let d = s.d;\n let current = d.getMonth();\n let original = s.epoch;\n let startUnit = d.getFullYear();\n if (current === n) {\n return\n }\n //try to get it as close as we can..\n let diff = n - current;\n s.epoch += milliseconds.day * (diff * 28); //special case\n //oops, did we change the year? revert it.\n if (startUnit !== s.d.getFullYear()) {\n s.epoch = original;\n }\n //incriment by day\n while (s.d.getMonth() < n) {\n s.epoch += milliseconds.day;\n }\n while (s.d.getMonth() > n) {\n s.epoch -= milliseconds.day;\n }\n }\n },\n date: {\n valid: n => n > 0 && n <= 31,\n walkTo: (s, n) => walk(s, n, 'getDate', 'day', 'getMonth')\n },\n hour: {\n valid: n => n >= 0 && n < 24,\n walkTo: (s, n) => walk(s, n, 'getHours', 'hour', 'getDate')\n },\n minute: {\n valid: n => n >= 0 && n < 60,\n walkTo: (s, n) => walk(s, n, 'getMinutes', 'minute', 'getHours')\n },\n second: {\n valid: n => n >= 0 && n < 60,\n walkTo: (s, n) => {\n //do this one directly\n s.epoch = s.seconds(n).epoch;\n }\n },\n millisecond: {\n valid: n => n >= 0 && n < 1000,\n walkTo: (s, n) => {\n //do this one directly\n s.epoch = s.milliseconds(n).epoch;\n }\n }\n};\n\nconst walkTo = (s, wants) => {\n let keys = Object.keys(units);\n let old = s.clone();\n for (let i = 0; i < keys.length; i++) {\n let k = keys[i];\n let n = wants[k];\n if (n === undefined) {\n n = old[k]();\n }\n if (typeof n === 'string') {\n n = parseInt(n, 10);\n }\n //make-sure it's valid\n if (!units[k].valid(n)) {\n s.epoch = null;\n if (s.silent === false) {\n console.warn('invalid ' + k + ': ' + n);\n }\n return\n }\n // console.log(k, n)\n units[k].walkTo(s, n);\n }\n return\n};\n\nvar walk_1 = walkTo;\n\nlet shortMonths = [\n 'jan',\n 'feb',\n 'mar',\n 'apr',\n 'may',\n 'jun',\n 'jul',\n 'aug',\n 'sept',\n 'oct',\n 'nov',\n 'dec'\n];\nlet longMonths = [\n 'january',\n 'february',\n 'march',\n 'april',\n 'may',\n 'june',\n 'july',\n 'august',\n 'september',\n 'october',\n 'november',\n 'december'\n];\n\nfunction buildMapping() {\n const obj = {\n sep: 8 //support this format\n };\n for (let i = 0; i < shortMonths.length; i++) {\n obj[shortMonths[i]] = i;\n }\n for (let i = 0; i < longMonths.length; i++) {\n obj[longMonths[i]] = i;\n }\n return obj\n}\n\nvar months = {\n short: () => shortMonths,\n long: () => longMonths,\n mapping: () => buildMapping(),\n set: i18n => {\n shortMonths = i18n.short || shortMonths;\n longMonths = i18n.long || longMonths;\n }\n};\n\n//pull-apart ISO offsets, like \"+0100\"\nconst parseOffset$1 = (s, offset) => {\n if (!offset) {\n return s\n }\n //this is a fancy-move\n if (offset === 'Z') {\n offset = '+0000';\n }\n\n // according to ISO8601, tz could be hh:mm, hhmm or hh\n // so need few more steps before the calculation.\n let num = 0;\n\n // for (+-)hh:mm\n if (/^[\\+-]?[0-9]{2}:[0-9]{2}$/.test(offset)) {\n //support \"+01:00\"\n if (/:00/.test(offset) === true) {\n offset = offset.replace(/:00/, '');\n }\n //support \"+01:30\"\n if (/:30/.test(offset) === true) {\n offset = offset.replace(/:30/, '.5');\n }\n }\n\n // for (+-)hhmm\n if (/^[\\+-]?[0-9]{4}$/.test(offset)) {\n offset = offset.replace(/30$/, '.5');\n }\n\n num = parseFloat(offset);\n\n //divide by 100 or 10 - , \"+0100\", \"+01\"\n if (Math.abs(num) > 100) {\n num = num / 100;\n }\n //okay, try to match it to a utc timezone\n //remember - this is opposite! a -5 offset maps to Etc/GMT+5 ¯\\_(:/)_/¯\n //https://askubuntu.com/questions/519550/why-is-the-8-timezone-called-gmt-8-in-the-filesystem\n num *= -1;\n\n if (num >= 0) {\n num = '+' + num;\n }\n let tz = 'etc/gmt' + num;\n let zones = s.timezones;\n\n if (zones[tz]) {\n // log a warning if we're over-writing a given timezone?\n // console.log('changing timezone to: ' + tz)\n s.tz = tz;\n }\n return s\n};\nvar parseOffset_1$1 = parseOffset$1;\n\nconst parseTime = (s, str = '') => {\n str = str.replace(/^\\s+/, '').toLowerCase(); //trim\n //formal time formats - 04:30.23\n let arr = str.match(/([0-9]{1,2}):([0-9]{1,2}):?([0-9]{1,2})?[:\\.]?([0-9]{1,4})?/);\n if (arr !== null) {\n //validate it a little\n let h = Number(arr[1]);\n if (h < 0 || h > 24) {\n return s.startOf('day')\n }\n let m = Number(arr[2]); //don't accept '5:3pm'\n if (arr[2].length < 2 || m < 0 || m > 59) {\n return s.startOf('day')\n }\n s = s.hour(h);\n s = s.minute(m);\n s = s.seconds(arr[3] || 0);\n s = s.millisecond(arr[4] || 0);\n //parse-out am/pm\n let ampm = str.match(/[\\b0-9](am|pm)\\b/);\n if (ampm !== null && ampm[1]) {\n s = s.ampm(ampm[1]);\n }\n return s\n }\n //try an informal form - 5pm (no minutes)\n arr = str.match(/([0-9]+) ?(am|pm)/);\n if (arr !== null && arr[1]) {\n let h = Number(arr[1]);\n //validate it a little..\n if (h > 12 || h < 1) {\n return s.startOf('day')\n }\n s = s.hour(arr[1] || 0);\n s = s.ampm(arr[2]);\n s = s.startOf('hour');\n return s\n }\n //no time info found, use start-of-day\n s = s.startOf('day');\n return s\n};\nvar parseTime_1 = parseTime;\n\nconst monthLengths = [\n 31, // January - 31 days\n 28, // February - 28 days in a common year and 29 days in leap years\n 31, // March - 31 days\n 30, // April - 30 days\n 31, // May - 31 days\n 30, // June - 30 days\n 31, // July - 31 days\n 31, // August - 31 days\n 30, // September - 30 days\n 31, // October - 31 days\n 30, // November - 30 days\n 31 // December - 31 days\n];\nvar monthLengths_1 = monthLengths;\n\nconst isLeapYear = fns.isLeapYear;\n\n//given a month, return whether day number exists in it\nconst hasDate = obj => {\n //invalid values\n if (monthLengths_1.hasOwnProperty(obj.month) !== true) {\n return false\n }\n //support leap-year in february\n if (obj.month === 1) {\n if (isLeapYear(obj.year) && obj.date <= 29) {\n return true\n } else {\n return obj.date <= 28\n }\n }\n //is this date too-big for this month?\n let max = monthLengths_1[obj.month] || 0;\n if (obj.date <= max) {\n return true\n }\n return false\n};\nvar hasDate_1 = hasDate;\n\nconst months$1 = months.mapping();\n\n\n\n\n\nconst parseYear = (str = '') => {\n //support '18 -> 2018\n // str = str.replace(/^'([0-9]{2})/, '20$1')\n // str = str.replace('([0-9]+) ?b\\.?c\\.?$', '-$1')\n let year = parseInt(str.trim(), 10);\n year = year || new Date().getFullYear();\n return year\n};\n\nconst strFmt = [\n //iso-this 1998-05-30T22:00:00:000Z, iso-that 2017-04-03T08:00:00-0700\n {\n reg: /^(\\-?0?0?[0-9]{3,4})-([0-9]{1,2})-([0-9]{1,2})[T| ]([0-9.:]+)(Z|[0-9\\-\\+:]+)?$/,\n parse: (s, arr, givenTz, options) => {\n let month = parseInt(arr[2], 10) - 1;\n let obj = {\n year: arr[1],\n month,\n date: arr[3]\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n parseOffset_1$1(s, arr[5]);\n walk_1(s, obj);\n s = parseTime_1(s, arr[4]);\n return s\n }\n },\n //iso \"2015-03-25\" or \"2015/03/25\" or \"2015/03/25 12:26:14 PM\"\n {\n reg: /^([0-9]{4})[\\-\\/]([0-9]{1,2})[\\-\\/]([0-9]{1,2}),?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i,\n parse: (s, arr) => {\n let obj = {\n year: arr[1],\n month: parseInt(arr[2], 10) - 1,\n date: parseInt(arr[3], 10)\n };\n if (obj.month >= 12) {\n //support yyyy/dd/mm (weird, but ok)\n obj.date = parseInt(arr[2], 10);\n obj.month = parseInt(arr[3], 10) - 1;\n }\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s, arr[4]);\n return s\n }\n },\n //mm/dd/yyyy - uk/canada \"6/28/2019, 12:26:14 PM\"\n {\n reg: /^([0-9]{1,2})[\\-\\/]([0-9]{1,2})[\\-\\/]?([0-9]{4})?,?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i,\n parse: (s, arr) => {\n let month = parseInt(arr[1], 10) - 1;\n let date = parseInt(arr[2], 10);\n //support dd/mm/yyy\n if (s.british || month >= 12) {\n date = parseInt(arr[1], 10);\n month = parseInt(arr[2], 10) - 1;\n }\n let year = arr[3] || new Date().getFullYear();\n let obj = {\n year,\n month,\n date\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s, arr[4]);\n return s\n }\n },\n //common british format - \"25-feb-2015\"\n {\n reg: /^([0-9]{1,2})[\\-\\/]([a-z]+)[\\-\\/]?([0-9]{4})?$/i,\n parse: (s, arr) => {\n let month = months$1[arr[2].toLowerCase()];\n let year = parseYear(arr[3]);\n let obj = {\n year,\n month,\n date: fns.toCardinal(arr[1] || '')\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s, arr[4]);\n return s\n }\n },\n\n //Long \"Mar 25 2015\"\n //February 22, 2017 15:30:00\n {\n reg: /^([a-z]+) ([0-9]{1,2}(?:st|nd|rd|th)?),?( [0-9]{4})?( ([0-9:]+( ?am| ?pm| ?gmt)?))?$/i,\n parse: (s, arr) => {\n let month = months$1[arr[1].toLowerCase()];\n let year = parseYear(arr[3]);\n let obj = {\n year,\n month,\n date: fns.toCardinal(arr[2] || '')\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s, arr[4]);\n return s\n }\n },\n //February 2017 (implied date)\n {\n reg: /^([a-z]+) ([0-9]{4})$/i,\n parse: (s, arr) => {\n let month = months$1[arr[1].toLowerCase()];\n let year = parseYear(arr[2]);\n let obj = {\n year,\n month,\n date: 1\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s, arr[4]);\n return s\n }\n },\n //Long \"25 Mar 2015\"\n {\n reg: /^([0-9]{1,2}(?:st|nd|rd|th)?) ([a-z]+),?( [0-9]{4})?,? ?([0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i,\n parse: (s, arr) => {\n let month = months$1[arr[2].toLowerCase()];\n if (!month) {\n return null\n }\n let year = parseYear(arr[3]);\n let obj = {\n year,\n month,\n date: fns.toCardinal(arr[1])\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s, arr[4]);\n return s\n }\n },\n {\n // '200bc'\n reg: /^[0-9,]+ ?b\\.?c\\.?$/i,\n parse: (s, arr) => {\n let str = arr[0] || '';\n //make negative-year\n str = str.replace(/^([0-9,]+) ?b\\.?c\\.?$/i, '-$1');\n //remove commas\n str = str.replace(/,/g, '');\n let year = parseInt(str.trim(), 10);\n let d = new Date();\n let obj = {\n year,\n month: d.getMonth(),\n date: d.getDate()\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s);\n return s\n }\n },\n {\n // '200ad'\n reg: /^[0-9,]+ ?(a\\.?d\\.?|c\\.?e\\.?)$/i,\n parse: (s, arr) => {\n let str = arr[0] || '';\n //remove commas\n str = str.replace(/,/g, '');\n let year = parseInt(str.trim(), 10);\n let d = new Date();\n let obj = {\n year,\n month: d.getMonth(),\n date: d.getDate()\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s);\n return s\n }\n },\n {\n // '1992'\n reg: /^[0-9]{4}( ?a\\.?d\\.?)?$/i,\n parse: (s, arr) => {\n let year = parseYear(arr[0]);\n let d = new Date();\n let obj = {\n year,\n month: d.getMonth(),\n date: d.getDate()\n };\n if (hasDate_1(obj) === false) {\n s.epoch = null;\n return s\n }\n walk_1(s, obj);\n s = parseTime_1(s);\n return s\n }\n }\n];\n\nvar strParse = strFmt;\n\nconst dates = {\n now: s => {\n s.epoch = Date.now();\n return s\n },\n tonight: s => {\n s.epoch = Date.now();\n s = s.hour(18);\n return s\n },\n today: s => {\n s.epoch = Date.now();\n return s\n },\n tomorrow: s => {\n s.epoch = Date.now();\n s = s.add(1, 'day');\n s = s.startOf('day');\n return s\n },\n yesterday: s => {\n s.epoch = Date.now();\n s = s.subtract(1, 'day');\n s = s.startOf('day');\n return s\n },\n christmas: s => {\n let year = new Date().getFullYear();\n s = s.set([year, 11, 25, 18, 0, 0]); // Dec 25\n return s\n },\n 'new years': s => {\n let year = new Date().getFullYear();\n s = s.set([year, 11, 31, 18, 0, 0]); // Dec 31\n return s\n }\n};\ndates['new years eve'] = dates['new years'];\nvar namedDates = dates;\n\n//we have to actually parse these inputs ourselves\n// - can't use built-in js parser ;(\n//=========================================\n// ISO Date\t \"2015-03-25\"\n// Short Date\t\"03/25/2015\" or \"2015/03/25\"\n// Long Date\t\"Mar 25 2015\" or \"25 Mar 2015\"\n// Full Date\t\"Wednesday March 25 2015\"\n//=========================================\n\n//-- also -\n// if the given epoch is really small, they've probably given seconds and not milliseconds\n// anything below this number is likely (but not necessarily) a mistaken input.\n// this may seem like an arbitrary number, but it's 'within jan 1970'\n// this is only really ambiguous until 2054 or so\nconst minimumEpoch = 2500000000;\n\nconst defaults = {\n year: new Date().getFullYear(),\n month: 0,\n date: 1\n};\n\n//support [2016, 03, 01] format\nconst handleArray = (s, arr) => {\n let order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond'];\n for (let i = 0; i < order.length; i++) {\n let num = arr[i] || defaults[order[i]] || 0;\n s = s[order[i]](num);\n }\n return s\n};\n//support {year:2016, month:3} format\nconst handleObject = (s, obj) => {\n obj = Object.assign({}, defaults, obj);\n let keys = Object.keys(obj);\n for (let i = 0; i < keys.length; i++) {\n let unit = keys[i];\n //make sure we have this method\n if (s[unit] === undefined || typeof s[unit] !== 'function') {\n continue\n }\n //make sure the value is a number\n if (obj[unit] === null || obj[unit] === undefined || obj[unit] === '') {\n continue\n }\n let num = obj[unit] || defaults[unit] || 0;\n s = s[unit](num);\n }\n return s\n};\n\n//find the epoch from different input styles\nconst parseInput = (s, input, givenTz) => {\n //if we've been given a epoch number, it's easy\n if (typeof input === 'number') {\n if (input > 0 && input < minimumEpoch && s.silent === false) {\n console.warn(' - Warning: You are setting the date to January 1970.');\n console.warn(' - did input seconds instead of milliseconds?');\n }\n s.epoch = input;\n return s\n }\n //set tmp time\n s.epoch = Date.now();\n if (input === null || input === undefined) {\n return s //k, we're good.\n }\n //support input of Date() object\n if (fns.isDate(input) === true) {\n s.epoch = input.getTime();\n return s\n }\n //support [2016, 03, 01] format\n if (fns.isArray(input) === true) {\n s = handleArray(s, input);\n return s\n }\n //support {year:2016, month:3} format\n if (fns.isObject(input) === true) {\n //support spacetime object as input\n if (input.epoch) {\n s.epoch = input.epoch;\n s.tz = input.tz;\n return s\n }\n s = handleObject(s, input);\n return s\n }\n //input as a string..\n if (typeof input !== 'string') {\n return s\n }\n //little cleanup..\n input = input.replace(/\\b(mon|tues|wed|wednes|thu|thurs|fri|sat|satur|sun)(day)?\\b/i, '');\n input = input.replace(/,/g, '');\n input = input.replace(/ +/g, ' ').trim();\n //try some known-words, like 'now'\n if (namedDates.hasOwnProperty(input) === true) {\n s = namedDates[input](s);\n return s\n }\n //try each text-parse template, use the first good result\n for (let i = 0; i < strParse.length; i++) {\n let m = input.match(strParse[i].reg);\n if (m) {\n let res = strParse[i].parse(s, m, givenTz);\n if (res !== null) {\n return res\n }\n }\n }\n if (s.silent === false) {\n console.warn(\"Warning: couldn't parse date-string: '\" + input + \"'\");\n }\n s.epoch = null;\n return s\n};\nvar input = parseInput;\n\nlet shortDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];\nlet longDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];\n\nvar days = {\n short: () => shortDays,\n long: () => longDays,\n set: i18n => {\n shortDays = i18n.short || shortDays;\n longDays = i18n.long || longDays;\n }\n};\n\n// create the timezone offset part of an iso timestamp\n// it's kind of nuts how involved this is\n// \"+01:00\", \"+0100\", or simply \"+01\"\nconst isoOffset = s => {\n let offset = s.timezone().current.offset;\n const isNegative = offset < 0;\n let minute = '00';\n //handle 5.5 → '5:30'\n if (Math.abs(offset % 1) === 0.5) {\n minute = '30';\n if (offset >= 0) {\n offset = Math.floor(offset);\n } else {\n offset = Math.ceil(offset);\n }\n }\n if (isNegative) {\n //handle negative sign\n offset *= -1;\n offset = fns.zeroPad(offset, 2);\n offset = '-' + offset;\n } else {\n offset = fns.zeroPad(offset, 2);\n offset = '+' + offset;\n }\n offset = offset + ':' + minute;\n //'Z' means 00\n if (offset === '+00:00') {\n offset = 'Z';\n }\n return offset\n};\n\nvar _offset = isoOffset;\n\nconst format = {\n day: s => fns.titleCase(s.dayName()),\n 'day-short': s => fns.titleCase(days.short()[s.day()]),\n 'day-number': s => s.day(),\n 'day-ordinal': s => fns.ordinal(s.day()),\n 'day-pad': s => fns.zeroPad(s.day()),\n\n date: s => s.date(),\n 'date-ordinal': s => fns.ordinal(s.date()),\n 'date-pad': s => fns.zeroPad(s.date()),\n\n month: s => fns.titleCase(s.monthName()),\n 'month-short': s => fns.titleCase(months.short()[s.month()]),\n 'month-number': s => s.month(),\n 'month-ordinal': s => fns.ordinal(s.month()),\n 'month-pad': s => fns.zeroPad(s.month()),\n 'iso-month': s => fns.zeroPad(s.month() + 1), //1-based months\n\n year: s => {\n let year = s.year();\n if (year > 0) {\n return year\n }\n year = Math.abs(year);\n return year + ' BC'\n },\n 'year-short': s => {\n let year = s.year();\n if (year > 0) {\n return `'${String(s.year()).substr(2, 4)}`\n }\n year = Math.abs(year);\n return year + ' BC'\n },\n 'iso-year': s => {\n let year = s.year();\n let isNegative = year < 0;\n let str = fns.zeroPad(Math.abs(year), 4); //0-padded\n if (isNegative) {\n //negative years are for some reason 6-digits ('-00008')\n str = fns.zeroPad(str, 6);\n str = '-' + str;\n }\n return str\n },\n\n time: s => s.time(),\n 'time-24': s => `${s.hour24()}:${fns.zeroPad(s.minute())}`,\n hour: s => s.hour12(),\n 'hour-pad': s => fns.zeroPad(s.hour12()),\n 'hour-24': s => s.hour24(),\n 'hour-24-pad': s => fns.zeroPad(s.hour24()),\n\n minute: s => s.minute(),\n 'minute-pad': s => fns.zeroPad(s.minute()),\n second: s => s.second(),\n 'second-pad': s => fns.zeroPad(s.second()),\n\n ampm: s => s.ampm(),\n quarter: s => 'Q' + s.quarter(),\n season: s => s.season(),\n era: s => s.era(),\n json: s => s.json(),\n timezone: s => s.timezone().name,\n offset: s => _offset(s),\n\n numeric: s => `${s.year()}/${fns.zeroPad(s.month() + 1)}/${fns.zeroPad(s.date())}`, // yyyy/mm/dd\n 'numeric-us': s => `${fns.zeroPad(s.month() + 1)}/${fns.zeroPad(s.date())}/${s.year()}`, // mm/dd/yyyy\n 'numeric-uk': s => `${fns.zeroPad(s.date())}/${fns.zeroPad(s.month() + 1)}/${s.year()}`, //dd/mm/yyyy\n 'mm/dd': s => `${fns.zeroPad(s.month() + 1)}/${fns.zeroPad(s.date())}`, //mm/dd\n\n // ... https://en.wikipedia.org/wiki/ISO_8601 ;(((\n iso: s => {\n let year = s.format('iso-year');\n let month = fns.zeroPad(s.month() + 1); //1-based months\n let date = fns.zeroPad(s.date());\n let hour = fns.zeroPad(s.h24());\n let minute = fns.zeroPad(s.minute());\n let second = fns.zeroPad(s.second());\n let ms = fns.zeroPad(s.millisecond(), 3);\n let offset = _offset(s);\n return `${year}-${month}-${date}T${hour}:${minute}:${second}.${ms}${offset}` //2018-03-09T08:50:00.000-05:00\n },\n 'iso-short': s => {\n let month = fns.zeroPad(s.month() + 1); //1-based months\n let date = fns.zeroPad(s.date());\n return `${s.year()}-${month}-${date}` //2017-02-15\n },\n 'iso-utc': s => {\n return new Date(s.epoch).toISOString() //2017-03-08T19:45:28.367Z\n },\n\n //i made these up\n nice: s => `${months.short()[s.month()]} ${fns.ordinal(s.date())}, ${s.time()}`,\n 'nice-year': s => `${months.short()[s.month()]} ${fns.ordinal(s.date())}, ${s.year()}`,\n 'nice-day': s =>\n `${days.short()[s.day()]} ${fns.titleCase(months.short()[s.month()])} ${fns.ordinal(s.date())}`,\n 'nice-full': s =>\n `${s.dayName()} ${fns.titleCase(s.monthName())} ${fns.ordinal(s.date())}, ${s.time()}`\n};\n//aliases\nconst aliases = {\n 'day-name': 'day',\n 'month-name': 'month',\n 'iso 8601': 'iso',\n 'time-h24': 'time-24',\n 'time-12': 'time',\n 'time-h12': 'time',\n tz: 'timezone',\n 'day-num': 'day-number',\n 'month-num': 'month-number',\n 'month-iso': 'iso-month',\n 'year-iso': 'iso-year',\n 'nice-short': 'nice',\n mdy: 'numeric-us',\n dmy: 'numeric-uk',\n ymd: 'numeric',\n 'yyyy/mm/dd': 'numeric',\n 'mm/dd/yyyy': 'numeric-us',\n 'dd/mm/yyyy': 'numeric-us',\n 'little-endian': 'numeric-uk',\n 'big-endian': 'numeric',\n 'day-nice': 'nice-day'\n};\nObject.keys(aliases).forEach(k => (format[k] = format[aliases[k]]));\n\nconst printFormat = (s, str = '') => {\n //don't print anything if it's an invalid date\n if (s.isValid() !== true) {\n return ''\n }\n //support .format('month')\n if (format.hasOwnProperty(str)) {\n let out = format[str](s) || '';\n if (str !== 'json') {\n out = String(out);\n if (str !== 'ampm') {\n out = fns.titleCase(out);\n }\n }\n return out\n }\n //support '{hour}:{minute}' notation\n if (str.indexOf('{') !== -1) {\n let sections = /\\{(.+?)\\}/g;\n str = str.replace(sections, (_, fmt) => {\n fmt = fmt.toLowerCase().trim();\n if (format.hasOwnProperty(fmt)) {\n return String(format[fmt](s) || '')\n }\n return ''\n });\n return str\n }\n\n return s.format('iso-short')\n};\nvar format_1 = printFormat;\n\nconst pad = fns.zeroPad;\nconst formatTimezone = fns.formatTimezone;\n//parse this insane unix-time-templating thing, from the 19th century\n//http://unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns\n\n//time-symbols we support\nconst mapping = {\n G: s => s.era(),\n GG: s => s.era(),\n GGG: s => s.era(),\n GGGG: s => (s.era() === 'AD' ? 'Anno Domini' : 'Before Christ'),\n //year\n y: s => s.year(),\n yy: s => {\n //last two chars\n return parseInt(String(s.year()).substr(2, 4), 10)\n },\n yyy: s => s.year(),\n yyyy: s => s.year(),\n yyyyy: s => '0' + s.year(),\n // u: (s) => {},//extended non-gregorian years\n\n //quarter\n Q: s => s.quarter(),\n QQ: s => s.quarter(),\n QQQ: s => s.quarter(),\n QQQQ: s => s.quarter(),\n\n //month\n M: s => s.month() + 1,\n MM: s => pad(s.month() + 1),\n MMM: s => s.format('month-short'),\n MMMM: s => s.format('month'),\n\n //week\n w: s => s.week(),\n ww: s => pad(s.week()),\n //week of month\n // W: (s) => s.week(),\n\n //date of month\n d: s => s.date(),\n dd: s => pad(s.date()),\n //date of year\n D: s => s.dayOfYear(),\n DD: s => pad(s.dayOfYear()),\n DDD: s => pad(s.dayOfYear(), 3),\n\n // F: (s) => {},//date of week in month\n // g: (s) => {},//modified julian day\n\n //day\n E: s => s.format('day-short'),\n EE: s => s.format('day-short'),\n EEE: s => s.format('day-short'),\n EEEE: s => s.format('day'),\n EEEEE: s => s.format('day')[0],\n e: s => s.day(),\n ee: s => s.day(),\n eee: s => s.format('day-short'),\n eeee: s => s.format('day'),\n eeeee: s => s.format('day')[0],\n\n //am/pm\n a: s => s.ampm().toUpperCase(),\n aa: s => s.ampm().toUpperCase(),\n aaa: s => s.ampm().toUpperCase(),\n aaaa: s => s.ampm().toUpperCase(),\n\n //hour\n h: s => s.h12(),\n hh: s => pad(s.h12()),\n H: s => s.hour(),\n HH: s => pad(s.hour()),\n // j: (s) => {},//weird hour format\n\n m: s => s.minute(),\n mm: s => pad(s.minute()),\n s: s => s.second(),\n ss: s => pad(s.second()),\n //milliseconds in the day\n A: s => s.epoch - s.startOf('day').epoch,\n //timezone\n z: s => s.timezone().name,\n zz: s => s.timezone().name,\n zzz: s => s.timezone().name,\n zzzz: s => s.timezone().name,\n Z: s => formatTimezone(s.timezone().current.offset),\n ZZ: s => formatTimezone(s.timezone().current.offset),\n ZZZ: s => formatTimezone(s.timezone().current.offset),\n ZZZZ: s => formatTimezone(s.timezone().current.offset, ':')\n};\n\nconst addAlias = (char, to, n) => {\n let name = char;\n let toName = to;\n for (let i = 0; i < n; i += 1) {\n mapping[name] = mapping[toName];\n name += char;\n toName += to;\n }\n};\naddAlias('q', 'Q', 4);\naddAlias('L', 'M', 4);\naddAlias('Y', 'y', 4);\naddAlias('c', 'e', 4);\naddAlias('k', 'H', 2);\naddAlias('K', 'h', 2);\naddAlias('S', 's', 2);\naddAlias('v', 'z', 4);\naddAlias('V', 'Z', 4);\n\nconst unixFmt = (s, str) => {\n let chars = str.split('');\n //combine consecutive chars, like 'yyyy' as one.\n let arr = [chars[0]];\n let quoteOn = false;\n for (let i = 1; i < chars.length; i += 1) {\n //support quoted substrings\n if (chars[i] === `'`) {\n quoteOn = !quoteOn;\n //support '', meaning one tick\n if (quoteOn === true && chars[i + 1] && chars[i + 1] === \"'\") {\n quoteOn = true;\n } else {\n continue\n }\n }\n //merge it with the last one\n if (quoteOn === true || chars[i] === arr[arr.length - 1][0]) {\n arr[arr.length - 1] += chars[i];\n } else {\n arr.push(chars[i]);\n }\n }\n return arr.reduce((txt, c) => {\n if (mapping[c] !== undefined) {\n txt += mapping[c](s) || '';\n } else {\n txt += c;\n }\n return txt\n }, '')\n};\nvar unixFmt_1 = unixFmt;\n\nconst units$1 = ['year', 'season', 'quarter', 'month', 'week', 'day', 'quarterHour', 'hour', 'minute'];\n\nconst doUnit = function(s, k) {\n let start = s.clone().startOf(k);\n let end = s.clone().endOf(k);\n let duration = end.epoch - start.epoch;\n let percent = (s.epoch - start.epoch) / duration;\n return parseFloat(percent.toFixed(2))\n};\n\n//how far it is along, from 0-1\nconst progress = (s, unit) => {\n if (unit) {\n unit = fns.normalize(unit);\n return doUnit(s, unit)\n }\n let obj = {};\n units$1.forEach(k => {\n obj[k] = doUnit(s, k);\n });\n return obj\n};\n\nvar progress_1 = progress;\n\n//round to either current, or +1 of this unit\nconst nearest = (s, unit) => {\n //how far have we gone?\n let prog = s.progress();\n unit = fns.normalize(unit);\n //fix camel-case for this one\n if (unit === 'quarterhour') {\n unit = 'quarterHour';\n }\n if (prog[unit] !== undefined) {\n // go forward one?\n if (prog[unit] > 0.5) {\n s = s.add(1, unit);\n }\n // go to start\n s = s.startOf(unit);\n } else if (s.silent === false) {\n console.warn(\"no known unit '\" + unit + \"'\");\n }\n return s\n};\nvar nearest_1 = nearest;\n\n//increment until dates are the same\nconst climb = (a, b, unit) => {\n let i = 0;\n a = a.clone();\n while (a.isBefore(b)) {\n //do proper, expensive increment to catch all-the-tricks\n a = a.add(1, unit);\n i += 1;\n }\n //oops, we went too-far..\n if (a.isAfter(b, unit)) {\n i -= 1;\n }\n return i\n};\n\n// do a thurough +=1 on the unit, until they match\n// for speed-reasons, only used on day, month, week.\nconst diffOne = (a, b, unit) => {\n if (a.isBefore(b)) {\n return climb(a, b, unit)\n } else {\n return climb(b, a, unit) * -1 //reverse it\n }\n};\n\nvar one = diffOne;\n\n// don't do anything too fancy here.\n// 2020 - 2019 may be 1 year, or 0 years\n// - '1 year difference' means 366 days during a leap year\nconst fastYear = (a, b) => {\n let years = b.year() - a.year();\n // should we decrement it by 1?\n a = a.year(b.year());\n if (a.isAfter(b)) {\n years -= 1;\n }\n return years\n};\n\n// use a waterfall-method for computing a diff of any 'pre-knowable' units\n// compute years, then compute months, etc..\n// ... then ms-math for any very-small units\nconst diff = function(a, b) {\n // an hour is always the same # of milliseconds\n // so these units can be 'pre-calculated'\n let msDiff = b.epoch - a.epoch;\n let obj = {\n milliseconds: msDiff,\n seconds: parseInt(msDiff / 1000, 10)\n };\n obj.minutes = parseInt(obj.seconds / 60, 10);\n obj.hours = parseInt(obj.minutes / 60, 10);\n\n //do the year\n let tmp = a.clone();\n obj.years = fastYear(tmp, b);\n tmp = a.add(obj.years, 'year');\n\n //there's always 12 months in a year...\n obj.months = obj.years * 12;\n tmp = a.add(obj.months, 'month');\n obj.months += one(tmp, b, 'month');\n\n // there's always atleast 52 weeks in a year..\n // (month * 4) isn't as close\n obj.weeks = obj.years * 52;\n tmp = a.add(obj.weeks, 'week');\n obj.weeks += one(tmp, b, 'week');\n\n // there's always atleast 7 days in a week\n obj.days = obj.weeks * 7;\n tmp = a.add(obj.days, 'day');\n obj.days += one(tmp, b, 'day');\n\n return obj\n};\nvar waterfall = diff;\n\nconst reverseDiff = function(obj) {\n Object.keys(obj).forEach(k => {\n obj[k] *= -1;\n });\n return obj\n};\n\n// this method counts a total # of each unit, between a, b.\n// '1 month' means 28 days in february\n// '1 year' means 366 days in a leap year\nconst main = function(a, b, unit) {\n b = fns.beADate(b, a);\n //reverse values, if necessary\n let reversed = false;\n if (a.isAfter(b)) {\n let tmp = a;\n a = b;\n b = tmp;\n reversed = true;\n }\n //compute them all (i know!)\n let obj = waterfall(a, b);\n if (reversed) {\n obj = reverseDiff(obj);\n }\n //return just the requested unit\n if (unit) {\n //make sure it's plural-form\n unit = fns.normalize(unit);\n if (/s$/.test(unit) !== true) {\n unit += 's';\n }\n if (unit === 'dates') {\n unit = 'days';\n }\n return obj[unit]\n }\n return obj\n};\n\nvar diff$1 = main;\n\n//by spencermountain + Shaun Grady\n\n//our conceptual 'break-points' for each unit\nconst qualifiers = {\n months: {\n almost: 10,\n over: 4\n },\n days: {\n almost: 25,\n over: 10\n },\n hours: {\n almost: 20,\n over: 8\n },\n minutes: {\n almost: 50,\n over: 20\n },\n seconds: {\n almost: 50,\n over: 20\n }\n};\n\n//get number of hours/minutes... between the two dates\nfunction getDiff(a, b) {\n const isBefore = a.isBefore(b);\n const later = isBefore ? b : a;\n let earlier = isBefore ? a : b;\n earlier = earlier.clone();\n const diff = {\n years: 0,\n months: 0,\n days: 0,\n hours: 0,\n minutes: 0,\n seconds: 0\n };\n Object.keys(diff).forEach(unit => {\n if (earlier.isSame(later, unit)) {\n return\n }\n let max = earlier.diff(later, unit);\n earlier = earlier.add(max, unit);\n diff[unit] = max;\n });\n\n //reverse it, if necessary\n if (isBefore) {\n Object.keys(diff).forEach(u => {\n if (diff[u] !== 0) {\n diff[u] *= -1;\n }\n });\n }\n return diff\n}\n\n// Expects a plural unit arg\nfunction pluralize(value, unit) {\n if (value === 1) {\n unit = unit.slice(0, -1);\n }\n return value + ' ' + unit\n}\n\n//create the human-readable diff between the two dates\nconst since = (start, end) => {\n end = fns.beADate(end, start);\n const diff = getDiff(start, end);\n const isNow = Object.keys(diff).every(u => !diff[u]);\n if (isNow === true) {\n return {\n diff,\n rounded: 'now',\n qualified: 'now',\n precise: 'now'\n }\n }\n let rounded;\n let qualified;\n let precise;\n let englishValues = [];\n\n //go through each value and create its text-representation\n Object.keys(diff).forEach((unit, i, units) => {\n const value = Math.abs(diff[unit]);\n if (value === 0) {\n return\n }\n const englishValue = pluralize(value, unit);\n englishValues.push(englishValue);\n if (!rounded) {\n rounded = qualified = englishValue;\n if (i > 4) {\n return\n }\n //is it a 'almost' something, etc?\n const nextUnit = units[i + 1];\n const nextValue = Math.abs(diff[nextUnit]);\n if (nextValue > qualifiers[nextUnit].almost) {\n rounded = pluralize(value + 1, unit);\n qualified = 'almost ' + rounded;\n } else if (nextValue > qualifiers[nextUnit].over) qualified = 'over ' + englishValue;\n }\n });\n //make them into a string\n precise = englishValues.splice(0, 2).join(', ');\n //handle before/after logic\n if (start.isAfter(end) === true) {\n rounded += ' ago';\n qualified += ' ago';\n precise += ' ago';\n } else {\n rounded = 'in ' + rounded;\n qualified = 'in ' + qualified;\n precise = 'in ' + precise;\n }\n return {\n diff,\n rounded,\n qualified,\n precise\n }\n};\n\nvar since_1 = since;\n\n//https://www.timeanddate.com/calendar/aboutseasons.html\n// Spring - from March 1 to May 31;\n// Summer - from June 1 to August 31;\n// Fall (autumn) - from September 1 to November 30; and,\n// Winter - from December 1 to February 28 (February 29 in a leap year).\nvar seasons = {\n north: [\n ['spring', 2, 1], //spring march 1\n ['summer', 5, 1], //june 1\n ['fall', 8, 1], //sept 1\n ['autumn', 8, 1], //sept 1\n ['winter', 11, 1] //dec 1\n ],\n south: [\n ['fall', 2, 1], //march 1\n ['autumn', 2, 1], //march 1\n ['winter', 5, 1], //june 1\n ['spring', 8, 1], //sept 1\n ['summer', 11, 1] //dec 1\n ]\n};\n\nvar quarters = [\n null,\n [0, 1], //jan 1\n [3, 1], //apr 1\n [6, 1], //july 1\n [9, 1] //oct 1\n];\n\nconst units$2 = {\n minute: s => {\n walk_1(s, {\n second: 0,\n millisecond: 0\n });\n return s\n },\n quarterhour: s => {\n let minute = s.minutes();\n if (minute >= 45) {\n s = s.minutes(45);\n } else if (minute >= 30) {\n s = s.minutes(30);\n } else if (minute >= 15) {\n s = s.minutes(15);\n } else {\n s = s.minutes(0);\n }\n walk_1(s, {\n second: 0,\n millisecond: 0\n });\n return s\n },\n hour: s => {\n walk_1(s, {\n minute: 0,\n second: 0,\n millisecond: 0\n });\n return s\n },\n day: s => {\n walk_1(s, {\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0\n });\n return s\n },\n week: s => {\n let original = s.clone();\n s = s.day(s._weekStart); //monday\n if (s.isAfter(original)) {\n s = s.subtract(1, 'week');\n }\n walk_1(s, {\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0\n });\n return s\n },\n month: s => {\n walk_1(s, {\n date: 1,\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0\n });\n return s\n },\n quarter: s => {\n let q = s.quarter();\n if (quarters[q]) {\n walk_1(s, {\n month: quarters[q][0],\n date: quarters[q][1],\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0\n });\n }\n return s\n },\n season: s => {\n let current = s.season();\n let hem = 'north';\n if (s.hemisphere() === 'South') {\n hem = 'south';\n }\n for (let i = 0; i < seasons[hem].length; i++) {\n if (seasons[hem][i][0] === current) {\n //winter goes between years\n let year = s.year();\n if (current === 'winter' && s.month() < 3) {\n year -= 1;\n }\n walk_1(s, {\n year,\n month: seasons[hem][i][1],\n date: seasons[hem][i][2],\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0\n });\n return s\n }\n }\n return s\n },\n year: s => {\n walk_1(s, {\n month: 0,\n date: 1,\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0\n });\n return s\n },\n decade: s => {\n s = s.startOf('year');\n let year = s.year();\n let decade = parseInt(year / 10, 10) * 10;\n s = s.year(decade);\n return s\n },\n century: s => {\n s = s.startOf('year');\n let year = s.year();\n // near 0AD goes '-1 | +1'\n let decade = parseInt(year / 100, 10) * 100;\n s = s.year(decade);\n return s\n }\n};\nunits$2.date = units$2.day;\n\nconst startOf = (a, unit) => {\n let s = a.clone();\n unit = fns.normalize(unit);\n if (units$2[unit]) {\n return units$2[unit](s)\n }\n if (unit === 'summer' || unit === 'winter') {\n s = s.season(unit);\n return units$2.season(s)\n }\n return s\n};\n\n//piggy-backs off startOf\nconst endOf = (a, unit) => {\n let s = a.clone();\n unit = fns.normalize(unit);\n if (units$2[unit]) {\n s = units$2[unit](s);\n s = s.add(1, unit);\n s = s.subtract(1, 'milliseconds');\n return s\n }\n return s\n};\nvar startOf_1 = {\n startOf,\n endOf\n};\n\n//is it 'wednesday'?\nconst isDay = function(unit) {\n if (days.short().find(s => s === unit)) {\n return true\n }\n if (days.long().find(s => s === unit)) {\n return true\n }\n return false\n};\n\n// return a list of the weeks/months/days between a -> b\n// returns spacetime objects in the timezone of the input\nconst every = function(start, unit = '', end) {\n if (!unit || !end) {\n return []\n }\n //cleanup unit param\n unit = fns.normalize(unit);\n //cleanup to param\n end = start.clone().set(end);\n //swap them, if they're backwards\n if (start.isAfter(end)) {\n let tmp = start;\n start = end;\n end = tmp;\n }\n\n //support 'every wednesday'\n let d = start.clone();\n if (isDay(unit)) {\n d = d.next(unit);\n unit = 'week';\n } else {\n d = d.next(unit);\n }\n //okay, actually start doing it\n let result = [];\n while (d.isBefore(end)) {\n result.push(d);\n d = d.add(1, unit);\n }\n return result\n};\nvar every_1 = every;\n\nconst parseDst = dst => {\n if (!dst) {\n return []\n }\n return dst.split('->')\n};\n\nconst titleCase = str => {\n str = str[0].toUpperCase() + str.substr(1);\n str = str.replace(/\\/gmt/, '/GMT');\n str = str.replace(/[\\/_]([a-z])/gi, s => {\n return s.toUpperCase()\n });\n return str\n};\n\n//get metadata about this timezone\nconst timezone = s => {\n let zones = s.timezones;\n let tz = s.tz;\n if (zones.hasOwnProperty(tz) === false) {\n tz = find(s.tz, zones);\n }\n if (tz === null) {\n if (s.silent === false) {\n console.warn(\"Warn: could not find given or local timezone - '\" + s.tz + \"'\");\n }\n return {\n current: {\n epochShift: 0\n }\n }\n }\n let found = zones[tz];\n let result = {\n name: titleCase(tz),\n hasDst: Boolean(found.dst),\n default_offset: found.offset,\n //do north-hemisphere version as default (sorry!)\n hemisphere: found.hem === 's' ? 'South' : 'North',\n current: {}\n };\n\n if (result.hasDst) {\n let arr = parseDst(found.dst);\n result.change = {\n start: arr[0],\n back: arr[1]\n };\n }\n //find the offsets for summer/winter times\n //(these variable names are north-centric)\n let summer = found.offset; // (july)\n let winter = summer; // (january) assume it's the same for now\n if (result.hasDst === true) {\n if (result.hemisphere === 'North') {\n winter = summer - 1;\n } else {\n //southern hemisphere\n winter = found.offset + 1;\n }\n }\n\n //find out which offset to use right now\n //use 'summer' time july-time\n if (result.hasDst === false) {\n result.current.offset = summer;\n result.current.isDST = false;\n } else if (summerTime(s.epoch, result.change.start, result.change.back, summer) === true) {\n result.current.offset = summer;\n result.current.isDST = result.hemisphere === 'North'; //dst 'on' in winter in north\n } else {\n //use 'winter' january-time\n result.current.offset = winter;\n result.current.isDST = result.hemisphere === 'South'; //dst 'on' in summer in south\n }\n return result\n};\nvar timezone_1 = timezone;\n\nconst units$3 = [\n 'century',\n 'decade',\n 'year',\n 'month',\n 'date',\n 'day',\n 'hour',\n 'minute',\n 'second',\n 'millisecond'\n];\n\n//the spacetime instance methods (also, the API)\nconst methods = {\n set: function(input$1, tz) {\n let s = this.clone();\n s = input(s, input$1);\n if (tz) {\n this.tz = find(tz);\n }\n return s\n },\n timezone: function() {\n return timezone_1(this)\n },\n isDST: function() {\n return timezone_1(this).current.isDST\n },\n hasDST: function() {\n return timezone_1(this).hasDst\n },\n offset: function() {\n return timezone_1(this).current.offset * 60\n },\n hemisphere: function() {\n return timezone_1(this).hemisphere\n },\n format: function(fmt) {\n return format_1(this, fmt)\n },\n unixFmt: function(fmt) {\n return unixFmt_1(this, fmt)\n },\n startOf: function(unit) {\n return startOf_1.startOf(this, unit)\n },\n endOf: function(unit) {\n return startOf_1.endOf(this, unit)\n },\n leapYear: function() {\n let year = this.year();\n return fns.isLeapYear(year)\n },\n progress: function(unit) {\n return progress_1(this, unit)\n },\n nearest: function(unit) {\n return nearest_1(this, unit)\n },\n diff: function(d, unit) {\n return diff$1(this, d, unit)\n },\n since: function(d) {\n if (!d) {\n d = this.clone().set();\n }\n return since_1(this, d)\n },\n next: function(unit) {\n let s = this.add(1, unit);\n return s.startOf(unit)\n },\n //the start of the previous year/week/century\n last: function(unit) {\n let s = this.subtract(1, unit);\n return s.startOf(unit)\n },\n isValid: function() {\n //null/undefined epochs\n if (!this.epoch && this.epoch !== 0) {\n return false\n }\n return !isNaN(this.d.getTime())\n },\n //travel to this timezone\n goto: function(tz) {\n let s = this.clone();\n s.tz = find(tz, s.timezones); //science!\n return s\n },\n //get each week/month/day between a -> b\n every: function(unit, to) {\n return every_1(this, unit, to)\n },\n isAwake: function() {\n let hour = this.hour();\n //10pm -> 8am\n if (hour < 8 || hour > 22) {\n return false\n }\n return true\n },\n isAsleep: function() {\n return !this.isAwake()\n },\n //pretty-printing\n log: function() {\n console.log('');\n console.log(format_1(this, 'nice-short'));\n return this\n },\n logYear: function() {\n console.log('');\n console.log(format_1(this, 'full-short'));\n return this\n },\n json: function() {\n return units$3.reduce((h, unit) => {\n h[unit] = this[unit]();\n return h\n }, {})\n },\n debug: function() {\n let tz = this.timezone();\n let date = this.format('MM') + ' ' + this.format('date-ordinal') + ' ' + this.year();\n date += '\\n - ' + this.format('time');\n console.log('\\n\\n', date + '\\n - ' + tz.name + ' (' + tz.current.offset + ')');\n return this\n },\n //alias of 'since' but opposite - like moment.js\n from: function(d) {\n d = this.clone().set(d);\n return d.since(this)\n },\n fromNow: function() {\n let d = this.clone().set(Date.now());\n return d.since(this)\n },\n weekStart: function(input) {\n //accept a number directly\n if (typeof input === 'number') {\n this._weekStart = input;\n return this\n }\n if (typeof input === 'string') {\n // accept 'wednesday'\n input = input.toLowerCase().trim();\n let num = days.short().indexOf(input);\n if (num === -1) {\n num = days.long().indexOf(input);\n }\n if (num === -1) {\n num = 1; //go back to default\n }\n this._weekStart = num;\n } else {\n console.warn('Spacetime Error: Cannot understand .weekStart() input:', input);\n }\n return this\n }\n};\n// aliases\nmethods.inDST = methods.isDST;\nmethods.round = methods.nearest;\nmethods.each = methods.every;\nvar methods_1 = methods;\n\n// javascript setX methods like setDate() can't be used because of the local bias\n//these methods wrap around them.\n\n\n\n\n\nconst validate = n => {\n //handle number as a string\n if (typeof n === 'string') {\n n = parseInt(n, 10);\n }\n return n\n};\n\nconst order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond'];\n\n//reduce hostile micro-changes when moving dates by millisecond\nconst confirm = (s, tmp, unit) => {\n let n = order.indexOf(unit);\n let arr = order.slice(n, order.length);\n for (let i = 0; i < arr.length; i++) {\n let want = tmp[arr[i]]();\n s[arr[i]](want);\n }\n return s\n};\n\nvar set = {\n milliseconds: (s, n) => {\n n = validate(n);\n let current = s.millisecond();\n let diff = current - n; //milliseconds to shift by\n return s.epoch - diff\n },\n\n seconds: (s, n) => {\n n = validate(n);\n let diff = s.second() - n;\n let shift = diff * milliseconds.second;\n return s.epoch - shift\n },\n\n minutes: (s, n) => {\n n = validate(n);\n let old = s.clone();\n let diff = s.minute() - n;\n let shift = diff * milliseconds.minute;\n s.epoch -= shift;\n confirm(s, old, 'second');\n return s.epoch\n },\n\n hours: (s, n) => {\n n = validate(n);\n if (n >= 24) {\n n = 24;\n } else if (n < 0) {\n n = 0;\n }\n let old = s.clone();\n let diff = s.hour() - n;\n let shift = diff * milliseconds.hour;\n s.epoch -= shift;\n walk_1(s, {\n hour: n\n });\n confirm(s, old, 'minute');\n return s.epoch\n },\n\n //support setting time by '4:25pm' - this isn't very-well developed..\n time: (s, str) => {\n let m = str.match(/([0-9]{1,2}):([0-9]{1,2})(am|pm)?/);\n if (!m) {\n //fallback to support just '2am'\n m = str.match(/([0-9]{1,2})(am|pm)/);\n if (!m) {\n return s.epoch\n }\n m.splice(2, 0, '0'); //add implicit 0 minutes\n }\n let h24 = false;\n let hour = parseInt(m[1], 10);\n let minute = parseInt(m[2], 10);\n if (hour > 12) {\n h24 = true;\n }\n //make the hour into proper 24h time\n if (h24 === false) {\n if (m[3] === 'am' && hour === 12) {\n //12am is midnight\n hour = 0;\n }\n if (m[3] === 'pm' && hour < 12) {\n //12pm is noon\n hour += 12;\n }\n }\n s = s.hour(hour);\n s = s.minute(minute);\n s = s.second(0);\n s = s.millisecond(0);\n return s.epoch\n },\n\n date: (s, n) => {\n n = validate(n);\n //avoid setting february 31st\n if (n > 28) {\n const max = monthLengths_1[s.month()];\n if (n > max) {\n n = max;\n }\n }\n //avoid setting < 0\n if (n <= 0) {\n n = 1;\n }\n walk_1(s, {\n date: n\n });\n return s.epoch\n },\n\n //this one's tricky\n month: (s, n) => {\n if (typeof n === 'string') {\n n = months.mapping()[n.toLowerCase()];\n }\n n = validate(n);\n //don't go past december\n if (n >= 12) {\n n = 11;\n }\n if (n <= 0) {\n n = 0;\n }\n\n let date = s.date();\n //there's no 30th of february, etc.\n if (date > monthLengths_1[n]) {\n //make it as close as we can..\n date = monthLengths_1[n];\n }\n walk_1(s, {\n month: n,\n date\n });\n return s.epoch\n },\n\n year: (s, n) => {\n n = validate(n);\n walk_1(s, {\n year: n\n });\n return s.epoch\n },\n\n dayOfYear: (s, n) => {\n n = validate(n);\n let old = s.clone();\n n -= 1; //days are 1-based\n if (n <= 0) {\n n = 0;\n } else if (n >= 365) {\n n = 364;\n }\n s = s.startOf('year');\n s = s.add(n, 'day');\n confirm(s, old, 'hour');\n return s.epoch\n }\n};\n\nconst methods$1 = {\n millisecond: function(num) {\n if (num !== undefined) {\n let s = this.clone();\n s.epoch = set.milliseconds(s, num);\n return s\n }\n return this.d.getMilliseconds()\n },\n second: function(num) {\n if (num !== undefined) {\n let s = this.clone();\n s.epoch = set.seconds(s, num);\n return s\n }\n return this.d.getSeconds()\n },\n minute: function(num) {\n if (num !== undefined) {\n let s = this.clone();\n s.epoch = set.minutes(s, num);\n return s\n }\n return this.d.getMinutes()\n },\n hour: function(num) {\n let d = this.d;\n if (num !== undefined) {\n let s = this.clone();\n s.epoch = set.hours(s, num);\n return s\n }\n return d.getHours()\n },\n\n //'3:30' is 3.5\n hourFloat: function(num) {\n if (num !== undefined) {\n let s = this.clone();\n let minute = num % 1;\n minute = minute * 60;\n let hour = parseInt(num, 10);\n s.epoch = set.hours(s, hour);\n s.epoch = set.minutes(s, minute);\n return s\n }\n let d = this.d;\n let hour = d.getHours();\n let minute = d.getMinutes();\n minute = minute / 60;\n return hour + minute\n },\n\n // hour in 12h format\n hour12: function(str) {\n let d = this.d;\n if (str !== undefined) {\n let s = this.clone();\n str = '' + str;\n let m = str.match(/^([0-9]+)(am|pm)$/);\n if (m) {\n let hour = parseInt(m[1], 10);\n if (m[2] === 'pm') {\n hour += 12;\n }\n s.epoch = set.hours(s, hour);\n }\n return s\n }\n //get the hour\n let hour12 = d.getHours();\n if (hour12 > 12) {\n hour12 = hour12 - 12;\n }\n if (hour12 === 0) {\n hour12 = 12;\n }\n return hour12\n },\n\n //some ambiguity here with 12/24h\n time: function(str) {\n if (str !== undefined) {\n let s = this.clone();\n s.epoch = set.time(s, str);\n return s\n }\n return `${this.h12()}:${fns.zeroPad(this.minute())}${this.ampm()}`\n },\n\n // either 'am' or 'pm'\n ampm: function(input) {\n let which = 'am';\n let hour = this.hour();\n if (hour >= 12) {\n which = 'pm';\n }\n if (typeof input !== 'string') {\n return which\n }\n //okay, we're doing a setter\n let s = this.clone();\n input = input.toLowerCase().trim();\n //ampm should never change the day\n // - so use `.hour(n)` instead of `.minus(12,'hour')`\n if (hour >= 12 && input === 'am') {\n //noon is 12pm\n hour -= 12;\n return s.hour(hour)\n }\n if (hour < 12 && input === 'pm') {\n hour += 12;\n return s.hour(hour)\n }\n return s\n },\n\n //some hard-coded times of day, like 'noon'\n dayTime: function(str) {\n if (str !== undefined) {\n const times = {\n morning: '7:00am',\n breakfast: '7:00am',\n noon: '12:00am',\n lunch: '12:00pm',\n afternoon: '2:00pm',\n evening: '6:00pm',\n dinner: '6:00pm',\n night: '11:00pm',\n midnight: '23:59pm'\n };\n let s = this.clone();\n str = str || '';\n str = str.toLowerCase();\n if (times.hasOwnProperty(str) === true) {\n s = s.time(times[str]);\n }\n return s\n }\n let h = this.hour();\n if (h < 6) {\n return 'night'\n }\n if (h < 12) {\n //until noon\n return 'morning'\n }\n if (h < 17) {\n //until 5pm\n return 'afternoon'\n }\n if (h < 22) {\n //until 10pm\n return 'evening'\n }\n return 'night'\n },\n\n //parse a proper iso string\n iso: function(num) {\n if (num !== undefined) {\n return this.set(num)\n }\n return this.format('iso')\n }\n};\nvar _01Time = methods$1;\n\nconst methods$2 = {\n // # day in the month\n date: function(num) {\n if (num !== undefined) {\n let s = this.clone();\n s.epoch = set.date(s, num);\n return s\n }\n return this.d.getDate()\n },\n\n //like 'wednesday' (hard!)\n day: function(input) {\n if (input === undefined) {\n return this.d.getDay()\n }\n let original = this.clone();\n let want = input;\n // accept 'wednesday'\n if (typeof input === 'string') {\n input = input.toLowerCase();\n want = days.short().indexOf(input);\n if (want === -1) {\n want = days.long().indexOf(input);\n }\n }\n //move approx\n let day = this.d.getDay();\n let diff = day - want;\n let s = this.subtract(diff * 24, 'hours');\n //tighten it back up\n walk_1(s, {\n hour: original.hour(),\n minute: original.minute(),\n second: original.second()\n });\n return s\n },\n\n //these are helpful name-wrappers\n dayName: function(input) {\n if (input === undefined) {\n return days.long()[this.day()]\n }\n let s = this.clone();\n s = s.day(input);\n return s\n },\n\n //either name or number\n month: function(input) {\n if (input !== undefined) {\n let s = this.clone();\n s.epoch = set.month(s, input);\n return s\n }\n return this.d.getMonth()\n }\n};\nvar _02Date = methods$2;\n\nconst clearMinutes = s => {\n s = s.minute(0);\n s = s.second(0);\n s = s.millisecond(1);\n return s\n};\n\nconst methods$3 = {\n // day 0-366\n dayOfYear: function(num) {\n if (num !== undefined) {\n let s = this.clone();\n s.epoch = set.dayOfYear(s, num);\n return s\n }\n //days since newyears - jan 1st is 1, jan 2nd is 2...\n let sum = 0;\n let month = this.d.getMonth();\n let tmp;\n //count the num days in each month\n for (let i = 1; i <= month; i++) {\n tmp = new Date();\n tmp.setDate(1);\n tmp.setFullYear(this.d.getFullYear()); //the year matters, because leap-years\n tmp.setHours(1);\n tmp.setMinutes(1);\n tmp.setMonth(i);\n tmp.setHours(-2); //the last day of the month\n sum += tmp.getDate();\n }\n return sum + this.d.getDate()\n },\n\n //since the start of the year\n week: function(num) {\n // week-setter\n if (num !== undefined) {\n let s = this.clone();\n s = s.month(0);\n s = s.date(1);\n s = s.day('monday');\n s = clearMinutes(s);\n //don't go into last-year\n if (s.monthName() === 'december') {\n s = s.add(1, 'week');\n }\n num -= 1; //1-based\n s = s.add(num, 'weeks');\n return s\n }\n //find-out which week it is\n let tmp = this.clone();\n tmp = tmp.month(0);\n tmp = tmp.date(1);\n tmp = clearMinutes(tmp);\n tmp = tmp.day('monday');\n //don't go into last-year\n if (tmp.monthName() === 'december') {\n tmp = tmp.add(1, 'week');\n }\n // is first monday the 1st?\n let toAdd = 1;\n if (tmp.date() === 1) {\n toAdd = 0;\n }\n tmp = tmp.minus(1, 'second');\n const thisOne = this.epoch;\n //if the week technically hasn't started yet\n if (tmp.epoch > thisOne) {\n return 1\n }\n //speed it up, if we can\n let i = 0;\n let skipWeeks = this.month() * 4;\n tmp.epoch += milliseconds.week * skipWeeks;\n i += skipWeeks;\n for (; i < 52; i++) {\n if (tmp.epoch > thisOne) {\n return i + toAdd\n }\n tmp = tmp.add(1, 'week');\n }\n return 52\n },\n\n //'january'\n monthName: function(input) {\n if (input === undefined) {\n return months.long()[this.month()]\n }\n let s = this.clone();\n s = s.month(input);\n return s\n },\n\n //q1, q2, q3, q4\n quarter: function(num) {\n if (num !== undefined) {\n if (typeof num === 'string') {\n num = num.replace(/^q/i, '');\n num = parseInt(num, 10);\n }\n if (quarters[num]) {\n let s = this.clone();\n let month = quarters[num][0];\n s = s.month(month);\n s = s.date(1);\n s = s.startOf('day');\n return s\n }\n }\n let month = this.d.getMonth();\n for (let i = 1; i < quarters.length; i++) {\n if (month < quarters[i][0]) {\n return i - 1\n }\n }\n return 4\n },\n\n //spring, summer, winter, fall\n season: function(input) {\n let hem = 'north';\n if (this.hemisphere() === 'South') {\n hem = 'south';\n }\n if (input !== undefined) {\n let s = this.clone();\n for (let i = 0; i < seasons[hem].length; i++) {\n if (input === seasons[hem][i][0]) {\n s = s.month(seasons[hem][i][1]);\n s = s.date(1);\n s = s.startOf('day');\n }\n }\n return s\n }\n let month = this.d.getMonth();\n for (let i = 0; i < seasons[hem].length - 1; i++) {\n if (month >= seasons[hem][i][1] && month < seasons[hem][i + 1][1]) {\n return seasons[hem][i][0]\n }\n }\n return 'winter'\n },\n\n //the year number\n year: function(num) {\n if (num !== undefined) {\n let s = this.clone();\n s.epoch = set.year(s, num);\n return s\n }\n return this.d.getFullYear()\n },\n\n //bc/ad years\n era: function(str) {\n if (str !== undefined) {\n let s = this.clone();\n str = str.toLowerCase();\n //TODO: there is no year-0AD i think. may have off-by-1 error here\n let year = s.d.getFullYear();\n //make '1992' into 1992bc..\n if (str === 'bc' && year > 0) {\n s.epoch = set.year(s, year * -1);\n }\n //make '1992bc' into '1992'\n if (str === 'ad' && year < 0) {\n s.epoch = set.year(s, year * -1);\n }\n return s\n }\n if (this.d.getFullYear() < 0) {\n return 'BC'\n }\n return 'AD'\n },\n\n // 2019 -> 2010\n decade: function(input) {\n if (input !== undefined) {\n input = String(input);\n input = input.replace(/([0-9])'?s$/, '$1'); //1950's\n input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals\n if (!input) {\n console.warn('Spacetime: Invalid decade input');\n return this\n }\n // assume 20th century?? for '70s'.\n if (input.length === 2 && /[0-9][0-9]/.test(input)) {\n input = '19' + input;\n }\n let year = Number(input);\n if (isNaN(year)) {\n return this\n }\n // round it down to the decade\n year = Math.floor(year / 10) * 10;\n return this.year(year) //.startOf('decade')\n }\n return this.startOf('decade').year()\n },\n // 1950 -> 19+1\n century: function(input) {\n if (input !== undefined) {\n if (typeof input === 'string') {\n input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals\n input = input.replace(/([0-9]+) ?(b\\.?c\\.?|a\\.?d\\.?)/i, (a, b, c) => {\n if (c.match(/b\\.?c\\.?/i)) {\n b = '-' + b;\n }\n return b\n });\n input = input.replace(/c$/, ''); //20thC\n }\n let year = Number(input);\n if (isNaN(input)) {\n console.warn('Spacetime: Invalid century input');\n return this\n }\n // there is no century 0\n if (year === 0) {\n year = 1;\n }\n if (year >= 0) {\n year = (year - 1) * 100;\n } else {\n year = (year + 1) * 100;\n }\n return this.year(year)\n }\n // century getter\n let num = this.startOf('century').year();\n num = Math.floor(num / 100);\n if (num < 0) {\n return num - 1\n }\n return num + 1\n },\n // 2019 -> 2+1\n millenium: function(input) {\n if (input !== undefined) {\n if (typeof input === 'string') {\n input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals\n input = Number(input);\n if (isNaN(input)) {\n console.warn('Spacetime: Invalid millenium input');\n return this\n }\n }\n if (input > 0) {\n input -= 1;\n }\n let year = input * 1000;\n // there is no year 0\n if (year === 0) {\n year = 1;\n }\n return this.year(year)\n }\n // get the current millenium\n let num = Math.floor(this.year() / 1000);\n if (num >= 0) {\n num += 1;\n }\n return num\n }\n};\nvar _03Year = methods$3;\n\nconst methods$4 = Object.assign({}, _01Time, _02Date, _03Year);\n\n//aliases\nmethods$4.milliseconds = methods$4.millisecond;\nmethods$4.seconds = methods$4.second;\nmethods$4.minutes = methods$4.minute;\nmethods$4.hours = methods$4.hour;\nmethods$4.hour24 = methods$4.hour;\nmethods$4.h12 = methods$4.hour12;\nmethods$4.h24 = methods$4.hour24;\nmethods$4.days = methods$4.day;\n\nconst addMethods = Space => {\n //hook the methods into prototype\n Object.keys(methods$4).forEach(k => {\n Space.prototype[k] = methods$4[k];\n });\n};\n\nvar query = addMethods;\n\nconst order$1 = ['millisecond', 'second', 'minute', 'hour', 'date', 'month'];\nlet keep = {\n second: order$1.slice(0, 1),\n minute: order$1.slice(0, 2),\n quarterhour: order$1.slice(0, 2),\n hour: order$1.slice(0, 3),\n date: order$1.slice(0, 4),\n month: order$1.slice(0, 4),\n quarter: order$1.slice(0, 4),\n season: order$1.slice(0, 4),\n year: order$1,\n decade: order$1,\n century: order$1\n};\nkeep.week = keep.hour;\nkeep.season = keep.date;\nkeep.quarter = keep.date;\n\n// Units need to be dst adjuested\nconst dstAwareUnits = {\n year: true,\n quarter: true,\n season: true,\n month: true,\n week: true,\n day: true\n};\n\nconst keepDate = {\n month: true,\n quarter: true,\n season: true,\n year: true\n};\n//month is the only thing we 'model/compute'\n//- because ms-shifting can be off by enough\nconst rollMonth = (want, old) => {\n //increment year\n if (want.month > 0) {\n let years = parseInt(want.month / 12, 10);\n want.year = old.year() + years;\n want.month = want.month % 12;\n } else if (want.month < 0) {\n //decrement year\n let years = Math.floor(Math.abs(want.month) / 13, 10);\n years = Math.abs(years) + 1;\n want.year = old.year() - years;\n //ignore extras\n want.month = want.month % 12;\n want.month = want.month + 12;\n if (want.month === 12) {\n want.month = 0;\n }\n }\n return want\n};\n\nconst addMethods$1 = SpaceTime => {\n SpaceTime.prototype.add = function(num, unit) {\n let s = this.clone();\n if (!unit || num === 0) {\n return s //don't bother\n }\n let old = this.clone();\n unit = fns.normalize(unit);\n //move forward by the estimated milliseconds (rough)\n if (milliseconds[unit]) {\n s.epoch += milliseconds[unit] * num;\n } else if (unit === 'week') {\n s.epoch += milliseconds.day * (num * 7);\n } else if (unit === 'quarter' || unit === 'season') {\n s.epoch += milliseconds.month * (num * 4);\n } else if (unit === 'season') {\n s.epoch += milliseconds.month * (num * 4);\n } else if (unit === 'quarterhour') {\n s.epoch += milliseconds.minute * 15 * num;\n }\n //now ensure our milliseconds/etc are in-line\n let want = {};\n if (keep[unit]) {\n keep[unit].forEach(u => {\n want[u] = old[u]();\n });\n }\n\n if (dstAwareUnits[unit]) {\n const diff = old.timezone().current.offset - s.timezone().current.offset;\n s.epoch += diff * 3600 * 1000;\n }\n\n //ensure month/year has ticked-over\n if (unit === 'month') {\n want.month = old.month() + num;\n //month is the one unit we 'model' directly\n want = rollMonth(want, old);\n }\n //support coercing a week, too\n if (unit === 'week') {\n let sum = old.date() + num * 7;\n if (sum <= 28 && sum > 1) {\n want.date = sum;\n }\n }\n //support 25-hour day-changes on dst-changes\n else if (unit === 'date') {\n //specify a naive date number, if it's easy to do...\n let sum = old.date() + num;\n if (sum <= 28 && sum > 1) {\n want.date = sum;\n }\n //or if we haven't moved at all..\n else if (num !== 0 && old.isSame(s, 'day')) {\n want.date = old.date() + num;\n }\n }\n //ensure year has changed (leap-years)\n else if (unit === 'year' && s.year() === old.year()) {\n s.epoch += milliseconds.week;\n }\n //these are easier\n else if (unit === 'decade') {\n want.year = s.year() + 10;\n } else if (unit === 'century') {\n want.year = s.year() + 100;\n }\n //keep current date, unless the month doesn't have it.\n if (keepDate[unit]) {\n let max = monthLengths_1[want.month];\n want.date = old.date();\n if (want.date > max) {\n want.date = max;\n }\n }\n walk_1(s, want);\n return s\n };\n\n //subtract is only add *-1\n SpaceTime.prototype.subtract = function(num, unit) {\n let s = this.clone();\n return s.add(num * -1, unit)\n };\n //add aliases\n SpaceTime.prototype.minus = SpaceTime.prototype.subtract;\n SpaceTime.prototype.plus = SpaceTime.prototype.add;\n};\n\nvar add = addMethods$1;\n\n//make a string, for easy comparison between dates\nconst print = {\n millisecond: s => {\n return s.epoch\n },\n second: s => {\n return [s.year(), s.month(), s.date(), s.hour(), s.minute(), s.second()].join('-')\n },\n minute: s => {\n return [s.year(), s.month(), s.date(), s.hour(), s.minute()].join('-')\n },\n hour: s => {\n return [s.year(), s.month(), s.date(), s.hour()].join('-')\n },\n day: s => {\n return [s.year(), s.month(), s.date()].join('-')\n },\n week: s => {\n return [s.year(), s.week()].join('-')\n },\n month: s => {\n return [s.year(), s.month()].join('-')\n },\n quarter: s => {\n return [s.year(), s.quarter()].join('-')\n },\n year: s => {\n return s.year()\n }\n};\nprint.date = print.day;\n\nconst addMethods$2 = SpaceTime => {\n SpaceTime.prototype.isSame = function(b, unit) {\n let a = this;\n if (!unit) {\n return null\n }\n if (typeof b === 'string' || typeof b === 'number') {\n b = new SpaceTime(b, this.timezone.name);\n }\n //support 'seconds' aswell as 'second'\n unit = unit.replace(/s$/, '');\n\n if (print[unit]) {\n return print[unit](a) === print[unit](b)\n }\n return null\n };\n};\n\nvar same = addMethods$2;\n\nconst addMethods$3 = SpaceTime => {\n const methods = {\n isAfter: function(d) {\n d = fns.beADate(d, this);\n let epoch = fns.getEpoch(d);\n if (epoch === null) {\n return null\n }\n return this.epoch > epoch\n },\n isBefore: function(d) {\n d = fns.beADate(d, this);\n let epoch = fns.getEpoch(d);\n if (epoch === null) {\n return null\n }\n return this.epoch < epoch\n },\n isEqual: function(d) {\n d = fns.beADate(d, this);\n let epoch = fns.getEpoch(d);\n if (epoch === null) {\n return null\n }\n return this.epoch === epoch\n },\n isBetween: function(start, end) {\n start = fns.beADate(start, this);\n end = fns.beADate(end, this);\n let startEpoch = fns.getEpoch(start);\n if (startEpoch === null) {\n return null\n }\n let endEpoch = fns.getEpoch(end);\n if (endEpoch === null) {\n return null\n }\n return startEpoch < this.epoch && this.epoch < endEpoch\n }\n };\n\n //hook them into proto\n Object.keys(methods).forEach(k => {\n SpaceTime.prototype[k] = methods[k];\n });\n};\n\nvar compare = addMethods$3;\n\nconst addMethods$4 = SpaceTime => {\n const methods = {\n i18n: data => {\n //change the day names\n if (fns.isObject(data.days)) {\n days.set(data.days);\n }\n //change the month names\n if (fns.isObject(data.months)) {\n months.set(data.months);\n }\n }\n };\n\n //hook them into proto\n Object.keys(methods).forEach(k => {\n SpaceTime.prototype[k] = methods[k];\n });\n};\n\nvar i18n = addMethods$4;\n\nlet timezones = unpack;\n\n//fake timezone-support, for fakers (es5 class)\nconst SpaceTime = function(input$1, tz, options = {}) {\n //the holy moment\n this.epoch = null;\n //the shift for the given timezone\n this.tz = find(tz, timezones);\n //whether to output warnings to console\n this.silent = options.silent || true;\n // favour british interpretation of 02/02/2018, etc\n this.british = options.dmy || options.british;\n\n //does the week start on sunday, or monday:\n this._weekStart = 1; //default to monday\n if (options.weekStart !== undefined) {\n this._weekStart = options.weekStart;\n }\n //add getter/setters\n Object.defineProperty(this, 'd', {\n //return a js date object\n get: function() {\n let offset = quick(this);\n //every computer is somewhere- get this computer's built-in offset\n let bias = new Date(this.epoch).getTimezoneOffset() || 0;\n //movement\n let shift = bias + offset * 60; //in minutes\n shift = shift * 60 * 1000; //in ms\n //remove this computer's offset\n let epoch = this.epoch + shift;\n let d = new Date(epoch);\n return d\n }\n });\n //add this data on the object, to allow adding new timezones\n Object.defineProperty(this, 'timezones', {\n get: () => timezones,\n set: obj => {\n timezones = obj;\n return obj\n }\n });\n //parse the various formats\n if (input$1 !== undefined || input$1 === null) {\n let tmp = input(this, input$1, tz);\n this.epoch = tmp.epoch;\n }\n};\n\n//(add instance methods to prototype)\nObject.keys(methods_1).forEach(k => {\n SpaceTime.prototype[k] = methods_1[k];\n});\n\n// ¯\\_(ツ)_/¯\nSpaceTime.prototype.clone = function() {\n return new SpaceTime(this.epoch, this.tz, {\n silent: this.silent,\n weekStart: this._weekStart\n })\n};\n\n//append more methods\nquery(SpaceTime);\nadd(SpaceTime);\nsame(SpaceTime);\ncompare(SpaceTime);\ni18n(SpaceTime);\n\nvar spacetime = SpaceTime;\n\n// const timezones = require('../data');\n\nconst whereIts = (a, b) => {\n let start = new spacetime(null);\n let end = new spacetime(null);\n start = start.time(a);\n //if b is undefined, use as 'within one hour'\n if (b) {\n end = end.time(b);\n } else {\n end = start.add(59, 'minutes');\n }\n\n let startHour = start.hour();\n let endHour = end.hour();\n let tzs = Object.keys(start.timezones).filter(tz => {\n if (tz.indexOf('/') === -1) {\n return false\n }\n let m = new spacetime(null, tz);\n let hour = m.hour();\n //do 'calendar-compare' not real-time-compare\n if (hour >= startHour && hour <= endHour) {\n //test minutes too, if applicable\n if (hour === startHour && m.minute() < start.minute()) {\n return false\n }\n if (hour === endHour && m.minute() > end.minute()) {\n return false\n }\n return true\n }\n return false\n });\n return tzs\n};\nvar whereIts_1 = whereIts;\n\nvar _version = '6.3.0';\n\nconst main$1 = (input, tz, options) => new spacetime(input, tz, options);\n\n//some helper functions on the main method\nmain$1.now = (tz, options) => new spacetime(new Date().getTime(), tz, options);\nmain$1.today = (tz, options) => {\n let s = new spacetime(new Date().getTime(), tz, options);\n return s.startOf('day')\n};\nmain$1.tomorrow = (tz, options) => {\n let s = new spacetime(new Date().getTime(), tz, options);\n return s.add(1, 'day').startOf('day')\n};\nmain$1.yesterday = (tz, options) => {\n let s = new spacetime(new Date().getTime(), tz, options);\n return s.subtract(1, 'day').startOf('day')\n};\nmain$1.extend = function(obj) {\n Object.keys(obj).forEach(k => {\n spacetime.prototype[k] = obj[k];\n });\n return this\n};\n//find tz by time\nmain$1.whereIts = whereIts_1;\nmain$1.version = _version;\n\n//aliases:\nmain$1.plugin = main$1.extend;\nvar src = main$1;\n\nexport default src;\n","const spacetime = require('spacetime')\n//hmmm: 'june 5th between 9 and 10am'\n\nconst halfPast = function(m, s) {\n let hour = m.match('#Cardinal$').text('reduced')\n\n let term = m.match('(half|quarter|25|15|10|5)')\n let mins = term.text('reduced')\n if (term.has('half')) {\n mins = '30'\n }\n if (term.has('quarter')) {\n mins = '15'\n }\n let behind = m.has('to')\n // apply it\n s = s.hour(hour)\n s = s.startOf('hour')\n if (behind) {\n s = s.subtract(mins, 'minutes')\n } else {\n s = s.add(mins, 'minutes')\n }\n return s\n}\n\nconst parseTime = function(doc) {\n let time = doc.match('(at|by|for|before)? #Time+')\n if (time.found) {\n doc.remove(time)\n }\n // get the main part of the time\n time = time.not('(at|by|for|before|sharp)')\n time = time.not('on the dot')\n let s = spacetime.now()\n let now = s.clone()\n\n // '5 oclock'\n let m = time.match('^#Cardinal oclock (am|pm)?')\n if (m.found) {\n m = m.not('oclock')\n s = s.hour(m.text('reduced'))\n if (s.isValid() && !s.isEqual(now)) {\n return s.time()\n }\n }\n\n // 'quarter to two'\n m = time.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal')\n if (m.found) {\n s = halfPast(m, s)\n if (s.isValid() && !s.isEqual(now)) {\n return s.time()\n }\n }\n // parse random a time like '4:54pm'\n let str = time.text('reduced')\n s = s.time(str)\n if (s.isValid() && !s.isEqual(now)) {\n return s.time()\n }\n return null\n}\nmodule.exports = parseTime\n","// interpret 'this halloween' or 'next june'\nconst parseRelative = function(doc) {\n let rel = null\n if (doc.has('^this? (next|upcoming)')) {\n rel = 'next'\n }\n if (doc.has('^this? (last|previous)')) {\n rel = 'last'\n }\n if (doc.has('^(this|current)')) {\n rel = 'this'\n }\n // finally, remove it from our text\n doc.remove('^(this|current|next|upcoming|last|previous)')\n return rel\n}\nmodule.exports = parseRelative\n","const spacetime = require('spacetime')\n\nclass Unit {\n constructor(str, unit) {\n this.str = str\n this.unit = unit || 'day'\n // set it to the beginning of the given unit\n let d = spacetime(str)\n // set to beginning\n if (d.isValid()) {\n d = d.startOf(unit)\n }\n Object.defineProperty(this, 'd', {\n enumerable: false,\n writable: true,\n value: d,\n })\n }\n // make a new one\n clone() {\n let d = new Unit(this.str)\n d.unit = this.unit\n return d\n }\n applyShift(obj) {\n Object.keys(obj).forEach(k => {\n this.d = this.d.add(obj[k], k)\n })\n return this\n }\n applyTime(str) {\n if (str) {\n this.d = this.d.time(str)\n } else {\n this.d = this.d.startOf('day') //zero-out time\n }\n return this\n }\n format(fmt) {\n return this.d.format(fmt)\n }\n start() {\n this.d = this.d.startOf(this.unit)\n return this\n }\n end() {\n this.d = this.d.endOf(this.unit)\n return this\n }\n // 'before 2019'\n before() {\n this.d = spacetime.now() // ???\n return this\n }\n // 'after 2019'\n after() {\n this.d = this.d.add(1, this.unit)\n this.d = this.d.startOf(this.unit)\n return this\n }\n // tricky: 'next june' 'next tuesday'\n next() {\n this.d = this.d.add(1, this.unit)\n this.d = this.d.startOf(this.unit)\n return this\n }\n // tricky: 'last june' 'last tuesday'\n last() {\n this.d = this.d.minus(1, this.unit)\n this.d = this.d.startOf(this.unit)\n return this\n }\n}\nmodule.exports = Unit\n","const spacetime = require('spacetime')\nconst Unit = require('./Unit')\n\nclass Day extends Unit {\n constructor(str, unit) {\n super(str, unit)\n this.unit = 'day'\n }\n}\nclass Month extends Unit {\n constructor(str, unit) {\n super(str, unit)\n this.unit = 'month'\n }\n}\nclass Quarter extends Unit {\n constructor(str, unit) {\n super(str, unit)\n this.unit = 'quarter'\n }\n}\nclass Year extends Unit {\n constructor(str, unit) {\n super(str, unit)\n this.unit = 'year'\n }\n}\nclass WeekDay extends Unit {\n constructor(str, unit) {\n super(str, unit)\n this.unit = 'week'\n this.d = this.d.day(str)\n //assume a wednesday in the future\n if (this.d.date() < spacetime.now().date()) {\n this.d = this.d.add(7, 'days')\n }\n }\n next() {\n this.d = this.d.add(7, 'days')\n this.d = this.d.day(this.str)\n return this\n }\n last() {\n this.d = this.d.minus(7, 'days')\n this.d = this.d.day(this.str)\n return this\n }\n}\n// like 'feb 2'\nclass CalendarDate extends Unit {\n constructor(str, unit) {\n super(str, unit)\n this.unit = 'day'\n }\n next() {\n this.d = this.d.add(1, 'year')\n return this\n }\n last() {\n this.d = this.d.minus(1, 'year')\n return this\n }\n}\n\nmodule.exports = {\n Unit: Unit,\n Day: Day,\n Month: Month,\n Quarter: Quarter,\n Year: Year,\n WeekDay: WeekDay,\n CalendarDate: CalendarDate,\n}\n","const units = require('./units')\nconst mapping = {\n week: units.Week,\n month: units.Month,\n quarter: units.Quarter,\n year: units.Year,\n season: units.Season,\n}\n\n// when a unit of time is spoken of as 'this month' - instead of 'february'\nconst namedUnit = function(doc) {\n //this month, last quarter, next year\n let m = doc.match('(weekday|week|month|quarter|season|year)')\n if (m.found === true) {\n let str = m.lastTerm().text('reduced')\n if (mapping.hasOwnProperty(str)) {\n let Model = mapping[str]\n if (!Model) {\n return null\n }\n let unit = new Model(null, str)\n return unit\n }\n }\n\n //try this version - 'next friday, last thursday'\n m = doc.match('(monday|tuesday|wednesday|thursday|friday|saturday|sunday)')\n if (m.found === true) {\n let str = m.lastTerm().text('reduced')\n let unit = new units.WeekDay(str)\n return unit\n }\n return null\n}\nmodule.exports = namedUnit\n","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('spacetime')) :\n typeof define === 'function' && define.amd ? define(['spacetime'], factory) :\n (global = global || self, global.spacetimeHoliday = factory(global.spacetime));\n}(this, function (spacetime) { 'use strict';\n\n spacetime = spacetime && spacetime.hasOwnProperty('default') ? spacetime['default'] : spacetime;\n\n //yep,\n var jan = 'january';\n var feb = 'february';\n var mar = 'march';\n var apr = 'april';\n var may = 'may';\n var jun = 'june';\n var jul = 'july';\n var aug = 'august';\n var sep = 'september';\n var oct = 'october';\n var nov = 'november';\n var dec = 'december';\n var fixedHolidays = {\n 'new years eve': [dec, 31],\n 'new years': [jan, 1],\n 'new years day': [jan, 1],\n 'inauguration day': [jan, 20],\n 'australia day': [jan, 26],\n 'national freedom day': [feb, 1],\n 'groundhog day': [feb, 2],\n 'rosa parks day': [feb, 4],\n 'valentines day': [feb, 14],\n 'saint valentines day': [feb, 14],\n 'st valentines day ': [feb, 14],\n 'saint patricks day': [mar, 17],\n 'st patricks day': [mar, 17],\n 'april fools': [apr, 1],\n 'april fools day': [apr, 1],\n 'emancipation day': [apr, 16],\n 'tax day': [apr, 15],\n //US\n 'labour day': [may, 1],\n 'cinco de mayo': [may, 5],\n 'national nurses day': [may, 6],\n 'harvey milk day': [may, 22],\n 'victoria day': [may, 24],\n juneteenth: [jun, 19],\n 'canada day': [jul, 1],\n 'independence day': [jul, 4],\n 'independents day': [jul, 4],\n 'bastille day': [jul, 14],\n 'purple heart day': [aug, 7],\n 'womens equality day': [aug, 26],\n '16 de septiembre': [sep, 16],\n 'dieciseis de septiembre': [sep, 16],\n 'grito de dolores': [sep, 16],\n halloween: [oct, 31],\n 'all hallows eve': [oct, 31],\n 'day of the dead': [oct, 31],\n // Ranged holiday [nov, 2],\n 'dia de muertos': [oct, 31],\n // Ranged holiday [nov, 2],\n 'veterans day': [nov, 11],\n 'st andrews day': [nov, 30],\n 'saint andrews day': [nov, 30],\n 'all saints day': [nov, 1],\n 'all sts day': [nov, 1],\n 'armistice day': [nov, 11],\n 'rememberance day': [nov, 11],\n 'christmas eve': [dec, 24],\n christmas: [dec, 25],\n xmas: [dec, 25],\n 'boxing day': [dec, 26],\n 'st stephens day': [dec, 26],\n 'saint stephens day': [dec, 26],\n // Fixed religious and cultural holidays\n // Catholic + Christian\n epiphany: [jan, 6],\n 'orthodox christmas day': [jan, 7],\n 'orthodox new year': [jan, 14],\n 'assumption of mary': [aug, 15],\n 'all souls day': [nov, 2],\n 'feast of the immaculate conception': [dec, 8],\n 'feast of our lady of guadalupe': [dec, 12],\n // Kwanzaa\n kwanzaa: [dec, 26],\n // Ranged holiday [jan, 1],\n // Pagan / metal 🤘\n imbolc: [feb, 2],\n beltaine: [may, 1],\n lughnassadh: [aug, 1],\n samhain: [oct, 31]\n };\n\n var fixedDates = function fixedDates(str, normal, year) {\n if (fixedHolidays.hasOwnProperty(str) || fixedHolidays.hasOwnProperty(normal)) {\n var arr = fixedHolidays[str] || fixedHolidays[normal] || [];\n var s = spacetime.now();\n s = s.year(year);\n s = s.startOf('year');\n s = s.month(arr[0]);\n s = s.date(arr[1]);\n\n if (s.isValid()) {\n return s;\n }\n }\n\n return null;\n };\n\n var _01FixedDates = fixedDates;\n\n //these are holidays on the 'nth weekday of month'\n var jan$1 = 'january';\n var feb$1 = 'february';\n var mar$1 = 'march'; // const apr = 'april'\n\n var may$1 = 'may';\n var jun$1 = 'june'; // const jul = 'july'\n // const aug = 'august'\n\n var sep$1 = 'september';\n var oct$1 = 'october';\n var nov$1 = 'november'; // const dec = 'december'\n\n var mon = 'monday'; // const tues = 'tuesday'\n // const wed = 'wednesday'\n\n var thurs = 'thursday';\n var fri = 'friday'; // const sat = 'saturday'\n\n var sun = 'sunday';\n var holidays = {\n 'martin luther king day': [3, mon, jan$1],\n //[third monday in january],\n 'presidents day': [3, mon, feb$1],\n //[third monday in february],\n 'commonwealth day': [2, mon, mar$1],\n //[second monday in march],\n 'mothers day': [2, sun, may$1],\n //[second Sunday in May],\n 'fathers day': [3, sun, jun$1],\n //[third Sunday in June],\n 'labor day': [1, mon, sep$1],\n //[first monday in september],\n 'columbus day': [2, mon, oct$1],\n //[second monday in october],\n 'canadian thanksgiving': [2, mon, oct$1],\n //[second monday in october],\n thanksgiving: [4, thurs, nov$1],\n // [fourth Thursday in November],\n 'black friday': [4, fri, nov$1] //[fourth friday in november],\n // 'memorial day': [may], //[last monday in may],\n // 'us election': [nov], // [Tuesday following the first Monday in November],\n // 'cyber monday': [nov]\n // 'advent': [] // fourth Sunday before Christmas\n\n }; // add aliases\n\n holidays['turday day'] = holidays.thanksgiving;\n holidays['indigenous peoples day'] = holidays['columbus day'];\n holidays['mlk day'] = holidays['martin luther king day'];\n var calendarHolidays = holidays;\n\n var fixedDates$1 = function fixedDates(str, normal, year) {\n if (calendarHolidays.hasOwnProperty(str) || calendarHolidays.hasOwnProperty(normal)) {\n var arr = calendarHolidays[str] || calendarHolidays[normal] || [];\n var s = spacetime.now();\n s = s.year(year); // [3rd, 'monday', 'january']\n\n s = s.month(arr[2]);\n s = s.startOf('month'); // make it january\n\n var month = s.month(); // make it the 1st monday\n\n s = s.day(arr[1]);\n\n if (s.month() !== month) {\n s = s.add(1, 'week');\n } // make it nth monday\n\n\n if (arr[0] > 1) {\n s = s.add(arr[0] - 1, 'week');\n }\n\n if (s.isValid()) {\n return s;\n }\n }\n\n return null;\n };\n\n var _02NthWeekday = fixedDates$1;\n\n // https://www.timeanddate.com/calendar/determining-easter-date.html\n var dates = {\n easter: 0,\n 'ash wednesday': -46,\n // (46 days before easter)\n 'palm sunday': 7,\n // (1 week before easter)\n 'maundy thursday': -3,\n // (3 days before easter)\n 'good friday': -2,\n // (2 days before easter)\n 'holy saturday': -1,\n // (1 days before easter)\n 'easter saturday': -1,\n // (1 day before easter)\n 'easter monday': 1,\n // (1 day after easter)\n 'ascension day': 39,\n // (39 days after easter)\n 'whit sunday': 49,\n // / pentecost (49 days after easter)\n 'whit monday': 50,\n // (50 days after easter)\n 'trinity sunday': 65,\n // (56 days after easter)\n 'corpus christi': 60,\n // (60 days after easter)\n 'mardi gras': -47 //(47 days before easter)\n\n };\n dates['easter sunday'] = dates.easter;\n dates['pentecost'] = dates['whit sunday'];\n dates['whitsun'] = dates['whit sunday'];\n var easterHolidays = dates;\n\n // by John Dyer\n // based on the algorithm by Oudin (1940) from http://www.tondering.dk/claus/cal/easter.php\n var calcEaster = function calcEaster(year) {\n var f = Math.floor,\n // Golden Number - 1\n G = year % 19,\n C = f(year / 100),\n // related to Epact\n H = (C - f(C / 4) - f((8 * C + 13) / 25) + 19 * G + 15) % 30,\n // number of days from 21 March to the Paschal full moon\n I = H - f(H / 28) * (1 - f(29 / (H + 1)) * f((21 - G) / 11)),\n // weekday for the Paschal full moon\n J = (year + f(year / 4) + I + 2 - C + f(C / 4)) % 7,\n // number of days from 21 March to the Sunday on or before the Paschal full moon\n L = I - J,\n month = 3 + f((L + 40) / 44),\n date = L + 28 - 31 * f(month / 4);\n month = month === 4 ? 'April' : 'March';\n return month + ' ' + date;\n };\n\n var calcEaster_1 = calcEaster;\n\n var easterDates = function easterDates(str, normal, year) {\n if (easterHolidays.hasOwnProperty(str) || easterHolidays.hasOwnProperty(normal)) {\n var days = easterHolidays[str] || easterHolidays[normal] || [];\n var date = calcEaster_1(year);\n\n if (!date) {\n return null; //no easter for this year\n }\n\n var e = spacetime(date);\n e = e.year(year);\n var s = e.add(days, 'day');\n\n if (s.isValid()) {\n return s;\n }\n }\n\n return null;\n };\n\n var _03EasterDates = easterDates;\n\n // http://www.astropixels.com/ephemeris/soleq2001.html\n // years 2000-2100\n var exceptions = {\n spring: [2003, 2007, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 2072, 2076, 2077, 2080, 2081, 2084, 2085, 2088, 2089, 2092, 2093, 2096, 2097],\n summer: [2021, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2041, 2044, 2045, 2048, 2049, 2052, 2053, 2056, 2057, 2060, 2061, 2064, 2065, 2068, 2069, 2070, 2072, 2073, 2074, 2076, 2077, 2078, 2080, 2081, 2082, 2084, 2085, 2086, 2088, 2089, 2090, 2092, 2093, 2094, 2096, 2097, 2098, 2099],\n fall: [2002, 2003, 2004, 2006, 2007, 2010, 2011, 2014, 2015, 2018, 2019, 2022, 2023, 2026, 2027, 2031, 2035, 2039, 2043, 2047, 2051, 2055, 2059, 2092, 2096],\n winter: [2002, 2003, 2006, 2007, 2011, 2015, 2019, 2023, 2027, 2031, 2035, 2039, 2043, 2080, 2084, 2088, 2092, 2096]\n };\n var winter20th = [2080, 2084, 2088, 2092, 2096];\n\n var calcSeasons = function calcSeasons(year) {\n // most common defaults\n var res = {\n spring: 'March 20 ' + year,\n summer: 'June 21 ' + year,\n fall: 'Sept 22 ' + year,\n winter: 'Dec 21 ' + year\n };\n\n if (exceptions.spring.indexOf(year) !== -1) {\n res.spring = 'March 19 ' + year;\n }\n\n if (exceptions.summer.indexOf(year) !== -1) {\n res.summer = 'June 20 ' + year;\n }\n\n if (exceptions.fall.indexOf(year) !== -1) {\n res.fall = 'Sept 21 ' + year;\n } // winter can be 20th, 21st, or 22nd\n\n\n if (exceptions.winter.indexOf(year) !== -1) {\n res.winter = 'Dec 22 ' + year;\n }\n\n if (winter20th.indexOf(year) !== -1) {\n res.winter = 'Dec 20 ' + year;\n }\n\n return res;\n };\n\n var seasons = calcSeasons;\n\n // these are properly calculated in ./lib/seasons\n var dates$1 = {\n 'spring equinox': 'spring',\n 'summer solistice': 'summer',\n 'fall equinox': 'fall',\n 'winter solstice': 'winter'\n }; // aliases\n\n dates$1['march equinox'] = dates$1['spring equinox'];\n dates$1['vernal equinox'] = dates$1['spring equinox'];\n dates$1['ostara'] = dates$1['spring equinox'];\n dates$1['june solstice'] = dates$1['summer solistice'];\n dates$1['litha'] = dates$1['summer solistice'];\n dates$1['autumn equinox'] = dates$1['fall equinox'];\n dates$1['autumnal equinox'] = dates$1['fall equinox'];\n dates$1['september equinox'] = dates$1['fall equinox'];\n dates$1['sept equinox'] = dates$1['fall equinox'];\n dates$1['mabon'] = dates$1['fall equinox'];\n dates$1['december solstice'] = dates$1['winter solistice'];\n dates$1['dec solstice'] = dates$1['winter solistice'];\n dates$1['yule'] = dates$1['winter solistice'];\n var astroHolidays = dates$1;\n\n var astroDates = function astroDates(str, normal, year) {\n if (astroHolidays.hasOwnProperty(str) || astroHolidays.hasOwnProperty(normal)) {\n var season = astroHolidays[str] || astroHolidays[normal];\n var seasons$1 = seasons(year);\n\n if (!season || !seasons$1 || !seasons$1[season]) {\n return null; // couldn't figure it out\n }\n\n var s = spacetime(seasons$1[season]);\n\n if (s.isValid()) {\n return s;\n }\n }\n\n return null;\n };\n\n var _04Astronomical = astroDates;\n\n var dates$2 = {\n // Muslim holidays\n 'isra and miraj': 'april 13',\n 'lailat al-qadr': 'june 10',\n 'eid al-fitr': 'june 15',\n 'id al-Fitr': 'june 15',\n 'eid ul-Fitr': 'june 15',\n ramadan: 'may 16',\n // Range holiday\n 'eid al-adha': 'sep 22',\n muharram: 'sep 12',\n 'prophets birthday': 'nov 21'\n };\n var lunarHolidays = dates$2;\n\n var dayDiff = -10.64;\n\n var lunarDates = function lunarDates(str, normal, year) {\n if (lunarHolidays.hasOwnProperty(str) || lunarHolidays.hasOwnProperty(normal)) {\n var date = lunarHolidays[str] || lunarHolidays[normal] || [];\n\n if (!date) {\n return null;\n } // start at 2018\n\n\n var s = spacetime(date + ' 2018');\n var diff = year - 2018;\n var toAdd = diff * dayDiff;\n s = s.add(toAdd, 'day');\n s = s.startOf('day'); // now set the correct year\n\n s = s.year(year);\n\n if (s.isValid()) {\n return s;\n }\n }\n\n return null;\n };\n\n var _05LunarDates = lunarDates;\n\n var nowYear = spacetime.now().year();\n\n var spacetimeHoliday = function spacetimeHoliday(str, year) {\n year = year || nowYear;\n str = str || '';\n str = String(str);\n str = str.trim().toLowerCase();\n str = str.replace(/'s/, 's'); // 'mother's day'\n\n var normal = str.replace(/ day$/, '');\n normal = normal.replace(/^the /, '');\n normal = normal.replace(/^orthodox /, ''); //orthodox good friday\n // try easier, unmoving holidays\n\n var s = _01FixedDates(str, normal, year);\n\n if (s !== null) {\n return s;\n } // try 'nth monday' holidays\n\n\n s = _02NthWeekday(str, normal, year);\n\n if (s !== null) {\n return s;\n } // easter-based holidays\n\n\n s = _03EasterDates(str, normal, year);\n\n if (s !== null) {\n return s;\n } // solar-based holidays\n\n\n s = _04Astronomical(str, normal, year);\n\n if (s !== null) {\n return s;\n } // mostly muslim holidays\n\n\n s = _05LunarDates(str, normal, year);\n\n if (s !== null) {\n return s;\n }\n\n return null;\n };\n\n var src = spacetimeHoliday;\n\n return src;\n\n}));\n//# sourceMappingURL=spacetime-holiday.js.map\n","const units = require('./units')\nconst spacetimeHoliday = require('spacetime-holiday')\n\nconst parseHoliday = function(doc) {\n let d = null\n let str = doc.match('#Holiday+').text('reduced')\n let year = 2020 //change me!\n let s = spacetimeHoliday(str, year)\n if (s !== null) {\n d = new units.CalendarDate(s)\n }\n return d\n}\nmodule.exports = parseHoliday\n","const { Unit } = require('./units')\n\n// parse things like 'june 5th 2019'\nconst parseExplicit = function(doc) {\n if (doc.has('#Number of #Month')) {\n }\n\n let str = doc.text('reduced')\n // spacetime does the heavy-lifting\n let d = new Unit(str)\n // did we find a date?\n if (d.d.isValid() === false) {\n return null\n }\n return d\n}\nmodule.exports = parseExplicit\n","const parseShift = require('./tokenize/01-shift')\nconst parseTime = require('./tokenize/02-time')\nconst parseRelative = require('./tokenize/03-relative')\nconst namedUnit = require('./01-namedUnit')\nconst parseHoliday = require('./02-holidays')\nconst explicit = require('./03-explicit')\nconst { Unit } = require('./units')\n\nconst parseDate = function(doc) {\n let shift = parseShift(doc)\n let time = parseTime(doc)\n let rel = parseRelative(doc)\n let d = null\n // let str = doc.text('reduced')\n // console.log(str, ' - ', rel, ' - ', shift, ' - ', time)\n\n // do we have just a time?\n if (doc.found === false && time !== null) {\n d = new Unit() // choose today\n }\n\n // this month\n d = d || namedUnit(doc)\n // this haloween\n d = d || parseHoliday(doc)\n // this june 2nd\n d = d || explicit(doc)\n\n if (!d) {\n return null\n }\n\n // // apply relative\n if (rel === 'last') {\n d.last()\n }\n if (rel === 'next') {\n d.next()\n }\n // apply shift\n if (shift) {\n d.applyShift(shift)\n }\n // apply time\n d.applyTime(time)\n\n return d\n}\nmodule.exports = parseDate\n","const parseDate = require('./toDate')\n\n//\nconst logic = function(doc, context) {\n // two explicit dates - 'between friday and sunday'\n let m = doc.match('between * and *')\n if (m.found) {\n let start = m\n .match('between [.*] and')\n .not('^between')\n .not('and$')\n start = parseDate(start, context)\n let end = m.match('and *').not('^and')\n end = parseDate(end, context)\n if (start) {\n return {\n start: start,\n end: end,\n }\n }\n }\n // two months, one year - 'june 5 to june 7 1998'\n m = doc.match('#Month #Value to #Month #Value of? #Year')\n if (m.found) {\n }\n // two months, no year - 'june 5 to june 7'\n m = doc.match('#Month #Value to #Month #Value')\n if (m.found) {\n }\n // one month, one year, first form - 'january 5 to 7 1998'\n m = doc.match('#Month #Value to #Value of? #Year')\n if (m.found) {\n }\n // one month, one year, second form - '5 to 7 of january 1998'\n m = doc.match('#Value to #Value of? #Month of? #Year')\n if (m.found) {\n }\n // one month, no year - '5 to 7 of january'\n m = doc.match('#Value to #Value of? #Month')\n if (m.found) {\n }\n // one month, no year - 'january 5 to 7'\n m = doc.match('#Month #Value to #Value')\n if (m.found) {\n }\n // 'from A to B'\n m = doc.match('from? * (to|@hasHyphen|until|upto) [*]')\n if (m.found) {\n }\n // 'before june'\n m = doc.match('^due (by|before|on|in)? [*]')\n if (m.found) {\n }\n // 'after june'\n m = doc.match('^(after|following|from) [*]')\n if (m.found) {\n }\n // 'in june'\n m = doc.match('^(on|during|in) [*]')\n if (m.found) {\n let d = parseDate(m, context)\n if (d) {\n return {\n start: d,\n end: d.clone().end(),\n }\n }\n }\n //else, try whole thing\n let d = parseDate(doc, context)\n return {\n start: d,\n end: null,\n }\n}\nmodule.exports = logic\n","const normalize = require('./01-normalize')\nconst parseRanges = require('./02-ranges')\n\nconst parse = function(doc, context) {\n doc = normalize(doc)\n return parseRanges(doc, context)\n}\nmodule.exports = parse\n","let arr = [\n ['mon', 'monday'],\n ['tue', 'tuesday'],\n ['tues', 'tuesday'],\n ['wed', 'wednesday'],\n ['thu', 'thursday'],\n ['thurs', 'thursday'],\n ['fri', 'friday'],\n ['sat', 'saturday'],\n ['sun', 'sunday'],\n\n ['jan', 'january'],\n ['feb', 'february'],\n ['mar', 'march'],\n ['apr', 'april'],\n ['jun', 'june'],\n ['jul', 'july'],\n ['aug', 'august'],\n ['sep', 'september'],\n ['sept', 'september'],\n ['oct', 'october'],\n ['nov', 'november'],\n ['dec', 'december'],\n]\n\narr = arr.map(a => {\n return { short: a[0], long: a[1] }\n})\n\nmodule.exports = arr\n","const tagger = require('./tagger')\nconst tags = require('./tags')\nconst words = require('./words')\nconst parse = require('./parse')\nconst abbrevs = require('./abbrevs')\n\nconst addMethods = function(Doc, world) {\n // our new tags\n world.addTags(tags)\n // add info for the date plugin\n world.addWords(words)\n // run our tagger\n world.postProcess(tagger)\n\n /** */\n class Dates extends Doc {\n constructor(list, from, w) {\n super(list, from, w)\n this.context = {}\n }\n /** overload the original json with noun information */\n json(options) {\n let n = null\n if (typeof options === 'number') {\n n = options\n options = null\n }\n options = options || { terms: false }\n let res = []\n let format = options.format || 'iso'\n this.forEach(doc => {\n let json = doc.json(options)[0]\n let obj = parse(doc, this.context)\n let start = obj.start ? obj.start.format(format) : null\n let end = obj.end ? obj.end.format(format) : null\n // set iso strings to json result\n json.date = {\n start: start,\n end: end,\n }\n // add duration\n if (start && end) {\n json.date.duration = obj.start.d.diff(obj.end.d)\n // we don't need these\n delete json.date.duration.milliseconds\n delete json.date.duration.seconds\n }\n res.push(json)\n })\n if (n !== null) {\n return res[n]\n }\n return res\n }\n\n /** render all dates according to a specific format */\n format(fmt) {\n this.forEach(doc => {\n let obj = parse(doc, this.context)\n let str = ''\n if (obj.start) {\n str = obj.start.format(fmt)\n if (obj.end) {\n str += ' to ' + obj.start.format(fmt)\n }\n doc.replaceWith(str, true)\n }\n })\n return this\n }\n /** replace 'Fri' with 'Friday', etc*/\n toLongForm() {\n abbrevs.forEach(a => {\n this.replace(a.short, a.long, true, true)\n })\n return this\n }\n /** replace 'Friday' with 'Fri', etc*/\n toShortForm() {\n abbrevs.forEach(a => {\n this.replace(a.long, a.short, true, true)\n })\n return this\n }\n }\n\n Doc.prototype.dates = function(n) {\n let context = {}\n if (n && typeof n === 'object') {\n context = n\n n = null\n }\n let r = this.clauses()\n let dates = r.match('#Date+')\n if (typeof n === 'number') {\n dates = dates.get(n)\n }\n if (typeof n === 'number') {\n dates = dates.get(n)\n }\n let d = new Dates(dates.list, this, this.world)\n d.context = context\n return d\n }\n}\n\nmodule.exports = addMethods\n"],"names":["preps","thisNext","sections","seasons","tagYear","m","reason","found","term","termList","num","parseInt","clean","tag","tagYearSafe","fixDates","doc","match","month","val","ifNo","duration","unTag","season","date","not","cardinal","v","time","here","values","has","dateTagger","sectionTagger","timeTagger","abbr","shiftTagger","fixUp","oops","d","knownDate","lastTerm","terms","methods","require$$0","require$$1","require$$2","require$$3","require$$4","require$$5","require$$6","tagDate","forEach","fn","FinancialQuarter","isA","Season","Year","notA","Duration","Time","Holiday","Timezone","DateShift","lex","data","a","i","length","normalize","clone","numbers","console","warn","toNumber","toCardinal","adverbs","remove","knownUnits","second","minute","hour","day","week","quarter","year","parseShift","result","ts","text","parseFloat","unit","replace","hasOwnProperty","Object","keys","k","createCommonjsModule","module","exports","getCjsExportFromNamespace","n","fns","isLeapYear","isDate","prototype","toString","call","isNaN","valueOf","isArray","input","isObject","zeroPad","str","len","pad","Array","join","titleCase","toUpperCase","substr","ordinal","j","String","toLowerCase","trim","getEpoch","tmp","getTime","epoch","beADate","s","set","formatTimezone","offset","delimiter","absOffset","Math","abs","sign","fns_1","fns_2","fns_3","fns_4","fns_5","fns_6","fns_7","fns_8","fns_9","fns_10","fns_11","fns_12","getMonth","getDate","getHours","shouldChange","start","end","defaultOffset","Date","bias","getTimezoneOffset","shift","current","summerTime","quickOffset","zones","timezones","obj","tz","undefined","dst","jul","dec","hem","split","inSummer","quick","_build","_build$1","freeze","_prefixes","all","Number","names","before","name","unpack","fallbackTZ","safeIntl","Intl","DateTimeFormat","format","resolvedOptions","timezone","timeZone","guessTz","guessTz_1","isOffset","isNumber","utcOffset","gmtOffset","toIana","parseOffset","parseOffset_1","local","cities","reduce","h","city","lookupTz","test","id","Error","find","o","millisecond","milliseconds","walk","previous","startUnit","original","diff","halfStep","units","valid","walkTo","getFullYear","seconds","wants","old","silent","walk_1","shortMonths","longMonths","buildMapping","sep","months","mapping","i18n","parseOffset$1","parseOffset_1$1","parseTime","arr","startOf","ampm","parseTime_1","monthLengths","monthLengths_1","hasDate","max","hasDate_1","months$1","parseYear","strFmt","reg","parse","givenTz","options","british","strParse","dates","now","tonight","today","tomorrow","add","yesterday","subtract","christmas","namedDates","minimumEpoch","defaults","handleArray","order","handleObject","assign","parseInput","res","shortDays","longDays","days","isoOffset","isNegative","floor","ceil","_offset","dayName","monthName","hour24","hour12","era","json","numeric","iso","h24","ms","toISOString","nice","aliases","mdy","dmy","ymd","printFormat","isValid","out","indexOf","_","fmt","format_1","G","GG","GGG","GGGG","y","yy","yyy","yyyy","yyyyy","Q","QQ","QQQ","QQQQ","M","MM","MMM","MMMM","w","ww","dd","D","dayOfYear","DD","DDD","E","EE","EEE","EEEE","EEEEE","e","ee","eee","eeee","eeeee","aa","aaa","aaaa","h12","hh","H","HH","mm","ss","A","z","zz","zzz","zzzz","Z","ZZ","ZZZ","ZZZZ","addAlias","char","to","toName","unixFmt","chars","quoteOn","push","txt","c","unixFmt_1","units$1","doUnit","endOf","percent","toFixed","progress","progress_1","nearest","prog","nearest_1","climb","b","isBefore","isAfter","diffOne","one","fastYear","years","msDiff","minutes","hours","weeks","waterfall","reverseDiff","main","reversed","diff$1","qualifiers","almost","over","getDiff","later","earlier","isSame","u","pluralize","value","slice","since","isNow","every","rounded","qualified","precise","englishValues","englishValue","nextUnit","nextValue","splice","since_1","north","south","quarters","units$2","quarterhour","_weekStart","q","hemisphere","decade","century","startOf_1","isDay","next","every_1","parseDst","epochShift","hasDst","Boolean","default_offset","change","back","summer","winter","isDST","timezone_1","units$3","input$1","hasDST","leapYear","last","isAwake","isAsleep","log","logYear","debug","from","fromNow","weekStart","inDST","round","each","methods_1","validate","confirm","want","methods$1","getMilliseconds","getSeconds","getMinutes","hourFloat","which","dayTime","times","morning","breakfast","noon","lunch","afternoon","evening","dinner","night","midnight","_01Time","methods$2","getDay","_02Date","clearMinutes","methods$3","sum","setDate","setFullYear","setHours","setMinutes","setMonth","toAdd","minus","thisOne","skipWeeks","millenium","_03Year","methods$4","addMethods","Space","query","order$1","keep","dstAwareUnits","keepDate","rollMonth","addMethods$1","SpaceTime","plus","print","addMethods$2","same","addMethods$3","isEqual","isBetween","startEpoch","endEpoch","compare","addMethods$4","defineProperty","get","spacetime","whereIts","startHour","endHour","tzs","filter","whereIts_1","_version","main$1","extend","version","plugin","src","halfPast","mins","behind","parseRelative","rel","Unit","enumerable","writable","Day","Month","Quarter","WeekDay","CalendarDate","Week","namedUnit","Model","define","feb","apr","nov","parseHoliday","spacetimeHoliday","parseExplicit","parseDate","explicit","applyShift","applyTime","logic","context","parseRanges","map","Doc","world","addTags","tags","addWords","words","postProcess","tagger","Dates","list","replaceWith","abbrevs","r","clauses"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/dates/builds/compromise-dates.min.js b/plugins/dates/builds/compromise-dates.min.js new file mode 100644 index 000000000..e4c948d43 --- /dev/null +++ b/plugins/dates/builds/compromise-dates.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).compromiseDates=e()}(this,(function(){"use strict";function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t,e){for(var n=0;n1e3&&a<3e3&&t.tag("Year",e)}}},m="date-values",f="date-tagger",y="section-tagger",p="shift-tagger",g="fix-tagger",v=[function(t){t.match("in the (night|evening|morning|afternoon|day|daytime)").tag("Time","in-the-night"),t.match("(#Value|#Time) (am|pm)").tag("Time","value-ampm");var e=t.if("#Month");!0===e.found&&(e.match("#Month #DateRange+").tag("Date","correction-numberRange"),e.match("#Value of #Month").tag("Date","value-of-month"),e.match("#Cardinal #Month").tag("Date","cardinal-month"),e.match("#Month #Value to #Value").tag("Date","value-to-value"),e.match("#Month the #Value").tag("Date","month-the-value"));var n=t.if("#Value");if(!0===n.found){n.match("(#WeekDay|#Month) #Value").ifNo("#Money").tag("Date","date-value"),n.match("#Value (#WeekDay|#Month)").ifNo("#Money").tag("Date","value-date"),n.match("#TextValue #TextValue").if("#Date").tag("#Date","textvalue-date");var a=n.if("#Duration");!0===a.found&&(a.match("for #Value #Duration").tag("Date","for-x-duration"),a.match("#Value #Duration #Conjunction").tag("Date","val-duration-conjunction"),a.match("".concat(s,"? #Value #Duration")).tag("Date","value-duration"),a.match("#Value #Duration old").unTag("Date","val-years-old"))}var r=t.if(h);!0===r.found&&(r.match("".concat(s,"? ").concat(c," ").concat(h)).tag("Date","thisNext-season"),r.match("the? ".concat(d," of ").concat(h)).tag("Date","section-season"),r.match("".concat(h," ").concat(s,"? #Cardinal")).tag("Date","season-year"));var o=t.if("#Date");!0===o.found&&(o.match("#Date the? #Ordinal").tag("Date","correction"),o.match("".concat(c," #Date")).tag("Date","thisNext"),o.match("due? (by|before|after|until) #Date").tag("Date","by"),o.match("(last|next|this|previous|current|upcoming|coming|the) #Date").tag("Date","next-feb"),o.match("the? ".concat(d," of #Date")).tag("Date","section-of"),o.match("#Ordinal #Duration in #Date").tag("Date","duration-in"),o.match("(early|late) (at|in)? the? #Date").tag("Time","early-evening"),o.match("#Date (by|before|after|at|@|about) #Cardinal").not("^#Date").tag("Time","date-before-Cardinal"),o.match("#Date [(am|pm)]").unTag("Verb").unTag("Copula").tag("Time","date-am"),o.match("#Date (#Preposition|to) #Date").ifNo("#Duration").tag("Date","date-prep-date"));var i=t.if("#Cardinal");if(!0===i.found){var u=i.match("#Date #Value [#Cardinal]");l(u,"date-value-year"),u=i.match("#Date+ [#Cardinal]"),l(u,"date-year"),u=i.match("#Month #Value [#Cardinal]"),l(u,"month-value-year"),u=i.match("#Month #Value to #Value [#Cardinal]"),l(u,"month-range-year"),u=i.match("(in|of|by|during|before|starting|ending|for|year) [#Cardinal]"),l(u,"in-year"),u=i.match("(q1|q2|q3|q4) [#Cardinal]"),l(u,"in-year"),u=i.match("#Ordinal quarter [#Cardinal]"),l(u,"in-year"),u=i.match("the year [#Cardinal]"),l(u,"in-year"),function(t,e){if(!0===t.found){var n=t.termList()[0];if(n){var a=parseInt(n.clean,10);a&&a>1900&&a<2030&&t.tag("Year",e)}}}(u=i.match("it (is|was) [#Cardinal]"),"in-year")}var m=t.if("#Time");return!0===m.found&&(m.match("(by|before|after|at|@|about) #Time").tag("Time","preposition-time"),m.match("#Cardinal #Time").not("#Year").tag("Time","value-time"),m.match("#Time [(eastern|pacific|central|mountain)]").tag("Time","timezone"),m.match("#Time [(est|pst|gmt)]").tag("Time","timezone abbr")),t},function(t){return t.has("#Value")&&(t.match("#Month #Value to #Value of? #Year?").tag("Date",m),t.match("#Value to #Value of? #Month #Year?").tag("Date",m),t.match("#Value #Duration of #Date").tag("Date",m),t.match("#Value+ #Duration (after|before|into|later|afterwards|ago)?").tag("Date",m),t.match("#Value #Date").tag("Date",m),t.match("#Date #Value").tag("Date",m),t.match("#Date #Preposition #Value").tag("Date",m),t.match("#Date (after|before|during|on|in) #Value").tag("Date",m),t.match("#Value (year|month|week|day) and a half").tag("Date",m),t.match("#Value and a half (years|months|weeks|days)").tag("Date",m),t.match("on the #Ordinal").tag("Date",m)),t},function(t){return t.match("(spring|summer|winter|fall|autumn|springtime|wintertime|summertime)").match("#Noun").tag("Season",f),t.match("(q1|q2|q3|q4)").tag("FinancialQuarter",f),t.match("(this|next|last|current) quarter").tag("FinancialQuarter",f),t.match("(this|next|last|current) season").tag("Season",f),t.has("#Date")&&(t.match("#Date #Preposition #Date").tag("Date",f),t.match("(once|twice) (a|an|each) #Date").tag("Date",f),t.match("(by|until|on|in|at|during|over|every|each|due) the? #Date").tag("Date",f),t.match("#Date+").tag("Date",f),t.match("(by|until|on|in|at|during|over|every|each|due) the? #Date").tag("Date",f),t.match("a #Duration").tag("Date",f),t.match("(between|from) #Date").tag("Date",f),t.match("(to|until|upto) #Date").tag("Date",f),t.match("#Date and #Date").tag("Date",f),t.match("(by|until|after|before|during|on|in|following) (next|this|last)? (#Date|#Date)").tag("Date",f),t.match("the? #Date after next one?").tag("Date",f),t.match("(about|approx|approximately|around) #Date").tag("Date",f)),t},function(t){return t.has("#Date")&&(t.match("this? (last|next|past|this|previous|current|upcoming|coming|the) #Date").tag("Date",y),t.match("(starting|beginning|ending) #Date").tag("Date",y),t.match("the? (start|end|middle|beginning) of (last|next|this|the) (#Date|#Date)").tag("Date",y),t.match("(the|this) #Date").tag("Date",y)),t},function(t){if(t.has("#Time")&&t.match("#Noun (standard|daylight|central|mountain)? time").tag("Timezone","time-tagger"),t.has("#Acronym")){t.match("(acdt|acst|ace|dmt|ist|tse|addt|adt|aedt|aest|ahdt|ahst|akdt|akst|amt|nst|apt|awt|gmt|awdt|awst|bdst|bst|bdt|nwt|bmt|wet|bost|cddt|cdt|cet|cmt|cpt|cst|cwt|chst|gst|eat|eddt|edt|eest|eet|emt|ept|ewt|est|ffmt|fmt|hdt|hst|hkst|hkt|hmt|iddt|idt|jmt|imt|jdt|jst|kdt|kst|kmt|lst|mddt|mdst|msd|msk|mdt|mmt|mpt|pdt|pst|mst|mwt|nddt|ndt|npt|nzdt|nzmt|nzst|pddt|pkst|pkt|plmt|pmmt|pmt|ppmt|ppt|pwt|qmt|rmt|sast|sdmt|set|sjmt|smt|sst|tbmt|tmt|utc|wast|wemt|wib|wit|wita|wmt|yddt|ydt|ypt|ywt|yst)").tag("Timezone","time-tagger")}return t.has("#Cardinal")&&t.match("(half|quarter|25|15|10|5) (past|after|to) #Cardinal").tag("Time"),t},function(t){return t.has("#Date")&&(t.match("#Cardinal #Duration (before|after)").tag("#DateShift",p),t.match("#Cardinal #Duration and? #DateShift").tag("#DateShift",p),t.match("#Cardinal #Duration and? #DateShift").tag("#DateShift",p),t.match("#Cardinal #Duration and? #DateShift").tag("#DateShift",p)),t},function(t){if(t.has("#Date")){var e=t.match("#Date+ by #Date+");e.found&&!e.has("^due")&&e.match("^#Date+").unTag("Date","by-monday");var n=t.match("#Date+");n.match("^day$").unTag("Date","spa-day");var a="(yesterday|today|tomorrow)";n.has(a)&&(n.match("".concat(a," [#Value]$")).unTag("Date","yesterday-7"),n.match("^[#Value] ".concat(a,"$")).unTag("Date","7 yesterday"),n.match("#WeekDay+ ".concat(a,"$")).unTag("Date").lastTerm().tag("Date","fri-yesterday"),n.match("(this|last|next) #Date ".concat(a,"$")).unTag("Date").lastTerm().tag("Date","this month yesterday")),n.match("on #Cardinal$").unTag("Date",g),n.match("this tomorrow").terms(0).unTag("Date","this-tomorrow"),n.match("(q1|q2|q3|q4) #Year").tag("Date",g),n.match("^#Value (this|next|last)").terms(0).unTag("Date",g),n.has("(last|this|next)")&&(n.match("(last|this|next) #Duration #Value").terms(2).unTag("Date",g),n.match("!#Month #Value (last|this|next) #Date").terms(0).unTag("Date",g)),!1===n.has("(#Year|#Time|#TextValue|#NumberRange)")&&n.match("(#Month|#WeekDay) #Value #Value").terms(2).unTag("Date",g),n.has("^between")&&!n.has("and .")&&n.unTag("Date",g),!n.has("#Month #Month")||n.has("@hasHyphen")||n.has("@hasComma")||n.match("#Month").lastTerm().unTag("Date","month-month")}return t}],b=function(t){return v.forEach((function(e){return e(t)})),t},w={FinancialQuarter:{isA:"Date"},Season:{isA:"Date"},Year:{isA:["Date"],notA:"RomanNumeral"},Duration:{isA:["Date","Noun"]},Time:{isA:["Date"]},Holiday:{isA:["Date","Noun"]},Timezone:{isA:["Date","Noun"]},DateShift:{isA:["Date"]}},k={};[[["weekend","weekday","summer","winter","autumn","some day","one day","all day","some point","eod","eom","standard time","daylight time","today","tomorrow","tmr","tmrw","yesterday"],["#Date"]],[["centuries","century","day","days","decade","decades","hour","hours","millisecond","milliseconds","minute","minutes","month","months","seconds","week","weeks","year","years"],["#Duration"]],[["all hallows eve","all saints day","all sts day","april fools","armistice day","australia day","bastille day","boxing day","canada day","christmas eve","christmas","cinco de mayo","day of the dead","dia de muertos","dieciseis de septiembre","emancipation day","grito de dolores","groundhog day","halloween","harvey milk day","inauguration day","independence day","independents day","juneteenth","labour day","national freedom day","national nurses day","new years eve","new years","purple heart day","rememberance day","rosa parks day","saint andrews day","saint patricks day","saint stephens day","saint valentines day","st andrews day","st patricks day","st stephens day","st valentines day ","valentines day","valentines","veterans day","victoria day","womens equality day","xmas","epiphany","orthodox christmas day","orthodox new year","assumption of mary","all souls day","feast of the immaculate conception","feast of our lady of guadalupe","kwanzaa","imbolc","beltaine","lughnassadh","samhain","martin luther king day","mlk day","presidents day","mardi gras","tax day","commonwealth day","mothers day","memorial day","fathers day","columbus day","indigenous peoples day","canadian thanksgiving","election day","thanksgiving","t-day","turkey day","black friday","cyber monday","ash wednesday","palm sunday","maundy thursday","good friday","holy saturday","easter","easter sunday","easter monday","orthodox good friday","orthodox holy saturday","orthodox easter","orthodox easter monday","ascension day","pentecost","whitsunday","whit sunday","whit monday","trinity sunday","corpus christi","advent","tu bishvat","tu bshevat","purim","passover","yom hashoah","lag baomer","shavuot","tisha bav","rosh hashana","yom kippur","sukkot","shmini atzeret","simchat torah","chanukah","hanukkah","isra and miraj","lailat al-qadr","eid al-fitr","id al-Fitr","eid ul-Fitr","ramadan","eid al-adha","muharram","the prophets birthday","ostara","march equinox","vernal equinox","litha","june solistice","summer solistice","mabon","september equinox","fall equinox","autumnal equinox","yule","december solstice","winter solstice","chinese new year","diwali"],["#Holiday"]],[["noon","midnight","now","morning","tonight","evening","afternoon","night","breakfast time","lunchtime","dinnertime","ago","sometime","eod","oclock","oclock","all day","at night"],["#Time"]]].forEach((function(t){for(var e=0;e1&&void 0!==arguments[1]?arguments[1]:2,n="0";return(t+="").length>=e?t:new Array(e-t.length+1).join(n)+t},e.titleCase=function(t){return t?t[0].toUpperCase()+t.substr(1):""},e.ordinal=function(t){var e=t%10,n=t%100;return 1===e&&11!==n?t+"st":2===e&&12!==n?t+"nd":3===e&&13!==n?t+"rd":t+"th"},e.toCardinal=function(t){return t=(t=String(t)).replace(/([0-9])(st|nd|rd|th)$/i,"$1"),parseInt(t,10)},e.normalize=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return"day"===(t=(t=(t=(t=t.toLowerCase().trim()).replace(/ies$/,"y")).replace(/s$/,"")).replace(/-/g,""))?"date":t},e.getEpoch=function(t){return"number"==typeof t?t:e.isDate(t)?t.getTime():t.epoch?t.epoch:null},e.beADate=function(t,n){return!1===e.isObject(t)?n.clone().set(t):t},e.formatTimezone=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",a=Math.abs(t),r=t>0?"+":"-";return"".concat(r).concat(e.zeroPad(a)).concat(n,"00")}})),T=(q.isLeapYear,q.isDate,q.isArray,q.isObject,q.zeroPad,q.titleCase,q.ordinal,q.toCardinal,q.normalize,q.getEpoch,q.beADate,q.formatTimezone,q.zeroPad),_=function(t,e,n,a){var r=new Date(t),o=(r.getTimezoneOffset()||0)+60*a;o=60*o*1e3;var i=function(t){return T(t.getMonth()+1)+"/"+T(t.getDate())+":"+T(t.getHours())}(r=new Date(t+o));return i>=e&&i");return!0===_(t.epoch,r[0],r[1],n)?n:a},C=["africa","america","asia","atlantic","australia","brazil","canada","chile","europe","indian","mexico","pacific","antarctica","etc"],P=(x=Object.freeze({default:{"9|s":"2/dili,2/jayapura","9|n":"2/chita,2/khandyga,2/pyongyang,2/seoul,2/tokyo,11/palau","9.5|s|04/07:03->10/06:02":"4/adelaide,4/broken_hill,4/south,4/yancowinna","9.5|s":"4/darwin,4/north","8|s":"12/casey,2/kuala_lumpur,2/makassar,2/singapore,4/perth,4/west","8|n|03/25:03->09/29:23":"2/ulan_bator","8|n":"2/brunei,2/choibalsan,2/chongqing,2/chungking,2/harbin,2/hong_kong,2/irkutsk,2/kuching,2/macao,2/macau,2/manila,2/shanghai,2/taipei,2/ujung_pandang,2/ulaanbaatar","8.75|s":"4/eucla","7|s":"12/davis,2/jakarta,9/christmas","7|n":"2/bangkok,2/barnaul,2/ho_chi_minh,2/hovd,2/krasnoyarsk,2/novokuznetsk,2/novosibirsk,2/phnom_penh,2/pontianak,2/saigon,2/tomsk,2/vientiane","6|s":"12/vostok","6|n":"2/almaty,2/bishkek,2/dacca,2/dhaka,2/kashgar,2/omsk,2/qyzylorda,2/thimbu,2/thimphu,2/urumqi,9/chagos","6.5|n":"2/rangoon,9/cocos","5|s":"12/mawson,9/kerguelen","5|n":"2/aqtau,2/aqtobe,2/ashgabat,2/ashkhabad,2/atyrau,2/baku,2/dushanbe,2/karachi,2/oral,2/samarkand,2/tashkent,2/yekaterinburg,9/maldives","5.75|n":"2/kathmandu,2/katmandu","5.5|n":"2/calcutta,2/colombo,2/kolkata","4|s":"9/reunion","4|n":"2/dubai,2/muscat,2/tbilisi,2/yerevan,8/astrakhan,8/samara,8/saratov,8/ulyanovsk,8/volgograd,2/volgograd,9/mahe,9/mauritius","4.5|n|03/22:00->09/21:24":"2/tehran","4.5|n":"2/kabul","3|s":"12/syowa,9/antananarivo","3|n|03/31:03->10/27:04":"2/nicosia,8/athens,8/bucharest,8/helsinki,8/kiev,8/mariehamn,8/nicosia,8/riga,8/sofia,8/tallinn,8/uzhgorod,8/vilnius,8/zaporozhye","3|n|03/31:02->10/27:03":"8/chisinau,8/tiraspol","3|n|03/31:00->10/26:24":"2/beirut","3|n|03/29:02->10/27:02":"2/jerusalem,2/tel_aviv","3|n|03/29:00->10/26:01":"2/gaza,2/hebron","3|n|03/29:00->10/25:01":"2/amman","3|n|03/29:00->10/24:24":"2/damascus","3|n":"0/addis_ababa,0/asmara,0/asmera,0/dar_es_salaam,0/djibouti,0/juba,0/kampala,0/mogadishu,0/nairobi,2/aden,2/baghdad,2/bahrain,2/istanbul,2/kuwait,2/qatar,2/riyadh,8/istanbul,8/kirov,8/minsk,8/moscow,8/simferopol,9/comoro,9/mayotte","2|s|03/31:02->10/27:02":"12/troll","2|s":"0/gaborone,0/harare,0/johannesburg,0/lubumbashi,0/lusaka,0/maputo,0/maseru,0/mbabane","2|n|03/31:02->10/27:03":"0/ceuta,arctic/longyearbyen,3/jan_mayen,8/amsterdam,8/andorra,8/belgrade,8/berlin,8/bratislava,8/brussels,8/budapest,8/busingen,8/copenhagen,8/gibraltar,8/ljubljana,8/luxembourg,8/madrid,8/malta,8/monaco,8/oslo,8/paris,8/podgorica,8/prague,8/rome,8/san_marino,8/sarajevo,8/skopje,8/stockholm,8/tirane,8/vaduz,8/vatican,8/vienna,8/warsaw,8/zagreb,8/zurich","2|n":"0/blantyre,0/bujumbura,0/cairo,0/khartoum,0/kigali,0/tripoli,8/kaliningrad","1|s|04/02:01->09/03:03":"0/windhoek","1|s":"0/kinshasa,0/luanda","1|n|05/05:03->06/09:02":"0/casablanca,0/el_aaiun","1|n|03/31:01->10/27:02":"3/canary,3/faeroe,3/faroe,3/madeira,8/belfast,8/dublin,8/guernsey,8/isle_of_man,8/jersey,8/lisbon,8/london","1|n":"0/algiers,0/bangui,0/brazzaville,0/douala,0/lagos,0/libreville,0/malabo,0/ndjamena,0/niamey,0/porto-novo,0/tunis","14|n":"11/kiritimati","13|s|04/07:04->09/29:03":"11/apia","13|s|01/15:02->11/05:03":"11/tongatapu","13|n":"11/enderbury,11/fakaofo","12|s|04/07:03->09/29:02":"12/mcmurdo,12/south_pole,11/auckland","12|s|01/13:03->11/10:02":"11/fiji","12|n":"2/anadyr,2/kamchatka,2/srednekolymsk,11/funafuti,11/kwajalein,11/majuro,11/nauru,11/tarawa,11/wake,11/wallis","12.75|s|04/07:03->09/29:02":"11/chatham","11|s":"12/macquarie,11/bougainville","11|n":"2/magadan,2/sakhalin,11/efate,11/guadalcanal,11/kosrae,11/noumea,11/pohnpei,11/ponape","11.5|n":"11/norfolk","10|s|04/07:03->10/06:02":"4/act,4/canberra,4/currie,4/hobart,4/melbourne,4/nsw,4/sydney,4/tasmania,4/victoria","10|s":"12/dumontdurville,4/brisbane,4/lindeman,4/queensland","10|n":"2/ust-nera,2/vladivostok,2/yakutsk,11/chuuk,11/guam,11/port_moresby,11/saipan,11/truk,11/yap","10.5|s|04/07:01->10/06:02":"4/lhi,4/lord_howe","0|n|03/31:00->10/27:01":"1/scoresbysund,3/azores","0|n":"0/abidjan,0/accra,0/bamako,0/banjul,0/bissau,0/conakry,0/dakar,0/freetown,0/lome,0/monrovia,0/nouakchott,0/ouagadougou,0/sao_tome,0/timbuktu,1/danmarkshavn,3/reykjavik,3/st_helena,13/gmt,13/gmt+0,13/gmt-0,13/gmt0,13/greenwich,13/utc,13/universal,13/zulu","-9|n|03/10:02->11/03:02":"1/adak,1/atka","-9|n":"11/gambier","-9.5|n":"11/marquesas","-8|n|03/10:02->11/03:02":"1/anchorage,1/juneau,1/metlakatla,1/nome,1/sitka,1/yakutat","-8|n":"11/pitcairn","-7|n|03/10:02->11/03:02":"1/dawson,1/ensenada,1/los_angeles,1/santa_isabel,1/tijuana,1/vancouver,1/whitehorse,6/pacific,6/yukon,10/bajanorte","-7|n":"1/creston,1/dawson_creek,1/hermosillo,1/phoenix","-6|s|04/06:22->09/07:22":"7/easterisland,11/easter","-6|n|04/07:02->10/27:02":"1/chihuahua,1/mazatlan,10/bajasur","-6|n|03/10:02->11/03:02":"1/boise,1/cambridge_bay,1/denver,1/edmonton,1/inuvik,1/ojinaga,1/shiprock,1/yellowknife,6/mountain","-6|n":"1/belize,1/costa_rica,1/el_salvador,1/guatemala,1/managua,1/regina,1/swift_current,1/tegucigalpa,6/east-saskatchewan,6/saskatchewan,11/galapagos","-5|s":"1/lima,1/rio_branco,5/acre","-5|n|04/07:02->10/27:02":"1/bahia_banderas,1/merida,1/mexico_city,1/monterrey,10/general","-5|n|03/12:03->11/05:01":"1/north_dakota","-5|n|03/10:02->11/03:02":"1/chicago,1/knox_in,1/matamoros,1/menominee,1/rainy_river,1/rankin_inlet,1/resolute,1/winnipeg,6/central","-5|n":"1/atikokan,1/bogota,1/cancun,1/cayman,1/coral_harbour,1/eirunepe,1/guayaquil,1/jamaica,1/panama,1/porto_acre","-4|s|05/13:23->08/13:01":"12/palmer","-4|s|04/06:24->09/08:00":"1/santiago,7/continental","-4|s|03/23:24->10/06:00":"1/asuncion","-4|s|02/16:24->11/03:00":"1/campo_grande,1/cuiaba","-4|s":"1/la_paz,1/manaus,5/west","-4|n|03/12:03->11/05:01":"1/indiana,1/kentucky","-4|n|03/10:02->11/03:02":"1/detroit,1/fort_wayne,1/grand_turk,1/indianapolis,1/iqaluit,1/louisville,1/montreal,1/nassau,1/new_york,1/nipigon,1/pangnirtung,1/port-au-prince,1/thunder_bay,1/toronto,6/eastern","-4|n|03/10:00->11/03:01":"1/havana","-4|n":"1/anguilla,1/antigua,1/aruba,1/barbados,1/blanc-sablon,1/boa_vista,1/caracas,1/curacao,1/dominica,1/grenada,1/guadeloupe,1/guyana,1/kralendijk,1/lower_princes,1/marigot,1/martinique,1/montserrat,1/port_of_spain,1/porto_velho,1/puerto_rico,1/santo_domingo,1/st_barthelemy,1/st_kitts,1/st_lucia,1/st_thomas,1/st_vincent,1/tortola,1/virgin","-3|s":"1/argentina,1/buenos_aires,1/cordoba,1/fortaleza,1/montevideo,1/punta_arenas,1/sao_paulo,12/rothera,3/stanley,5/east","-3|n|03/10:02->11/03:02":"1/glace_bay,1/goose_bay,1/halifax,1/moncton,1/thule,3/bermuda,6/atlantic","-3|n":"1/araguaina,1/bahia,1/belem,1/catamarca,1/cayenne,1/jujuy,1/maceio,1/mendoza,1/paramaribo,1/recife,1/rosario,1/santarem","-2|s":"5/denoronha","-2|n|03/30:22->10/26:23":"1/godthab","-2|n|03/10:02->11/03:02":"1/miquelon","-2|n":"1/noronha,3/south_georgia","-2.5|n|03/10:02->11/03:02":"1/st_johns,6/newfoundland","-1|n":"3/cape_verde","-11|n":"11/midway,11/niue,11/pago_pago,11/samoa","-10|n":"11/honolulu,11/johnston,11/rarotonga,11/tahiti"}}))&&x.default||x,S={};Object.keys(P).forEach((function(t){var e=t.split("|"),n={offset:Number(e[0]),hem:e[1]};e[2]&&(n.dst=e[2]),P[t].split(",").forEach((function(t){t=t.replace(/(^[0-9]+)\//,(function(t,e){return e=Number(e),C[e]+"/"})),S[t]=n}))})),S.utc={offset:0,hem:"n"};for(var V=-14;V<=14;V+=.5){var E=V;E>0&&(E="+"+E);var N="etc/gmt"+E;S[N]={offset:-1*V,hem:"n"},S[N="utc/gmt"+E]={offset:-1*V,hem:"n"}}var A=S,$=/(\-?[0-9]+)h(rs)?/i,I=/(\-?[0-9]+)/,Y=/utc([\-+]?[0-9]+)/i,F=/gmt([\-+]?[0-9]+)/i,L=function(t){return(t=Number(t))>-13&&t<13?"etc/gmt"+(t=((t*=-1)>0?"+":"")+t):null},H=function(t){var e=t.match($);if(null!==e)return L(e[1]);if(null!==(e=t.match(Y)))return L(e[1]);if(null!==(e=t.match(F))){var n=-1*Number(e[1]);return L(n)}return null!==(e=t.match(I))?L(e[1]):null},Q=function(){var t=function(){if("undefined"==typeof Intl||void 0===Intl.DateTimeFormat)return null;var t=Intl.DateTimeFormat();if(void 0===t||void 0===t.resolvedOptions)return null;var e=t.resolvedOptions().timeZone;return e?e.toLowerCase():null}();return null===t?"utc":t}(),Z=Object.keys(A).reduce((function(t,e){var n=e.split("/")[1]||"";return t[n=n.replace(/_/g," ")]=e,t}),{}),W=function(t,e){if(!t)return Q;var n=t.trim(),a=t.split("/");if(a.length>2&&!1===e.hasOwnProperty(n)&&(n=a[0]+"/"+a[1]),n=n.toLowerCase(),!0===e.hasOwnProperty(n))return n;if(n=function(t){return t=(t=(t=(t=(t=(t=t.replace(/ time/g,"")).replace(/ (standard|daylight|summer)/g,"")).replace(/\b(east|west|north|south)ern/g,"$1")).replace(/\b(africa|america|australia)n/g,"$1")).replace(/\beuropean/g,"europe")).replace(/\islands/g,"island")}(n),!0===e.hasOwnProperty(n))return n;if(!0===Z.hasOwnProperty(n))return Z[n];if(!0===/[0-9]/.test(n)){var r=H(n);if(r)return r}throw new Error("Spacetime: Cannot find timezone named: '"+t+"'. Please enter an IANA timezone id.")},B={millisecond:1,second:1e3,minute:6e4,hour:36e5,day:864e5};B.date=B.day,B.month=25488e5,B.week=6048e5,B.year=3154e7,Object.keys(B).forEach((function(t){B[t+"s"]=B[t]}));var G=B,U=function(t,e,n,a,r){var o=t.d[n]();if(o!==e){var i=null===r?null:t.d[r](),u=t.epoch,s=e-o;t.epoch+=G[a]*s,"day"===a&&Math.abs(s)>28&&e<28&&(t.epoch+=G.hour);for(var c=G[a]/2;t.d[n]()e;)t.epoch-=c;null!==r&&i!==t.d[r]()&&(t.epoch=u,t.epoch+=G[a]*s*.89)}},R={year:{valid:function(t){return t>-4e3&&t<4e3},walkTo:function(t,e){return U(t,e,"getFullYear","year",null)}},month:{valid:function(t){return t>=0&&t<=11},walkTo:function(t,e){var n=t.d,a=n.getMonth(),r=t.epoch,o=n.getFullYear();if(a!==e){var i=e-a;for(t.epoch+=G.day*(28*i),o!==t.d.getFullYear()&&(t.epoch=r);t.d.getMonth()e;)t.epoch-=G.day}}},date:{valid:function(t){return t>0&&t<=31},walkTo:function(t,e){return U(t,e,"getDate","day","getMonth")}},hour:{valid:function(t){return t>=0&&t<24},walkTo:function(t,e){return U(t,e,"getHours","hour","getDate")}},minute:{valid:function(t){return t>=0&&t<60},walkTo:function(t,e){return U(t,e,"getMinutes","minute","getHours")}},second:{valid:function(t){return t>=0&&t<60},walkTo:function(t,e){t.epoch=t.seconds(e).epoch}},millisecond:{valid:function(t){return t>=0&&t<1e3},walkTo:function(t,e){t.epoch=t.milliseconds(e).epoch}}},J=function(t,e){for(var n=Object.keys(R),a=t.clone(),r=0;r100&&(n/=100),(n*=-1)>=0&&(n="+"+n);var a="etc/gmt"+n;return t.timezones[a]&&(t.tz=a),t},ot=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=(e=e.replace(/^\s+/,"").toLowerCase()).match(/([0-9]{1,2}):([0-9]{1,2}):?([0-9]{1,2})?[:\.]?([0-9]{1,4})?/);if(null!==n){var a=Number(n[1]);if(a<0||a>24)return t.startOf("day");var r=Number(n[2]);if(n[2].length<2||r<0||r>59)return t.startOf("day");t=(t=(t=(t=t.hour(a)).minute(r)).seconds(n[3]||0)).millisecond(n[4]||0);var o=e.match(/[\b0-9](am|pm)\b/);return null!==o&&o[1]&&(t=t.ampm(o[1])),t}if(null!==(n=e.match(/([0-9]+) ?(am|pm)/))&&n[1]){var i=Number(n[1]);return i>12||i<1?t.startOf("day"):t=(t=(t=t.hour(n[1]||0)).ampm(n[2])).startOf("hour")}return t=t.startOf("day")},it=[31,28,31,30,31,30,31,31,30,31,30,31],ut=q.isLeapYear,st=function(t){if(!0!==it.hasOwnProperty(t.month))return!1;if(1===t.month)return!!(ut(t.year)&&t.date<=29)||t.date<=28;var e=it[t.month]||0;return t.date<=e},ct=nt(),dt=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=parseInt(t.trim(),10);return e=e||(new Date).getFullYear()},ht=[{reg:/^(\-?0?0?[0-9]{3,4})-([0-9]{1,2})-([0-9]{1,2})[T| ]([0-9.:]+)(Z|[0-9\-\+:]+)?$/,parse:function(t,e,n,a){var r=parseInt(e[2],10)-1,o={year:e[1],month:r,date:e[3]};return!1===st(o)?(t.epoch=null,t):(rt(t,e[5]),J(t,o),t=ot(t,e[4]))}},{reg:/^([0-9]{4})[\-\/]([0-9]{1,2})[\-\/]([0-9]{1,2}),?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i,parse:function(t,e){var n={year:e[1],month:parseInt(e[2],10)-1,date:parseInt(e[3],10)};return n.month>=12&&(n.date=parseInt(e[2],10),n.month=parseInt(e[3],10)-1),!1===st(n)?(t.epoch=null,t):(J(t,n),t=ot(t,e[4]))}},{reg:/^([0-9]{1,2})[\-\/]([0-9]{1,2})[\-\/]?([0-9]{4})?,?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i,parse:function(t,e){var n=parseInt(e[1],10)-1,a=parseInt(e[2],10);(t.british||n>=12)&&(a=parseInt(e[1],10),n=parseInt(e[2],10)-1);var r={year:e[3]||(new Date).getFullYear(),month:n,date:a};return!1===st(r)?(t.epoch=null,t):(J(t,r),t=ot(t,e[4]))}},{reg:/^([0-9]{1,2})[\-\/]([a-z]+)[\-\/]?([0-9]{4})?$/i,parse:function(t,e){var n=ct[e[2].toLowerCase()],a={year:dt(e[3]),month:n,date:q.toCardinal(e[1]||"")};return!1===st(a)?(t.epoch=null,t):(J(t,a),t=ot(t,e[4]))}},{reg:/^([a-z]+) ([0-9]{1,2}(?:st|nd|rd|th)?),?( [0-9]{4})?( ([0-9:]+( ?am| ?pm| ?gmt)?))?$/i,parse:function(t,e){var n=ct[e[1].toLowerCase()],a={year:dt(e[3]),month:n,date:q.toCardinal(e[2]||"")};return!1===st(a)?(t.epoch=null,t):(J(t,a),t=ot(t,e[4]))}},{reg:/^([a-z]+) ([0-9]{4})$/i,parse:function(t,e){var n=ct[e[1].toLowerCase()],a={year:dt(e[2]),month:n,date:1};return!1===st(a)?(t.epoch=null,t):(J(t,a),t=ot(t,e[4]))}},{reg:/^([0-9]{1,2}(?:st|nd|rd|th)?) ([a-z]+),?( [0-9]{4})?,? ?([0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i,parse:function(t,e){var n=ct[e[2].toLowerCase()];if(!n)return null;var a={year:dt(e[3]),month:n,date:q.toCardinal(e[1])};return!1===st(a)?(t.epoch=null,t):(J(t,a),t=ot(t,e[4]))}},{reg:/^[0-9,]+ ?b\.?c\.?$/i,parse:function(t,e){var n=e[0]||"";n=(n=n.replace(/^([0-9,]+) ?b\.?c\.?$/i,"-$1")).replace(/,/g,"");var a=parseInt(n.trim(),10),r=new Date,o={year:a,month:r.getMonth(),date:r.getDate()};return!1===st(o)?(t.epoch=null,t):(J(t,o),t=ot(t))}},{reg:/^[0-9,]+ ?(a\.?d\.?|c\.?e\.?)$/i,parse:function(t,e){var n=e[0]||"";n=n.replace(/,/g,"");var a=parseInt(n.trim(),10),r=new Date,o={year:a,month:r.getMonth(),date:r.getDate()};return!1===st(o)?(t.epoch=null,t):(J(t,o),t=ot(t))}},{reg:/^[0-9]{4}( ?a\.?d\.?)?$/i,parse:function(t,e){var n=dt(e[0]),a=new Date,r={year:n,month:a.getMonth(),date:a.getDate()};return!1===st(r)?(t.epoch=null,t):(J(t,r),t=ot(t))}}],lt={now:function(t){return t.epoch=Date.now(),t},tonight:function(t){return t.epoch=Date.now(),t=t.hour(18)},today:function(t){return t.epoch=Date.now(),t},tomorrow:function(t){return t.epoch=Date.now(),t=(t=t.add(1,"day")).startOf("day")},yesterday:function(t){return t.epoch=Date.now(),t=(t=t.subtract(1,"day")).startOf("day")},christmas:function(t){var e=(new Date).getFullYear();return t=t.set([e,11,25,18,0,0])},"new years":function(t){var e=(new Date).getFullYear();return t=t.set([e,11,31,18,0,0])}};lt["new years eve"]=lt["new years"];var mt=lt,ft={year:(new Date).getFullYear(),month:0,date:1},yt=function(t,e,n){if("number"==typeof e)return e>0&&e<25e8&&!1===t.silent&&(console.warn(" - Warning: You are setting the date to January 1970."),console.warn(" - did input seconds instead of milliseconds?")),t.epoch=e,t;if(t.epoch=Date.now(),null==e)return t;if(!0===q.isDate(e))return t.epoch=e.getTime(),t;if(!0===q.isArray(e))return t=function(t,e){for(var n=["year","month","date","hour","minute","second","millisecond"],a=0;a=0?Math.floor(e):Math.ceil(e)),n?(e*=-1,e="-"+(e=q.zeroPad(e,2))):e="+"+(e=q.zeroPad(e,2)),"+00:00"===(e=e+":"+a)&&(e="Z"),e},Dt={day:function(t){return q.titleCase(t.dayName())},"day-short":function(t){return q.titleCase(vt()[t.day()])},"day-number":function(t){return t.day()},"day-ordinal":function(t){return q.ordinal(t.day())},"day-pad":function(t){return q.zeroPad(t.day())},date:function(t){return t.date()},"date-ordinal":function(t){return q.ordinal(t.date())},"date-pad":function(t){return q.zeroPad(t.date())},month:function(t){return q.titleCase(t.monthName())},"month-short":function(t){return q.titleCase(tt()[t.month()])},"month-number":function(t){return t.month()},"month-ordinal":function(t){return q.ordinal(t.month())},"month-pad":function(t){return q.zeroPad(t.month())},"iso-month":function(t){return q.zeroPad(t.month()+1)},year:function(t){var e=t.year();return e>0?e:(e=Math.abs(e),e+" BC")},"year-short":function(t){var e=t.year();return e>0?"'".concat(String(t.year()).substr(2,4)):(e=Math.abs(e))+" BC"},"iso-year":function(t){var e=t.year(),n=e<0,a=q.zeroPad(Math.abs(e),4);return n&&(a="-"+(a=q.zeroPad(a,6))),a},time:function(t){return t.time()},"time-24":function(t){return"".concat(t.hour24(),":").concat(q.zeroPad(t.minute()))},hour:function(t){return t.hour12()},"hour-pad":function(t){return q.zeroPad(t.hour12())},"hour-24":function(t){return t.hour24()},"hour-24-pad":function(t){return q.zeroPad(t.hour24())},minute:function(t){return t.minute()},"minute-pad":function(t){return q.zeroPad(t.minute())},second:function(t){return t.second()},"second-pad":function(t){return q.zeroPad(t.second())},ampm:function(t){return t.ampm()},quarter:function(t){return"Q"+t.quarter()},season:function(t){return t.season()},era:function(t){return t.era()},json:function(t){return t.json()},timezone:function(t){return t.timezone().name},offset:function(t){return kt(t)},numeric:function(t){return"".concat(t.year(),"/").concat(q.zeroPad(t.month()+1),"/").concat(q.zeroPad(t.date()))},"numeric-us":function(t){return"".concat(q.zeroPad(t.month()+1),"/").concat(q.zeroPad(t.date()),"/").concat(t.year())},"numeric-uk":function(t){return"".concat(q.zeroPad(t.date()),"/").concat(q.zeroPad(t.month()+1),"/").concat(t.year())},"mm/dd":function(t){return"".concat(q.zeroPad(t.month()+1),"/").concat(q.zeroPad(t.date()))},iso:function(t){var e=t.format("iso-year"),n=q.zeroPad(t.month()+1),a=q.zeroPad(t.date()),r=q.zeroPad(t.h24()),o=q.zeroPad(t.minute()),i=q.zeroPad(t.second()),u=q.zeroPad(t.millisecond(),3),s=kt(t);return"".concat(e,"-").concat(n,"-").concat(a,"T").concat(r,":").concat(o,":").concat(i,".").concat(u).concat(s)},"iso-short":function(t){var e=q.zeroPad(t.month()+1),n=q.zeroPad(t.date());return"".concat(t.year(),"-").concat(e,"-").concat(n)},"iso-utc":function(t){return new Date(t.epoch).toISOString()},nice:function(t){return"".concat(tt()[t.month()]," ").concat(q.ordinal(t.date()),", ").concat(t.time())},"nice-year":function(t){return"".concat(tt()[t.month()]," ").concat(q.ordinal(t.date()),", ").concat(t.year())},"nice-day":function(t){return"".concat(vt()[t.day()]," ").concat(q.titleCase(tt()[t.month()])," ").concat(q.ordinal(t.date()))},"nice-full":function(t){return"".concat(t.dayName()," ").concat(q.titleCase(t.monthName())," ").concat(q.ordinal(t.date()),", ").concat(t.time())}},zt={"day-name":"day","month-name":"month","iso 8601":"iso","time-h24":"time-24","time-12":"time","time-h12":"time",tz:"timezone","day-num":"day-number","month-num":"month-number","month-iso":"iso-month","year-iso":"iso-year","nice-short":"nice",mdy:"numeric-us",dmy:"numeric-uk",ymd:"numeric","yyyy/mm/dd":"numeric","mm/dd/yyyy":"numeric-us","dd/mm/yyyy":"numeric-us","little-endian":"numeric-uk","big-endian":"numeric","day-nice":"nice-day"};Object.keys(zt).forEach((function(t){return Dt[t]=Dt[zt[t]]}));var Ot=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(!0!==t.isValid())return"";if(Dt.hasOwnProperty(e)){var n=Dt[e](t)||"";return"json"!==e&&(n=String(n),"ampm"!==e&&(n=q.titleCase(n))),n}if(-1!==e.indexOf("{")){var a=/\{(.+?)\}/g;return e=e.replace(a,(function(e,n){return n=n.toLowerCase().trim(),Dt.hasOwnProperty(n)?String(Dt[n](t)||""):""}))}return t.format("iso-short")},jt=q.zeroPad,xt=q.formatTimezone,qt={G:function(t){return t.era()},GG:function(t){return t.era()},GGG:function(t){return t.era()},GGGG:function(t){return"AD"===t.era()?"Anno Domini":"Before Christ"},y:function(t){return t.year()},yy:function(t){return parseInt(String(t.year()).substr(2,4),10)},yyy:function(t){return t.year()},yyyy:function(t){return t.year()},yyyyy:function(t){return"0"+t.year()},Q:function(t){return t.quarter()},QQ:function(t){return t.quarter()},QQQ:function(t){return t.quarter()},QQQQ:function(t){return t.quarter()},M:function(t){return t.month()+1},MM:function(t){return jt(t.month()+1)},MMM:function(t){return t.format("month-short")},MMMM:function(t){return t.format("month")},w:function(t){return t.week()},ww:function(t){return jt(t.week())},d:function(t){return t.date()},dd:function(t){return jt(t.date())},D:function(t){return t.dayOfYear()},DD:function(t){return jt(t.dayOfYear())},DDD:function(t){return jt(t.dayOfYear(),3)},E:function(t){return t.format("day-short")},EE:function(t){return t.format("day-short")},EEE:function(t){return t.format("day-short")},EEEE:function(t){return t.format("day")},EEEEE:function(t){return t.format("day")[0]},e:function(t){return t.day()},ee:function(t){return t.day()},eee:function(t){return t.format("day-short")},eeee:function(t){return t.format("day")},eeeee:function(t){return t.format("day")[0]},a:function(t){return t.ampm().toUpperCase()},aa:function(t){return t.ampm().toUpperCase()},aaa:function(t){return t.ampm().toUpperCase()},aaaa:function(t){return t.ampm().toUpperCase()},h:function(t){return t.h12()},hh:function(t){return jt(t.h12())},H:function(t){return t.hour()},HH:function(t){return jt(t.hour())},m:function(t){return t.minute()},mm:function(t){return jt(t.minute())},s:function(t){return t.second()},ss:function(t){return jt(t.second())},A:function(t){return t.epoch-t.startOf("day").epoch},z:function(t){return t.timezone().name},zz:function(t){return t.timezone().name},zzz:function(t){return t.timezone().name},zzzz:function(t){return t.timezone().name},Z:function(t){return xt(t.timezone().current.offset)},ZZ:function(t){return xt(t.timezone().current.offset)},ZZZ:function(t){return xt(t.timezone().current.offset)},ZZZZ:function(t){return xt(t.timezone().current.offset,":")}},Tt=function(t,e,n){for(var a=t,r=e,o=0;o.5&&(t=t.add(1,e)),t=t.startOf(e)):!1===t.silent&&console.warn("no known unit '"+e+"'"),t},Vt=function(t,e,n){var a=0;for(t=t.clone();t.isBefore(e);)t=t.add(1,n),a+=1;return t.isAfter(e,n)&&(a-=1),a},Et=function(t,e,n){return t.isBefore(e)?Vt(t,e,n):-1*Vt(e,t,n)},Nt=function(t,e){var n=e.epoch-t.epoch,a={milliseconds:n,seconds:parseInt(n/1e3,10)};a.minutes=parseInt(a.seconds/60,10),a.hours=parseInt(a.minutes/60,10);var r=t.clone();return a.years=function(t,e){var n=e.year()-t.year();return(t=t.year(e.year())).isAfter(e)&&(n-=1),n}(r,e),r=t.add(a.years,"year"),a.months=12*a.years,r=t.add(a.months,"month"),a.months+=Et(r,e,"month"),a.weeks=52*a.years,r=t.add(a.weeks,"week"),a.weeks+=Et(r,e,"week"),a.days=7*a.weeks,r=t.add(a.days,"day"),a.days+=Et(r,e,"day"),a},At=function(t,e,n){e=q.beADate(e,t);var a=!1;if(t.isAfter(e)){var r=t;t=e,e=r,a=!0}var o=Nt(t,e);return a&&(o=function(t){return Object.keys(t).forEach((function(e){t[e]*=-1})),t}(o)),n?(n=q.normalize(n),!0!==/s$/.test(n)&&(n+="s"),"dates"===n&&(n="days"),o[n]):o},$t={months:{almost:10,over:4},days:{almost:25,over:10},hours:{almost:20,over:8},minutes:{almost:50,over:20},seconds:{almost:50,over:20}};function It(t,e){return 1===t&&(e=e.slice(0,-1)),t+" "+e}var Yt=function(t,e){var n,a,r,o=function(t,e){var n=t.isBefore(e),a=n?e:t,r=n?t:e;r=r.clone();var o={years:0,months:0,days:0,hours:0,minutes:0,seconds:0};return Object.keys(o).forEach((function(t){if(!r.isSame(a,t)){var e=r.diff(a,t);r=r.add(e,t),o[t]=e}})),n&&Object.keys(o).forEach((function(t){0!==o[t]&&(o[t]*=-1)})),o}(t,e=q.beADate(e,t));if(!0===Object.keys(o).every((function(t){return!o[t]})))return{diff:o,rounded:"now",qualified:"now",precise:"now"};var i=[];return Object.keys(o).forEach((function(t,e,r){var u=Math.abs(o[t]);if(0!==u){var s=It(u,t);if(i.push(s),!n){if(n=a=s,e>4)return;var c=r[e+1],d=Math.abs(o[c]);d>$t[c].almost?(n=It(u+1,t),a="almost "+n):d>$t[c].over&&(a="over "+s)}}})),r=i.splice(0,2).join(", "),!0===t.isAfter(e)?(n+=" ago",a+=" ago",r+=" ago"):(n="in "+n,a="in "+a,r="in "+r),{diff:o,rounded:n,qualified:a,precise:r}},Ft={north:[["spring",2,1],["summer",5,1],["fall",8,1],["autumn",8,1],["winter",11,1]],south:[["fall",2,1],["autumn",2,1],["winter",5,1],["spring",8,1],["summer",11,1]]},Lt=[null,[0,1],[3,1],[6,1],[9,1]],Ht={minute:function(t){return J(t,{second:0,millisecond:0}),t},quarterhour:function(t){var e=t.minutes();return t=e>=45?t.minutes(45):e>=30?t.minutes(30):e>=15?t.minutes(15):t.minutes(0),J(t,{second:0,millisecond:0}),t},hour:function(t){return J(t,{minute:0,second:0,millisecond:0}),t},day:function(t){return J(t,{hour:0,minute:0,second:0,millisecond:0}),t},week:function(t){var e=t.clone();return(t=t.day(t._weekStart)).isAfter(e)&&(t=t.subtract(1,"week")),J(t,{hour:0,minute:0,second:0,millisecond:0}),t},month:function(t){return J(t,{date:1,hour:0,minute:0,second:0,millisecond:0}),t},quarter:function(t){var e=t.quarter();return Lt[e]&&J(t,{month:Lt[e][0],date:Lt[e][1],hour:0,minute:0,second:0,millisecond:0}),t},season:function(t){var e=t.season(),n="north";"South"===t.hemisphere()&&(n="south");for(var a=0;a1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0;if(!e||!n)return[];if(e=q.normalize(e),n=t.clone().set(n),t.isAfter(n)){var a=t;t=n,n=a}var r=t.clone();Wt(e)?(r=r.next(e),e="week"):r=r.next(e);for(var o=[];r.isBefore(n);)o.push(r),r=r.add(1,e);return o},Gt=function(t){var e=t.timezones,n=t.tz;if(!1===e.hasOwnProperty(n)&&(n=W(t.tz,e)),null===n)return!1===t.silent&&console.warn("Warn: could not find given or local timezone - '"+t.tz+"'"),{current:{epochShift:0}};var a,r,o=e[n],i={name:(a=n,a=(a=(a=a[0].toUpperCase()+a.substr(1)).replace(/\/gmt/,"/GMT")).replace(/[\/_]([a-z])/gi,(function(t){return t.toUpperCase()}))),hasDst:Boolean(o.dst),default_offset:o.offset,hemisphere:"s"===o.hem?"South":"North",current:{}};if(i.hasDst){var u=(r=o.dst)?r.split("->"):[];i.change={start:u[0],back:u[1]}}var s=o.offset,c=s;return!0===i.hasDst&&(c="North"===i.hemisphere?s-1:o.offset+1),!1===i.hasDst?(i.current.offset=s,i.current.isDST=!1):!0===_(t.epoch,i.change.start,i.change.back,s)?(i.current.offset=s,i.current.isDST="North"===i.hemisphere):(i.current.offset=c,i.current.isDST="South"===i.hemisphere),i},Ut=["century","decade","year","month","date","day","hour","minute","second","millisecond"],Rt={set:function(t,e){var n=this.clone();return n=yt(n,t),e&&(this.tz=W(e)),n},timezone:function(){return Gt(this)},isDST:function(){return Gt(this).current.isDST},hasDST:function(){return Gt(this).hasDst},offset:function(){return 60*Gt(this).current.offset},hemisphere:function(){return Gt(this).hemisphere},format:function(t){return Ot(this,t)},unixFmt:function(t){return _t(this,t)},startOf:function(t){return Qt(this,t)},endOf:function(t){return Zt(this,t)},leapYear:function(){var t=this.year();return q.isLeapYear(t)},progress:function(t){return Pt(this,t)},nearest:function(t){return St(this,t)},diff:function(t,e){return At(this,t,e)},since:function(t){return t||(t=this.clone().set()),Yt(this,t)},next:function(t){return this.add(1,t).startOf(t)},last:function(t){return this.subtract(1,t).startOf(t)},isValid:function(){return!(!this.epoch&&0!==this.epoch)&&!isNaN(this.d.getTime())},goto:function(t){var e=this.clone();return e.tz=W(t,e.timezones),e},every:function(t,e){return Bt(this,t,e)},isAwake:function(){var t=this.hour();return!(t<8||t>22)},isAsleep:function(){return!this.isAwake()},log:function(){return console.log(""),console.log(Ot(this,"nice-short")),this},logYear:function(){return console.log(""),console.log(Ot(this,"full-short")),this},json:function(){var t=this;return Ut.reduce((function(e,n){return e[n]=t[n](),e}),{})},debug:function(){var t=this.timezone(),e=this.format("MM")+" "+this.format("date-ordinal")+" "+this.year();return e+="\n - "+this.format("time"),console.log("\n\n",e+"\n - "+t.name+" ("+t.current.offset+")"),this},from:function(t){return(t=this.clone().set(t)).since(this)},fromNow:function(){return this.clone().set(Date.now()).since(this)},weekStart:function(t){if("number"==typeof t)return this._weekStart=t,this;if("string"==typeof t){t=t.toLowerCase().trim();var e=vt().indexOf(t);-1===e&&(e=bt().indexOf(t)),-1===e&&(e=1),this._weekStart=e}else console.warn("Spacetime Error: Cannot understand .weekStart() input:",t);return this}};Rt.inDST=Rt.isDST,Rt.round=Rt.nearest,Rt.each=Rt.every;var Jt=Rt,Kt=function(t){return"string"==typeof t&&(t=parseInt(t,10)),t},Xt=["year","month","date","hour","minute","second","millisecond"],te=function(t,e,n){for(var a=Xt.indexOf(n),r=Xt.slice(a,Xt.length),o=0;o=24?e=24:e<0&&(e=0);var n=t.clone(),a=(t.hour()-e)*G.hour;return t.epoch-=a,J(t,{hour:e}),te(t,n,"minute"),t.epoch},oe=function(t,e){var n=e.match(/([0-9]{1,2}):([0-9]{1,2})(am|pm)?/);if(!n){if(!(n=e.match(/([0-9]{1,2})(am|pm)/)))return t.epoch;n.splice(2,0,"0")}var a=!1,r=parseInt(n[1],10),o=parseInt(n[2],10);return r>12&&(a=!0),!1===a&&("am"===n[3]&&12===r&&(r=0),"pm"===n[3]&&r<12&&(r+=12)),(t=(t=(t=(t=t.hour(r)).minute(o)).second(0)).millisecond(0)).epoch},ie=function(t,e){if((e=Kt(e))>28){var n=it[t.month()];e>n&&(e=n)}return e<=0&&(e=1),J(t,{date:e}),t.epoch},ue=function(t,e){"string"==typeof e&&(e=nt()[e.toLowerCase()]),(e=Kt(e))>=12&&(e=11),e<=0&&(e=0);var n=t.date();return n>it[e]&&(n=it[e]),J(t,{month:e,date:n}),t.epoch},se=function(t,e){return e=Kt(e),J(t,{year:e}),t.epoch},ce=function(t,e){e=Kt(e);var n=t.clone();return(e-=1)<=0?e=0:e>=365&&(e=364),t=(t=t.startOf("year")).add(e,"day"),te(t,n,"hour"),t.epoch},de={millisecond:function(t){if(void 0!==t){var e=this.clone();return e.epoch=ee(e,t),e}return this.d.getMilliseconds()},second:function(t){if(void 0!==t){var e=this.clone();return e.epoch=ne(e,t),e}return this.d.getSeconds()},minute:function(t){if(void 0!==t){var e=this.clone();return e.epoch=ae(e,t),e}return this.d.getMinutes()},hour:function(t){var e=this.d;if(void 0!==t){var n=this.clone();return n.epoch=re(n,t),n}return e.getHours()},hourFloat:function(t){if(void 0!==t){var e=this.clone(),n=t%1;n*=60;var a=parseInt(t,10);return e.epoch=re(e,a),e.epoch=ae(e,n),e}var r=this.d,o=r.getHours(),i=r.getMinutes();return o+(i/=60)},hour12:function(t){var e=this.d;if(void 0!==t){var n=this.clone(),a=(t=""+t).match(/^([0-9]+)(am|pm)$/);if(a){var r=parseInt(a[1],10);"pm"===a[2]&&(r+=12),n.epoch=re(n,r)}return n}var o=e.getHours();return o>12&&(o-=12),0===o&&(o=12),o},time:function(t){if(void 0!==t){var e=this.clone();return e.epoch=oe(e,t),e}return"".concat(this.h12(),":").concat(q.zeroPad(this.minute())).concat(this.ampm())},ampm:function(t){var e="am",n=this.hour();if(n>=12&&(e="pm"),"string"!=typeof t)return e;var a=this.clone();return t=t.toLowerCase().trim(),n>=12&&"am"===t?(n-=12,a.hour(n)):n<12&&"pm"===t?(n+=12,a.hour(n)):a},dayTime:function(t){if(void 0!==t){var e={morning:"7:00am",breakfast:"7:00am",noon:"12:00am",lunch:"12:00pm",afternoon:"2:00pm",evening:"6:00pm",dinner:"6:00pm",night:"11:00pm",midnight:"23:59pm"},n=this.clone();return t=(t=t||"").toLowerCase(),!0===e.hasOwnProperty(t)&&(n=n.time(e[t])),n}var a=this.hour();return a<6?"night":a<12?"morning":a<17?"afternoon":a<22?"evening":"night"},iso:function(t){return void 0!==t?this.set(t):this.format("iso")}},he={date:function(t){if(void 0!==t){var e=this.clone();return e.epoch=ie(e,t),e}return this.d.getDate()},day:function(t){if(void 0===t)return this.d.getDay();var e=this.clone(),n=t;"string"==typeof t&&(t=t.toLowerCase(),-1===(n=vt().indexOf(t))&&(n=bt().indexOf(t)));var a=this.d.getDay(),r=a-n,o=this.subtract(24*r,"hours");return J(o,{hour:e.hour(),minute:e.minute(),second:e.second()}),o},dayName:function(t){if(void 0===t)return bt()[this.day()];var e=this.clone();return e=e.day(t)},month:function(t){if(void 0!==t){var e=this.clone();return e.epoch=ue(e,t),e}return this.d.getMonth()}},le=function(t){return t=(t=(t=t.minute(0)).second(0)).millisecond(1)},me={dayOfYear:function(t){if(void 0!==t){var e=this.clone();return e.epoch=ce(e,t),e}for(var n,a=0,r=this.d.getMonth(),o=1;o<=r;o++)(n=new Date).setDate(1),n.setFullYear(this.d.getFullYear()),n.setHours(1),n.setMinutes(1),n.setMonth(o),n.setHours(-2),a+=n.getDate();return a+this.d.getDate()},week:function(t){if(void 0!==t){var e=this.clone();return e=(e=(e=e.month(0)).date(1)).day("monday"),"december"===(e=le(e)).monthName()&&(e=e.add(1,"week")),t-=1,e=e.add(t,"weeks")}var n=this.clone();n=(n=n.month(0)).date(1),"december"===(n=(n=le(n)).day("monday")).monthName()&&(n=n.add(1,"week"));var a=1;1===n.date()&&(a=0),n=n.minus(1,"second");var r=this.epoch;if(n.epoch>r)return 1;var o=0,i=4*this.month();for(n.epoch+=G.week*i,o+=i;o<52;o++){if(n.epoch>r)return o+a;n=n.add(1,"week")}return 52},monthName:function(t){if(void 0===t)return et()[this.month()];var e=this.clone();return e=e.month(t)},quarter:function(t){if(void 0!==t&&("string"==typeof t&&(t=t.replace(/^q/i,""),t=parseInt(t,10)),Lt[t])){var e=this.clone(),n=Lt[t][0];return e=(e=(e=e.month(n)).date(1)).startOf("day")}for(var a=this.d.getMonth(),r=1;r=Ft[e][o][1]&&r0&&(e.epoch=se(e,-1*n)),"ad"===t&&n<0&&(e.epoch=se(e,-1*n)),e}return this.d.getFullYear()<0?"BC":"AD"},decade:function(t){if(void 0!==t){if(!(t=(t=(t=String(t)).replace(/([0-9])'?s$/,"$1")).replace(/([0-9])(th|rd|st|nd)/,"$1")))return console.warn("Spacetime: Invalid decade input"),this;2===t.length&&/[0-9][0-9]/.test(t)&&(t="19"+t);var e=Number(t);return isNaN(e)?this:(e=10*Math.floor(e/10),this.year(e))}return this.startOf("decade").year()},century:function(t){if(void 0!==t){"string"==typeof t&&(t=(t=(t=t.replace(/([0-9])(th|rd|st|nd)/,"$1")).replace(/([0-9]+) ?(b\.?c\.?|a\.?d\.?)/i,(function(t,e,n){return n.match(/b\.?c\.?/i)&&(e="-"+e),e}))).replace(/c$/,""));var e=Number(t);return isNaN(t)?(console.warn("Spacetime: Invalid century input"),this):(0===e&&(e=1),e=e>=0?100*(e-1):100*(e+1),this.year(e))}var n=this.startOf("century").year();return(n=Math.floor(n/100))<0?n-1:n+1},millenium:function(t){if(void 0!==t){if("string"==typeof t&&(t=t.replace(/([0-9])(th|rd|st|nd)/,"$1"),t=Number(t),isNaN(t)))return console.warn("Spacetime: Invalid millenium input"),this;t>0&&(t-=1);var e=1e3*t;return 0===e&&(e=1),this.year(e)}var n=Math.floor(this.year()/1e3);return n>=0&&(n+=1),n}},fe=Object.assign({},de,he,me);fe.milliseconds=fe.millisecond,fe.seconds=fe.second,fe.minutes=fe.minute,fe.hours=fe.hour,fe.hour24=fe.hour,fe.h12=fe.hour12,fe.h24=fe.hour24,fe.days=fe.day;var ye=function(t){Object.keys(fe).forEach((function(e){t.prototype[e]=fe[e]}))},pe=["millisecond","second","minute","hour","date","month"],ge={second:pe.slice(0,1),minute:pe.slice(0,2),quarterhour:pe.slice(0,2),hour:pe.slice(0,3),date:pe.slice(0,4),month:pe.slice(0,4),quarter:pe.slice(0,4),season:pe.slice(0,4),year:pe,decade:pe,century:pe};ge.week=ge.hour,ge.season=ge.date,ge.quarter=ge.date;var ve={year:!0,quarter:!0,season:!0,month:!0,week:!0,day:!0},be={month:!0,quarter:!0,season:!0,year:!0},we=function(t){t.prototype.add=function(t,e){var n=this.clone();if(!e||0===t)return n;var a=this.clone();e=q.normalize(e),G[e]?n.epoch+=G[e]*t:"week"===e?n.epoch+=G.day*(7*t):"quarter"===e||"season"===e?n.epoch+=G.month*(4*t):"season"===e?n.epoch+=G.month*(4*t):"quarterhour"===e&&(n.epoch+=15*G.minute*t);var r={};if(ge[e]&&ge[e].forEach((function(t){r[t]=a[t]()})),ve[e]){var o=a.timezone().current.offset-n.timezone().current.offset;n.epoch+=3600*o*1e3}if("month"===e&&(r.month=a.month()+t,r=function(t,e){if(t.month>0){var n=parseInt(t.month/12,10);t.year=e.year()+n,t.month=t.month%12}else if(t.month<0){var a=Math.floor(Math.abs(t.month)/13,10);a=Math.abs(a)+1,t.year=e.year()-a,t.month=t.month%12,t.month=t.month+12,12===t.month&&(t.month=0)}return t}(r,a)),"week"===e){var i=a.date()+7*t;i<=28&&i>1&&(r.date=i)}else if("date"===e){var u=a.date()+t;u<=28&&u>1?r.date=u:0!==t&&a.isSame(n,"day")&&(r.date=a.date()+t)}else"year"===e&&n.year()===a.year()?n.epoch+=G.week:"decade"===e?r.year=n.year()+10:"century"===e&&(r.year=n.year()+100);if(be[e]){var s=it[r.month];r.date=a.date(),r.date>s&&(r.date=s)}return J(n,r),n},t.prototype.subtract=function(t,e){return this.clone().add(-1*t,e)},t.prototype.minus=t.prototype.subtract,t.prototype.plus=t.prototype.add},ke={millisecond:function(t){return t.epoch},second:function(t){return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second()].join("-")},minute:function(t){return[t.year(),t.month(),t.date(),t.hour(),t.minute()].join("-")},hour:function(t){return[t.year(),t.month(),t.date(),t.hour()].join("-")},day:function(t){return[t.year(),t.month(),t.date()].join("-")},week:function(t){return[t.year(),t.week()].join("-")},month:function(t){return[t.year(),t.month()].join("-")},quarter:function(t){return[t.year(),t.quarter()].join("-")},year:function(t){return t.year()}};ke.date=ke.day;var De=function(t){t.prototype.isSame=function(e,n){return n?("string"!=typeof e&&"number"!=typeof e||(e=new t(e,this.timezone.name)),n=n.replace(/s$/,""),ke[n]?ke[n](this)===ke[n](e):null):null}},ze=function(t){var e={isAfter:function(t){t=q.beADate(t,this);var e=q.getEpoch(t);return null===e?null:this.epoch>e},isBefore:function(t){t=q.beADate(t,this);var e=q.getEpoch(t);return null===e?null:this.epoch2&&void 0!==arguments[2]?arguments[2]:{};if(this.epoch=null,this.tz=W(e,je),this.silent=n.silent||!0,this.british=n.dmy||n.british,this._weekStart=1,void 0!==n.weekStart&&(this._weekStart=n.weekStart),Object.defineProperty(this,"d",{get:function(){var t=M(this),e=(new Date(this.epoch).getTimezoneOffset()||0)+60*t;e=60*e*1e3;var n=this.epoch+e;return new Date(n)}}),Object.defineProperty(this,"timezones",{get:function(){return je},set:function(t){return je=t,t}}),void 0!==t||null===t){var a=yt(this,t,e);this.epoch=a.epoch}};Object.keys(Jt).forEach((function(t){xe.prototype[t]=Jt[t]})),xe.prototype.clone=function(){return new xe(this.epoch,this.tz,{silent:this.silent,weekStart:this._weekStart})},ye(xe),we(xe),De(xe),ze(xe),Oe(xe);var qe=xe,Te=function(t,e){var n=new qe(null),a=new qe(null);n=n.time(t),a=e?a.time(e):n.add(59,"minutes");var r=n.hour(),o=a.hour();return Object.keys(n.timezones).filter((function(t){if(-1===t.indexOf("/"))return!1;var e=new qe(null,t),i=e.hour();return i>=r&&i<=o&&(!(i===r&&e.minute()a.minute()))}))},_e=function(t,e,n){return new qe(t,e,n)};_e.now=function(t,e){return new qe((new Date).getTime(),t,e)},_e.today=function(t,e){return new qe((new Date).getTime(),t,e).startOf("day")},_e.tomorrow=function(t,e){return new qe((new Date).getTime(),t,e).add(1,"day").startOf("day")},_e.yesterday=function(t,e){return new qe((new Date).getTime(),t,e).subtract(1,"day").startOf("day")},_e.extend=function(t){return Object.keys(t).forEach((function(e){qe.prototype[e]=t[e]})),this},_e.whereIts=Te,_e.version="6.3.0",_e.plugin=_e.extend;var Me=_e;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var Ce=function(t){return t&&t.default||t}(Object.freeze({__proto__:null,default:Me})),Pe=function(t){var e=t.match("(at|by|for|before)? #Time+");e.found&&t.remove(e),e=(e=e.not("(at|by|for|before|sharp)")).not("on the dot");var n=Ce.now(),a=n.clone(),r=e.match("^#Cardinal oclock (am|pm)?");if(r.found&&(r=r.not("oclock"),(n=n.hour(r.text("reduced"))).isValid()&&!n.isEqual(a)))return n.time();if((r=e.match("(half|quarter|25|15|10|5) (past|after|to) #Cardinal")).found&&(n=function(t,e){var n=t.match("#Cardinal$").text("reduced"),a=t.match("(half|quarter|25|15|10|5)"),r=a.text("reduced");a.has("half")&&(r="30"),a.has("quarter")&&(r="15");var o=t.has("to");return e=(e=e.hour(n)).startOf("hour"),e=o?e.subtract(r,"minutes"):e.add(r,"minutes")}(r,n)).isValid()&&!n.isEqual(a))return n.time();var o=e.text("reduced");return(n=n.time(o)).isValid()&&!n.isEqual(a)?n.time():null},Se=function(t){var e=null;return t.has("^this? (next|upcoming)")&&(e="next"),t.has("^this? (last|previous)")&&(e="last"),t.has("^(this|current)")&&(e="this"),t.remove("^(this|current|next|upcoming|last|previous)"),e},Ve=function(){function t(n,a){e(this,t),this.str=n,this.unit=a||"day";var r=Ce(n);r.isValid()&&(r=r.startOf(a)),Object.defineProperty(this,"d",{enumerable:!1,writable:!0,value:r})}return a(t,[{key:"clone",value:function(){var e=new t(this.str);return e.unit=this.unit,e}},{key:"applyShift",value:function(t){var e=this;return Object.keys(t).forEach((function(n){e.d=e.d.add(t[n],n)})),this}},{key:"applyTime",value:function(t){return this.d=t?this.d.time(t):this.d.startOf("day"),this}},{key:"format",value:function(t){return this.d.format(t)}},{key:"start",value:function(){return this.d=this.d.startOf(this.unit),this}},{key:"end",value:function(){return this.d=this.d.endOf(this.unit),this}},{key:"before",value:function(){return this.d=Ce.now(),this}},{key:"after",value:function(){return this.d=this.d.add(1,this.unit),this.d=this.d.startOf(this.unit),this}},{key:"next",value:function(){return this.d=this.d.add(1,this.unit),this.d=this.d.startOf(this.unit),this}},{key:"last",value:function(){return this.d=this.d.minus(1,this.unit),this.d=this.d.startOf(this.unit),this}}]),t}(),Ee={Unit:Ve,Day:function(t){function n(t,a){var r;return e(this,n),(r=u(this,o(n).call(this,t,a))).unit="day",r}return r(n,t),n}(Ve),Month:function(t){function n(t,a){var r;return e(this,n),(r=u(this,o(n).call(this,t,a))).unit="month",r}return r(n,t),n}(Ve),Quarter:function(t){function n(t,a){var r;return e(this,n),(r=u(this,o(n).call(this,t,a))).unit="quarter",r}return r(n,t),n}(Ve),Year:function(t){function n(t,a){var r;return e(this,n),(r=u(this,o(n).call(this,t,a))).unit="year",r}return r(n,t),n}(Ve),WeekDay:function(t){function n(t,a){var r;return e(this,n),(r=u(this,o(n).call(this,t,a))).unit="week",r.d=r.d.day(t),r.d.date()1&&(o=o.add(r[0]-1,"week")),o.isValid())return o}return null},g={easter:0,"ash wednesday":-46,"palm sunday":7,"maundy thursday":-3,"good friday":-2,"holy saturday":-1,"easter saturday":-1,"easter monday":1,"ascension day":39,"whit sunday":49,"whit monday":50,"trinity sunday":65,"corpus christi":60,"mardi gras":-47};g["easter sunday"]=g.easter,g.pentecost=g["whit sunday"],g.whitsun=g["whit sunday"];var v=g,b=function(t){var e=Math.floor,n=t%19,a=e(t/100),r=(a-e(a/4)-e((8*a+13)/25)+19*n+15)%30,o=r-e(r/28)*(1-e(29/(r+1))*e((21-n)/11)),i=o-(t+e(t/4)+o+2-a+e(a/4))%7,u=3+e((i+40)/44),s=i+28-31*e(u/4);return(u=4===u?"April":"March")+" "+s},w=function(e,n,a){if(v.hasOwnProperty(e)||v.hasOwnProperty(n)){var r=v[e]||v[n]||[],o=b(a);if(!o)return null;var i=t(o),u=(i=i.year(a)).add(r,"day");if(u.isValid())return u}return null},k={spring:[2003,2007,2044,2048,2052,2056,2060,2064,2068,2072,2076,2077,2080,2081,2084,2085,2088,2089,2092,2093,2096,2097],summer:[2021,2016,2020,2024,2028,2032,2036,2040,2041,2044,2045,2048,2049,2052,2053,2056,2057,2060,2061,2064,2065,2068,2069,2070,2072,2073,2074,2076,2077,2078,2080,2081,2082,2084,2085,2086,2088,2089,2090,2092,2093,2094,2096,2097,2098,2099],fall:[2002,2003,2004,2006,2007,2010,2011,2014,2015,2018,2019,2022,2023,2026,2027,2031,2035,2039,2043,2047,2051,2055,2059,2092,2096],winter:[2002,2003,2006,2007,2011,2015,2019,2023,2027,2031,2035,2039,2043,2080,2084,2088,2092,2096]},D=[2080,2084,2088,2092,2096],z=function(t){var e={spring:"March 20 "+t,summer:"June 21 "+t,fall:"Sept 22 "+t,winter:"Dec 21 "+t};return-1!==k.spring.indexOf(t)&&(e.spring="March 19 "+t),-1!==k.summer.indexOf(t)&&(e.summer="June 20 "+t),-1!==k.fall.indexOf(t)&&(e.fall="Sept 21 "+t),-1!==k.winter.indexOf(t)&&(e.winter="Dec 22 "+t),-1!==D.indexOf(t)&&(e.winter="Dec 20 "+t),e},O={"spring equinox":"spring","summer solistice":"summer","fall equinox":"fall","winter solstice":"winter"};O["march equinox"]=O["spring equinox"],O["vernal equinox"]=O["spring equinox"],O.ostara=O["spring equinox"],O["june solstice"]=O["summer solistice"],O.litha=O["summer solistice"],O["autumn equinox"]=O["fall equinox"],O["autumnal equinox"]=O["fall equinox"],O["september equinox"]=O["fall equinox"],O["sept equinox"]=O["fall equinox"],O.mabon=O["fall equinox"],O["december solstice"]=O["winter solistice"],O["dec solstice"]=O["winter solistice"],O.yule=O["winter solistice"];var j=O,x=function(e,n,a){if(j.hasOwnProperty(e)||j.hasOwnProperty(n)){var r=j[e]||j[n],o=z(a);if(!r||!o||!o[r])return null;var i=t(o[r]);if(i.isValid())return i}return null},q={"isra and miraj":"april 13","lailat al-qadr":"june 10","eid al-fitr":"june 15","id al-Fitr":"june 15","eid ul-Fitr":"june 15",ramadan:"may 16","eid al-adha":"sep 22",muharram:"sep 12","prophets birthday":"nov 21"},T=function(e,n,a){if(q.hasOwnProperty(e)||q.hasOwnProperty(n)){var r=q[e]||q[n]||[];if(!r)return null;var o=t(r+" 2018"),i=-10.64*(a-2018);if((o=(o=(o=o.add(i,"day")).startOf("day")).year(a)).isValid())return o}return null},_=t.now().year();return function(t,e){e=e||_,t=t||"";var n=(t=(t=(t=String(t)).trim().toLowerCase()).replace(/'s/,"s")).replace(/ day$/,"");n=(n=n.replace(/^the /,"")).replace(/^orthodox /,"");var a=l(t,n,e);return null!==a?a:null!==(a=p(t,n,e))?a:null!==(a=w(t,n,e))?a:null!==(a=x(t,n,e))?a:null!==(a=T(t,n,e))?a:null}}(Ce)})),Ie=function(t){var e=null,n=t.match("#Holiday+").text("reduced"),a=$e(n,2020);return null!==a&&(e=new Ee.CalendarDate(a)),e},Ye=Ee.Unit,Fe=function(t){t.has("#Number of #Month");var e=t.text("reduced"),n=new Ye(e);return!1===n.d.isValid()?null:n},Le=Ee.Unit,He=function(t){var e=j(t),n=Pe(t),a=Se(t),r=null;return!1===t.found&&null!==n&&(r=new Le),(r=(r=(r=r||Ae(t))||Ie(t))||Fe(t))?("last"===a&&r.last(),"next"===a&&r.next(),e&&r.applyShift(e),r.applyTime(n),r):null},Qe=function(t,e){var n=t.match("between * and *");if(n.found){var a=n.match("between [.*] and").not("^between").not("and$");a=He(a);var r=n.match("and *").not("^and");if(r=He(r),a)return{start:a,end:r}}if((n=t.match("#Month #Value to #Month #Value of? #Year")).found,(n=t.match("#Month #Value to #Month #Value")).found,(n=t.match("#Month #Value to #Value of? #Year")).found,(n=t.match("#Value to #Value of? #Month of? #Year")).found,(n=t.match("#Value to #Value of? #Month")).found,(n=t.match("#Month #Value to #Value")).found,(n=t.match("from? * (to|@hasHyphen|until|upto) [*]")).found,(n=t.match("^due (by|before|on|in)? [*]")).found,(n=t.match("^(after|following|from) [*]")).found,(n=t.match("^(on|during|in) [*]")).found){var o=He(n);if(o)return{start:o,end:o.clone().end()}}return{start:He(t),end:null}},Ze=function(t,e){return t=z(t),Qe(t)},We=[["mon","monday"],["tue","tuesday"],["tues","tuesday"],["wed","wednesday"],["thu","thursday"],["thurs","thursday"],["fri","friday"],["sat","saturday"],["sun","sunday"],["jan","january"],["feb","february"],["mar","march"],["apr","april"],["jun","june"],["jul","july"],["aug","august"],["sep","september"],["sept","september"],["oct","october"],["nov","november"],["dec","december"]],Be=We=We.map((function(t){return{short:t[0],long:t[1]}}));return function(n,i){i.addTags(w),i.addWords(D),i.postProcess(b);var s=function(t){function n(t,a,r){var i;return e(this,n),(i=u(this,o(n).call(this,t,a,r))).context={},i}return r(n,t),a(n,[{key:"json",value:function(t){var e=this,n=null;"number"==typeof t&&(n=t,t=null);var a=[],r=(t=t||{terms:!1}).format||"iso";return this.forEach((function(n){var o=n.json(t)[0],i=Ze(n,e.context),u=i.start?i.start.format(r):null,s=i.end?i.end.format(r):null;o.date={start:u,end:s},u&&s&&(o.date.duration=i.start.d.diff(i.end.d),delete o.date.duration.milliseconds,delete o.date.duration.seconds),a.push(o)})),null!==n?a[n]:a}},{key:"format",value:function(t){var e=this;return this.forEach((function(n){var a=Ze(n,e.context),r="";a.start&&(r=a.start.format(t),a.end&&(r+=" to "+a.start.format(t)),n.replaceWith(r,!0))})),this}},{key:"toLongForm",value:function(){var t=this;return Be.forEach((function(e){t.replace(e.short,e.long,!0,!0)})),this}},{key:"toShortForm",value:function(){var t=this;return Be.forEach((function(e){t.replace(e.long,e.short,!0,!0)})),this}}]),n}(n);n.prototype.dates=function(e){var n={};e&&"object"===t(e)&&(n=e,e=null);var a=this.clauses().match("#Date+");"number"==typeof e&&(a=a.get(e)),"number"==typeof e&&(a=a.get(e));var r=new s(a.list,this,this.world);return r.context=n,r}}})); diff --git a/plugins/dates/builds/compromise-dates.mjs b/plugins/dates/builds/compromise-dates.mjs new file mode 100644 index 000000000..77cb074b9 --- /dev/null +++ b/plugins/dates/builds/compromise-dates.mjs @@ -0,0 +1,5748 @@ +function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); +} + +function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); +} + +//ambiguous 'may' and 'march' +var preps = '(in|by|before|during|on|until|after|of|within|all)'; //6 + +var thisNext = '(last|next|this|previous|current|upcoming|coming)'; //2 + +var sections = '(start|end|middle|starting|ending|midpoint|beginning)'; //2 + +var seasons = '(spring|summer|winter|fall|autumn)'; //ensure a year is approximately typical for common years +//please change in one thousand years + +var tagYear = function tagYear(m, reason) { + if (m.found !== true) { + return; + } + + var term = m.termList()[0]; + + if (term) { + var num = parseInt(term.clean, 10); + + if (num && num > 1000 && num < 3000) { + m.tag('Year', reason); + } + } +}; //same, but for less-confident values + + +var tagYearSafe = function tagYearSafe(m, reason) { + if (m.found !== true) { + return; + } + + var term = m.termList()[0]; + + if (term) { + var num = parseInt(term.clean, 10); + + if (num && num > 1900 && num < 2030) { + m.tag('Year', reason); + } + } +}; + +var fixDates = function fixDates(doc) { + doc.match('in the (night|evening|morning|afternoon|day|daytime)').tag('Time', 'in-the-night'); + doc.match('(#Value|#Time) (am|pm)').tag('Time', 'value-ampm'); //months: + + var month = doc["if"]('#Month'); + + if (month.found === true) { + //June 5-7th + month.match("#Month #DateRange+").tag('Date', 'correction-numberRange'); //5th of March + + month.match('#Value of #Month').tag('Date', 'value-of-month'); //5 March + + month.match('#Cardinal #Month').tag('Date', 'cardinal-month'); //march 5 to 7 + + month.match('#Month #Value to #Value').tag('Date', 'value-to-value'); //march the 12th + + month.match('#Month the #Value').tag('Date', 'month-the-value'); + } //months: + + + var val = doc["if"]('#Value'); + + if (val.found === true) { + //june 7 + val.match('(#WeekDay|#Month) #Value').ifNo('#Money').tag('Date', 'date-value'); //7 june + + val.match('#Value (#WeekDay|#Month)').ifNo('#Money').tag('Date', 'value-date'); //may twenty five + + val.match('#TextValue #TextValue')["if"]('#Date').tag('#Date', 'textvalue-date'); //eg 'year' + + var duration = val["if"]('#Duration'); + + if (duration.found === true) { + //for 4 months + duration.match('for #Value #Duration').tag('Date', 'for-x-duration'); //two days before + + duration.match('#Value #Duration #Conjunction').tag('Date', 'val-duration-conjunction'); //for four days + + duration.match("".concat(preps, "? #Value #Duration")).tag('Date', 'value-duration'); //two years old + + duration.match('#Value #Duration old').unTag('Date', 'val-years-old'); + } + } //seasons + + + var season = doc["if"](seasons); + + if (season.found === true) { + season.match("".concat(preps, "? ").concat(thisNext, " ").concat(seasons)).tag('Date', 'thisNext-season'); + season.match("the? ".concat(sections, " of ").concat(seasons)).tag('Date', 'section-season'); + season.match("".concat(seasons, " ").concat(preps, "? #Cardinal")).tag('Date', 'season-year'); + } //rest-dates + + + var date = doc["if"]('#Date'); + + if (date.found === true) { + //june the 5th + date.match('#Date the? #Ordinal').tag('Date', 'correction'); //last month + + date.match("".concat(thisNext, " #Date")).tag('Date', 'thisNext'); //by 5 March + + date.match('due? (by|before|after|until) #Date').tag('Date', 'by'); //next feb + + date.match('(last|next|this|previous|current|upcoming|coming|the) #Date').tag('Date', 'next-feb'); //start of june + + date.match("the? ".concat(sections, " of #Date")).tag('Date', 'section-of'); //fifth week in 1998 + + date.match('#Ordinal #Duration in #Date').tag('Date', 'duration-in'); //early in june + + date.match('(early|late) (at|in)? the? #Date').tag('Time', 'early-evening'); //tomorrow before 3 + + date.match('#Date (by|before|after|at|@|about) #Cardinal').not('^#Date').tag('Time', 'date-before-Cardinal'); //saturday am + + date.match('#Date [(am|pm)]').unTag('Verb').unTag('Copula').tag('Time', 'date-am'); //feb to june + + date.match('#Date (#Preposition|to) #Date').ifNo('#Duration').tag('Date', 'date-prep-date'); + } //year/cardinal tagging + + + var cardinal = doc["if"]('#Cardinal'); + + if (cardinal.found === true) { + var v = cardinal.match("#Date #Value [#Cardinal]"); + tagYear(v, 'date-value-year'); //scoops up a bunch + + v = cardinal.match("#Date+ [#Cardinal]"); + tagYear(v, 'date-year'); //feb 8 2018 + + v = cardinal.match("#Month #Value [#Cardinal]"); + tagYear(v, 'month-value-year'); //feb 8 to 10th 2018 + + v = cardinal.match("#Month #Value to #Value [#Cardinal]"); + tagYear(v, 'month-range-year'); //in 1998 + + v = cardinal.match("(in|of|by|during|before|starting|ending|for|year) [#Cardinal]"); + tagYear(v, 'in-year'); //q2 2009 + + v = cardinal.match('(q1|q2|q3|q4) [#Cardinal]'); + tagYear(v, 'in-year'); //2nd quarter 2009 + + v = cardinal.match('#Ordinal quarter [#Cardinal]'); + tagYear(v, 'in-year'); //in the year 1998 + + v = cardinal.match('the year [#Cardinal]'); + tagYear(v, 'in-year'); //it was 1998 + + v = cardinal.match('it (is|was) [#Cardinal]'); + tagYearSafe(v, 'in-year'); + } + + var time = doc["if"]('#Time'); + + if (time.found === true) { + //by 6pm + time.match('(by|before|after|at|@|about) #Time').tag('Time', 'preposition-time'); //7 7pm + + time.match('#Cardinal #Time').not('#Year').tag('Time', 'value-time'); //2pm est + + time.match('#Time [(eastern|pacific|central|mountain)]').tag('Time', 'timezone'); //6pm est + + time.match('#Time [(est|pst|gmt)]').tag('Time', 'timezone abbr'); + } + + return doc; +}; + +var _00Basic = fixDates; + +var here = 'date-values'; // + +var values = function values(doc) { + if (doc.has('#Value')) { + //june 5 to 7th + doc.match('#Month #Value to #Value of? #Year?').tag('Date', here); //5 to 7th june + + doc.match('#Value to #Value of? #Month #Year?').tag('Date', here); //third week of may + + doc.match('#Value #Duration of #Date').tag('Date', here); //two days after + + doc.match('#Value+ #Duration (after|before|into|later|afterwards|ago)?').tag('Date', here); //two days + + doc.match('#Value #Date').tag('Date', here); //june 5th + + doc.match('#Date #Value').tag('Date', here); //tuesday at 5 + + doc.match('#Date #Preposition #Value').tag('Date', here); //tomorrow before 3 + + doc.match('#Date (after|before|during|on|in) #Value').tag('Date', here); //a year and a half + + doc.match('#Value (year|month|week|day) and a half').tag('Date', here); //5 and a half years + + doc.match('#Value and a half (years|months|weeks|days)').tag('Date', here); //on the fifth + + doc.match('on the #Ordinal').tag('Date', here); + } + + return doc; +}; + +var _01Values = values; + +var here$1 = 'date-tagger'; // + +var dateTagger = function dateTagger(doc) { + doc.match('(spring|summer|winter|fall|autumn|springtime|wintertime|summertime)').match('#Noun').tag('Season', here$1); + doc.match('(q1|q2|q3|q4)').tag('FinancialQuarter', here$1); + doc.match('(this|next|last|current) quarter').tag('FinancialQuarter', here$1); + doc.match('(this|next|last|current) season').tag('Season', here$1); + + if (doc.has('#Date')) { + //friday to sunday + doc.match('#Date #Preposition #Date').tag('Date', here$1); //once a day.. + + doc.match('(once|twice) (a|an|each) #Date').tag('Date', here$1); //TODO:fixme + + doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here$1); //tuesday + + doc.match('#Date+').tag('Date', here$1); //by June + + doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here$1); //a year after.. + + doc.match('a #Duration').tag('Date', here$1); //between x and y + + doc.match('(between|from) #Date').tag('Date', here$1); + doc.match('(to|until|upto) #Date').tag('Date', here$1); + doc.match('#Date and #Date').tag('Date', here$1); //during this june + + doc.match('(by|until|after|before|during|on|in|following) (next|this|last)? (#Date|#Date)').tag('Date', here$1); //day after next + + doc.match('the? #Date after next one?').tag('Date', here$1); //approximately... + + doc.match('(about|approx|approximately|around) #Date').tag('Date', here$1); + } + + return doc; +}; + +var _02Dates = dateTagger; + +var here$2 = 'section-tagger'; // + +var sectionTagger = function sectionTagger(doc) { + if (doc.has('#Date')) { + // //next september + doc.match('this? (last|next|past|this|previous|current|upcoming|coming|the) #Date').tag('Date', here$2); //starting this june + + doc.match('(starting|beginning|ending) #Date').tag('Date', here$2); //start of june + + doc.match('the? (start|end|middle|beginning) of (last|next|this|the) (#Date|#Date)').tag('Date', here$2); //this coming june + + doc.match('(the|this) #Date').tag('Date', here$2); + } + + return doc; +}; + +var _03Sections = sectionTagger; + +var here$3 = 'time-tagger'; // + +var timeTagger = function timeTagger(doc) { + if (doc.has('#Time')) { + //eastern daylight time + doc.match('#Noun (standard|daylight|central|mountain)? time').tag('Timezone', here$3); + } // https://raw.githubusercontent.com/davispuh/TimezoneParser/master/data/abbreviations.yml + + + if (doc.has('#Acronym')) { + var abbr = '(acdt|acst|ace|dmt|ist|tse|addt|adt|aedt|aest|ahdt|ahst|akdt|akst|amt|nst|apt|awt|gmt|awdt|awst|bdst|bst|bdt|nwt|bmt|wet|bost|cddt|cdt|cet|cmt|cpt|cst|cwt|chst|gst|eat|eddt|edt|eest|eet|emt|ept|ewt|est|ffmt|fmt|hdt|hst|hkst|hkt|hmt|iddt|idt|jmt|imt|jdt|jst|kdt|kst|kmt|lst|mddt|mdst|msd|msk|mdt|mmt|mpt|pdt|pst|mst|mwt|nddt|ndt|npt|nzdt|nzmt|nzst|pddt|pkst|pkt|plmt|pmmt|pmt|ppmt|ppt|pwt|qmt|rmt|sast|sdmt|set|sjmt|smt|sst|tbmt|tmt|utc|wast|wemt|wib|wit|wita|wmt|yddt|ydt|ypt|ywt|yst)'; + doc.match(abbr).tag('Timezone', here$3); + } // quarter to seven + + + if (doc.has('#Cardinal')) { + doc.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal').tag('Time'); + } + + return doc; +}; + +var _04Time = timeTagger; + +var here$4 = 'shift-tagger'; // + +var shiftTagger = function shiftTagger(doc) { + if (doc.has('#Date')) { + //two weeks before + doc.match('#Cardinal #Duration (before|after)').tag('#DateShift', here$4); //two weeks and three days before + + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here$4); + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here$4); + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here$4); + } + + return doc; +}; + +var _05Shifts = shiftTagger; + +var here$5 = 'fix-tagger'; // + +var fixUp = function fixUp(doc) { + //fixups + if (doc.has('#Date')) { + //first day by monday + var oops = doc.match('#Date+ by #Date+'); + + if (oops.found && !oops.has('^due')) { + oops.match('^#Date+').unTag('Date', 'by-monday'); + } + + var d = doc.match('#Date+'); //'spa day' + + d.match('^day$').unTag('Date', 'spa-day'); + var knownDate = '(yesterday|today|tomorrow)'; + + if (d.has(knownDate)) { + //yesterday 7 + d.match("".concat(knownDate, " [#Value]$")).unTag('Date', 'yesterday-7'); //7 yesterday + + d.match("^[#Value] ".concat(knownDate, "$")).unTag('Date', '7 yesterday'); //friday yesterday + + d.match("#WeekDay+ ".concat(knownDate, "$")).unTag('Date').lastTerm().tag('Date', 'fri-yesterday'); // yesterday yesterday + // d.match(`${knownDate}+ ${knownDate}$`) + // .unTag('Date') + // .lastTerm() + // .tag('Date', here) + + d.match("(this|last|next) #Date ".concat(knownDate, "$")).unTag('Date').lastTerm().tag('Date', 'this month yesterday'); + } //tomorrow on 5 + + + d.match("on #Cardinal$").unTag('Date', here$5); //this tomorrow + + d.match("this tomorrow").terms(0).unTag('Date', 'this-tomorrow'); //q2 2019 + + d.match("(q1|q2|q3|q4) #Year").tag('Date', here$5); //5 tuesday + // d.match(`^#Value #WeekDay`).terms(0).unTag('Date'); + //5 next week + + d.match("^#Value (this|next|last)").terms(0).unTag('Date', here$5); + + if (d.has('(last|this|next)')) { + //this month 7 + d.match("(last|this|next) #Duration #Value").terms(2).unTag('Date', here$5); //7 this month + + d.match("!#Month #Value (last|this|next) #Date").terms(0).unTag('Date', here$5); + } //january 5 5 + + + if (d.has('(#Year|#Time|#TextValue|#NumberRange)') === false) { + d.match('(#Month|#WeekDay) #Value #Value').terms(2).unTag('Date', here$5); + } //between june + + + if (d.has('^between') && !d.has('and .')) { + d.unTag('Date', here$5); + } //june june + + + if (d.has('#Month #Month') && !d.has('@hasHyphen') && !d.has('@hasComma')) { + d.match('#Month').lastTerm().unTag('Date', 'month-month'); + } + } + + return doc; +}; + +var _06Fixup = fixUp; + +var methods = [_00Basic, _01Values, _02Dates, _03Sections, _04Time, _05Shifts, _06Fixup]; // run each of the taggers + +var tagDate = function tagDate(doc) { + methods.forEach(function (fn) { + return fn(doc); + }); + return doc; +}; + +var tagger = tagDate; + +var tags = { + FinancialQuarter: { + isA: 'Date' + }, + // 'summer' + Season: { + isA: 'Date' + }, + // '1982' + Year: { + isA: ['Date'], + notA: 'RomanNumeral' + }, + // 'months' + Duration: { + isA: ['Date', 'Noun'] + }, + // '9:20pm' + Time: { + isA: ['Date'] + }, + // 'easter' + Holiday: { + isA: ['Date', 'Noun'] + }, + // 'PST' + Timezone: { + isA: ['Date', 'Noun'] + }, + // 'two weeks before' + DateShift: { + isA: ['Date'] + } +}; + +var dates = ['weekend', 'weekday', 'summer', 'winter', 'autumn', 'some day', 'one day', 'all day', 'some point', 'eod', 'eom', 'standard time', 'daylight time', 'today', 'tomorrow', 'tmr', 'tmrw', 'yesterday']; + +var durations = ['centuries', 'century', 'day', 'days', 'decade', 'decades', 'hour', 'hours', 'millisecond', 'milliseconds', 'minute', 'minutes', 'month', 'months', 'seconds', 'week', 'weeks', 'year', 'years']; + +var holidays = ['all hallows eve', 'all saints day', 'all sts day', 'april fools', 'armistice day', 'australia day', 'bastille day', 'boxing day', 'canada day', 'christmas eve', 'christmas', 'cinco de mayo', 'day of the dead', 'dia de muertos', 'dieciseis de septiembre', 'emancipation day', 'grito de dolores', 'groundhog day', 'halloween', 'harvey milk day', 'inauguration day', 'independence day', 'independents day', 'juneteenth', 'labour day', 'national freedom day', 'national nurses day', 'new years eve', 'new years', 'purple heart day', 'rememberance day', 'rosa parks day', 'saint andrews day', 'saint patricks day', 'saint stephens day', 'saint valentines day', 'st andrews day', 'st patricks day', 'st stephens day', 'st valentines day ', 'valentines day', 'valentines', 'veterans day', 'victoria day', 'womens equality day', 'xmas', // Fixed religious and cultural holidays +// Catholic + Christian +'epiphany', 'orthodox christmas day', 'orthodox new year', 'assumption of mary', 'all souls day', 'feast of the immaculate conception', 'feast of our lady of guadalupe', // Kwanzaa +'kwanzaa', // Pagan / metal 🤘 +'imbolc', 'beltaine', 'lughnassadh', 'samhain', 'martin luther king day', 'mlk day', 'presidents day', 'mardi gras', 'tax day', 'commonwealth day', 'mothers day', 'memorial day', 'fathers day', 'columbus day', 'indigenous peoples day', 'canadian thanksgiving', 'election day', 'thanksgiving', 't-day', 'turkey day', 'black friday', 'cyber monday', // Astronomical religious and cultural holidays +'ash wednesday', 'palm sunday', 'maundy thursday', 'good friday', 'holy saturday', 'easter', 'easter sunday', 'easter monday', 'orthodox good friday', 'orthodox holy saturday', 'orthodox easter', 'orthodox easter monday', 'ascension day', 'pentecost', 'whitsunday', 'whit sunday', 'whit monday', 'trinity sunday', 'corpus christi', 'advent', // Jewish +'tu bishvat', 'tu bshevat', 'purim', 'passover', 'yom hashoah', 'lag baomer', 'shavuot', 'tisha bav', 'rosh hashana', 'yom kippur', 'sukkot', 'shmini atzeret', 'simchat torah', 'chanukah', 'hanukkah', // Muslim +'isra and miraj', 'lailat al-qadr', 'eid al-fitr', 'id al-Fitr', 'eid ul-Fitr', 'ramadan', 'eid al-adha', 'muharram', 'the prophets birthday', 'ostara', 'march equinox', 'vernal equinox', 'litha', 'june solistice', 'summer solistice', 'mabon', 'september equinox', 'fall equinox', 'autumnal equinox', 'yule', 'december solstice', 'winter solstice', // Additional important holidays +'chinese new year', 'diwali']; + +var times = ['noon', 'midnight', 'now', 'morning', 'tonight', 'evening', 'afternoon', 'night', 'breakfast time', 'lunchtime', 'dinnertime', 'ago', 'sometime', 'eod', 'oclock', 'oclock', 'all day', 'at night']; + +var lex = {}; +var data = [[dates, ['#Date']], [durations, ['#Duration']], [holidays, ['#Holiday']], [times, ['#Time']]]; +data.forEach(function (a) { + for (var i = 0; i < a[0].length; i++) { + lex[a[0][i]] = a[1]; + } +}); +var words = lex; + +var normalize = function normalize(doc) { + doc = doc.clone(); + + if (!doc.numbers) { + console.warn("Compromise: compromise-dates cannot find plugin dependency 'compromise-number'"); + } else { + // convert 'two' to 2 + var num = doc.numbers(); + num.toNumber(); + num.toCardinal(); + } // remove adverbs + + + doc.adverbs().remove(); + return doc; +}; + +var _01Normalize = normalize; + +var knownUnits = { + second: true, + minute: true, + hour: true, + day: true, + week: true, + month: true, + season: true, + quarter: true, + year: true +}; //turn '5 weeks before' to {weeks:5} + +var parseShift = function parseShift(doc) { + var result = {}; + var m = doc.match('#DateShift+'); + + if (m.found === false) { + return result; + } + + m.match('#Cardinal #Duration').forEach(function (ts) { + var num = ts.match('#Cardinal').text('normal'); + num = parseFloat(num); + + if (num && typeof num === 'number') { + var unit = ts.match('#Duration').text('normal'); + unit = unit.replace(/s$/, ''); + + if (unit && knownUnits.hasOwnProperty(unit)) { + result[unit] = num; + } + } + }); //is it 2 weeks before? → -2 + + if (m.has('before$') === true) { + Object.keys(result).forEach(function (k) { + return result[k] *= -1; + }); + } // finally, remove it from our text + + + doc.remove('#DateShift'); + return result; +}; + +var _01Shift = parseShift; + +function createCommonjsModule(fn, module) { + return module = { + exports: {} + }, fn(module, module.exports), module.exports; +} + +function getCjsExportFromNamespace(n) { + return n && n['default'] || n; +} + +var fns = createCommonjsModule(function (module, exports) { + //git:blame @JuliasCaesar https://www.timeanddate.com/date/leapyear.html + exports.isLeapYear = function (year) { + return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; + }; // unsurprisingly-nasty `typeof date` call + + + exports.isDate = function (d) { + return Object.prototype.toString.call(d) === '[object Date]' && !isNaN(d.valueOf()); + }; + + exports.isArray = function (input) { + return Object.prototype.toString.call(input) === '[object Array]'; + }; + + exports.isObject = function (input) { + return Object.prototype.toString.call(input) === '[object Object]'; + }; + + exports.zeroPad = function (str) { + var len = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; + var pad = '0'; + str = str + ''; + return str.length >= len ? str : new Array(len - str.length + 1).join(pad) + str; + }; + + exports.titleCase = function (str) { + if (!str) { + return ''; + } + + return str[0].toUpperCase() + str.substr(1); + }; + + exports.ordinal = function (i) { + var j = i % 10; + var k = i % 100; + + if (j === 1 && k !== 11) { + return i + 'st'; + } + + if (j === 2 && k !== 12) { + return i + 'nd'; + } + + if (j === 3 && k !== 13) { + return i + 'rd'; + } + + return i + 'th'; + }; //strip 'st' off '1st'.. + + + exports.toCardinal = function (str) { + str = String(str); + str = str.replace(/([0-9])(st|nd|rd|th)$/i, '$1'); + return parseInt(str, 10); + }; //used mostly for cleanup of unit names, like 'months' + + + exports.normalize = function () { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + str = str.toLowerCase().trim(); + str = str.replace(/ies$/, 'y'); //'centuries' + + str = str.replace(/s$/, ''); + str = str.replace(/-/g, ''); + + if (str === 'day') { + return 'date'; + } + + return str; + }; + + exports.getEpoch = function (tmp) { + //support epoch + if (typeof tmp === 'number') { + return tmp; + } //suport date objects + + + if (exports.isDate(tmp)) { + return tmp.getTime(); + } + + if (tmp.epoch) { + return tmp.epoch; + } + + return null; + }; //make sure this input is a spacetime obj + + + exports.beADate = function (d, s) { + if (exports.isObject(d) === false) { + return s.clone().set(d); + } + + return d; + }; + + exports.formatTimezone = function (offset) { + var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var absOffset = Math.abs(offset); + var sign = offset > 0 ? '+' : '-'; + return "".concat(sign).concat(exports.zeroPad(absOffset)).concat(delimiter, "00"); + }; +}); +var fns_1 = fns.isLeapYear; +var fns_2 = fns.isDate; +var fns_3 = fns.isArray; +var fns_4 = fns.isObject; +var fns_5 = fns.zeroPad; +var fns_6 = fns.titleCase; +var fns_7 = fns.ordinal; +var fns_8 = fns.toCardinal; +var fns_9 = fns.normalize; +var fns_10 = fns.getEpoch; +var fns_11 = fns.beADate; +var fns_12 = fns.formatTimezone; +var zeroPad = fns.zeroPad; + +var toString = function toString(d) { + return zeroPad(d.getMonth() + 1) + '/' + zeroPad(d.getDate()) + ':' + zeroPad(d.getHours()); +}; // a timezone will begin with a specific offset in january +// then some will switch to something else between november-march + + +var shouldChange = function shouldChange(epoch, start, end, defaultOffset) { + //note: this has a cray order-of-operations issue + //we can't get the date, without knowing the timezone, and vice-versa + //it's possible that we can miss a dst-change by a few hours. + var d = new Date(epoch); //(try to mediate this a little?) + + var bias = d.getTimezoneOffset() || 0; + var shift = bias + defaultOffset * 60; //in minutes + + shift = shift * 60 * 1000; //in ms + + d = new Date(epoch + shift); + var current = toString(d); //eg. is it after ~november? + + if (current >= start) { + //eg. is it before ~march~ too? + if (current < end) { + return true; + } + } + + return false; +}; + +var summerTime = shouldChange; // this method avoids having to do a full dst-calculation on every operation +// it reproduces some things in ./index.js, but speeds up spacetime considerably + +var quickOffset = function quickOffset(s) { + var zones = s.timezones; + var obj = zones[s.tz]; + + if (obj === undefined) { + console.warn("Warning: couldn't find timezone " + s.tz); + return 0; + } + + if (obj.dst === undefined) { + return obj.offset; + } //get our two possible offsets + + + var jul = obj.offset; + var dec = obj.offset + 1; // assume it's the same for now + + if (obj.hem === 'n') { + dec = jul - 1; + } + + var split = obj.dst.split('->'); + var inSummer = summerTime(s.epoch, split[0], split[1], jul); + + if (inSummer === true) { + return jul; + } + + return dec; +}; + +var quick = quickOffset; +var _build = { + "9|s": "2/dili,2/jayapura", + "9|n": "2/chita,2/khandyga,2/pyongyang,2/seoul,2/tokyo,11/palau", + "9.5|s|04/07:03->10/06:02": "4/adelaide,4/broken_hill,4/south,4/yancowinna", + "9.5|s": "4/darwin,4/north", + "8|s": "12/casey,2/kuala_lumpur,2/makassar,2/singapore,4/perth,4/west", + "8|n|03/25:03->09/29:23": "2/ulan_bator", + "8|n": "2/brunei,2/choibalsan,2/chongqing,2/chungking,2/harbin,2/hong_kong,2/irkutsk,2/kuching,2/macao,2/macau,2/manila,2/shanghai,2/taipei,2/ujung_pandang,2/ulaanbaatar", + "8.75|s": "4/eucla", + "7|s": "12/davis,2/jakarta,9/christmas", + "7|n": "2/bangkok,2/barnaul,2/ho_chi_minh,2/hovd,2/krasnoyarsk,2/novokuznetsk,2/novosibirsk,2/phnom_penh,2/pontianak,2/saigon,2/tomsk,2/vientiane", + "6|s": "12/vostok", + "6|n": "2/almaty,2/bishkek,2/dacca,2/dhaka,2/kashgar,2/omsk,2/qyzylorda,2/thimbu,2/thimphu,2/urumqi,9/chagos", + "6.5|n": "2/rangoon,9/cocos", + "5|s": "12/mawson,9/kerguelen", + "5|n": "2/aqtau,2/aqtobe,2/ashgabat,2/ashkhabad,2/atyrau,2/baku,2/dushanbe,2/karachi,2/oral,2/samarkand,2/tashkent,2/yekaterinburg,9/maldives", + "5.75|n": "2/kathmandu,2/katmandu", + "5.5|n": "2/calcutta,2/colombo,2/kolkata", + "4|s": "9/reunion", + "4|n": "2/dubai,2/muscat,2/tbilisi,2/yerevan,8/astrakhan,8/samara,8/saratov,8/ulyanovsk,8/volgograd,2/volgograd,9/mahe,9/mauritius", + "4.5|n|03/22:00->09/21:24": "2/tehran", + "4.5|n": "2/kabul", + "3|s": "12/syowa,9/antananarivo", + "3|n|03/31:03->10/27:04": "2/nicosia,8/athens,8/bucharest,8/helsinki,8/kiev,8/mariehamn,8/nicosia,8/riga,8/sofia,8/tallinn,8/uzhgorod,8/vilnius,8/zaporozhye", + "3|n|03/31:02->10/27:03": "8/chisinau,8/tiraspol", + "3|n|03/31:00->10/26:24": "2/beirut", + "3|n|03/29:02->10/27:02": "2/jerusalem,2/tel_aviv", + "3|n|03/29:00->10/26:01": "2/gaza,2/hebron", + "3|n|03/29:00->10/25:01": "2/amman", + "3|n|03/29:00->10/24:24": "2/damascus", + "3|n": "0/addis_ababa,0/asmara,0/asmera,0/dar_es_salaam,0/djibouti,0/juba,0/kampala,0/mogadishu,0/nairobi,2/aden,2/baghdad,2/bahrain,2/istanbul,2/kuwait,2/qatar,2/riyadh,8/istanbul,8/kirov,8/minsk,8/moscow,8/simferopol,9/comoro,9/mayotte", + "2|s|03/31:02->10/27:02": "12/troll", + "2|s": "0/gaborone,0/harare,0/johannesburg,0/lubumbashi,0/lusaka,0/maputo,0/maseru,0/mbabane", + "2|n|03/31:02->10/27:03": "0/ceuta,arctic/longyearbyen,3/jan_mayen,8/amsterdam,8/andorra,8/belgrade,8/berlin,8/bratislava,8/brussels,8/budapest,8/busingen,8/copenhagen,8/gibraltar,8/ljubljana,8/luxembourg,8/madrid,8/malta,8/monaco,8/oslo,8/paris,8/podgorica,8/prague,8/rome,8/san_marino,8/sarajevo,8/skopje,8/stockholm,8/tirane,8/vaduz,8/vatican,8/vienna,8/warsaw,8/zagreb,8/zurich", + "2|n": "0/blantyre,0/bujumbura,0/cairo,0/khartoum,0/kigali,0/tripoli,8/kaliningrad", + "1|s|04/02:01->09/03:03": "0/windhoek", + "1|s": "0/kinshasa,0/luanda", + "1|n|05/05:03->06/09:02": "0/casablanca,0/el_aaiun", + "1|n|03/31:01->10/27:02": "3/canary,3/faeroe,3/faroe,3/madeira,8/belfast,8/dublin,8/guernsey,8/isle_of_man,8/jersey,8/lisbon,8/london", + "1|n": "0/algiers,0/bangui,0/brazzaville,0/douala,0/lagos,0/libreville,0/malabo,0/ndjamena,0/niamey,0/porto-novo,0/tunis", + "14|n": "11/kiritimati", + "13|s|04/07:04->09/29:03": "11/apia", + "13|s|01/15:02->11/05:03": "11/tongatapu", + "13|n": "11/enderbury,11/fakaofo", + "12|s|04/07:03->09/29:02": "12/mcmurdo,12/south_pole,11/auckland", + "12|s|01/13:03->11/10:02": "11/fiji", + "12|n": "2/anadyr,2/kamchatka,2/srednekolymsk,11/funafuti,11/kwajalein,11/majuro,11/nauru,11/tarawa,11/wake,11/wallis", + "12.75|s|04/07:03->09/29:02": "11/chatham", + "11|s": "12/macquarie,11/bougainville", + "11|n": "2/magadan,2/sakhalin,11/efate,11/guadalcanal,11/kosrae,11/noumea,11/pohnpei,11/ponape", + "11.5|n": "11/norfolk", + "10|s|04/07:03->10/06:02": "4/act,4/canberra,4/currie,4/hobart,4/melbourne,4/nsw,4/sydney,4/tasmania,4/victoria", + "10|s": "12/dumontdurville,4/brisbane,4/lindeman,4/queensland", + "10|n": "2/ust-nera,2/vladivostok,2/yakutsk,11/chuuk,11/guam,11/port_moresby,11/saipan,11/truk,11/yap", + "10.5|s|04/07:01->10/06:02": "4/lhi,4/lord_howe", + "0|n|03/31:00->10/27:01": "1/scoresbysund,3/azores", + "0|n": "0/abidjan,0/accra,0/bamako,0/banjul,0/bissau,0/conakry,0/dakar,0/freetown,0/lome,0/monrovia,0/nouakchott,0/ouagadougou,0/sao_tome,0/timbuktu,1/danmarkshavn,3/reykjavik,3/st_helena,13/gmt,13/gmt+0,13/gmt-0,13/gmt0,13/greenwich,13/utc,13/universal,13/zulu", + "-9|n|03/10:02->11/03:02": "1/adak,1/atka", + "-9|n": "11/gambier", + "-9.5|n": "11/marquesas", + "-8|n|03/10:02->11/03:02": "1/anchorage,1/juneau,1/metlakatla,1/nome,1/sitka,1/yakutat", + "-8|n": "11/pitcairn", + "-7|n|03/10:02->11/03:02": "1/dawson,1/ensenada,1/los_angeles,1/santa_isabel,1/tijuana,1/vancouver,1/whitehorse,6/pacific,6/yukon,10/bajanorte", + "-7|n": "1/creston,1/dawson_creek,1/hermosillo,1/phoenix", + "-6|s|04/06:22->09/07:22": "7/easterisland,11/easter", + "-6|n|04/07:02->10/27:02": "1/chihuahua,1/mazatlan,10/bajasur", + "-6|n|03/10:02->11/03:02": "1/boise,1/cambridge_bay,1/denver,1/edmonton,1/inuvik,1/ojinaga,1/shiprock,1/yellowknife,6/mountain", + "-6|n": "1/belize,1/costa_rica,1/el_salvador,1/guatemala,1/managua,1/regina,1/swift_current,1/tegucigalpa,6/east-saskatchewan,6/saskatchewan,11/galapagos", + "-5|s": "1/lima,1/rio_branco,5/acre", + "-5|n|04/07:02->10/27:02": "1/bahia_banderas,1/merida,1/mexico_city,1/monterrey,10/general", + "-5|n|03/12:03->11/05:01": "1/north_dakota", + "-5|n|03/10:02->11/03:02": "1/chicago,1/knox_in,1/matamoros,1/menominee,1/rainy_river,1/rankin_inlet,1/resolute,1/winnipeg,6/central", + "-5|n": "1/atikokan,1/bogota,1/cancun,1/cayman,1/coral_harbour,1/eirunepe,1/guayaquil,1/jamaica,1/panama,1/porto_acre", + "-4|s|05/13:23->08/13:01": "12/palmer", + "-4|s|04/06:24->09/08:00": "1/santiago,7/continental", + "-4|s|03/23:24->10/06:00": "1/asuncion", + "-4|s|02/16:24->11/03:00": "1/campo_grande,1/cuiaba", + "-4|s": "1/la_paz,1/manaus,5/west", + "-4|n|03/12:03->11/05:01": "1/indiana,1/kentucky", + "-4|n|03/10:02->11/03:02": "1/detroit,1/fort_wayne,1/grand_turk,1/indianapolis,1/iqaluit,1/louisville,1/montreal,1/nassau,1/new_york,1/nipigon,1/pangnirtung,1/port-au-prince,1/thunder_bay,1/toronto,6/eastern", + "-4|n|03/10:00->11/03:01": "1/havana", + "-4|n": "1/anguilla,1/antigua,1/aruba,1/barbados,1/blanc-sablon,1/boa_vista,1/caracas,1/curacao,1/dominica,1/grenada,1/guadeloupe,1/guyana,1/kralendijk,1/lower_princes,1/marigot,1/martinique,1/montserrat,1/port_of_spain,1/porto_velho,1/puerto_rico,1/santo_domingo,1/st_barthelemy,1/st_kitts,1/st_lucia,1/st_thomas,1/st_vincent,1/tortola,1/virgin", + "-3|s": "1/argentina,1/buenos_aires,1/cordoba,1/fortaleza,1/montevideo,1/punta_arenas,1/sao_paulo,12/rothera,3/stanley,5/east", + "-3|n|03/10:02->11/03:02": "1/glace_bay,1/goose_bay,1/halifax,1/moncton,1/thule,3/bermuda,6/atlantic", + "-3|n": "1/araguaina,1/bahia,1/belem,1/catamarca,1/cayenne,1/jujuy,1/maceio,1/mendoza,1/paramaribo,1/recife,1/rosario,1/santarem", + "-2|s": "5/denoronha", + "-2|n|03/30:22->10/26:23": "1/godthab", + "-2|n|03/10:02->11/03:02": "1/miquelon", + "-2|n": "1/noronha,3/south_georgia", + "-2.5|n|03/10:02->11/03:02": "1/st_johns,6/newfoundland", + "-1|n": "3/cape_verde", + "-11|n": "11/midway,11/niue,11/pago_pago,11/samoa", + "-10|n": "11/honolulu,11/johnston,11/rarotonga,11/tahiti" +}; + +var _build$1 = +/*#__PURE__*/ +Object.freeze({ + 'default': _build +}); //prefixes for iana names.. + + +var _prefixes = ['africa', 'america', 'asia', 'atlantic', 'australia', 'brazil', 'canada', 'chile', 'europe', 'indian', 'mexico', 'pacific', 'antarctica', 'etc']; +var data$1 = getCjsExportFromNamespace(_build$1); +var all = {}; +Object.keys(data$1).forEach(function (k) { + var split = k.split('|'); + var obj = { + offset: Number(split[0]), + hem: split[1] + }; + + if (split[2]) { + obj.dst = split[2]; + } + + var names = data$1[k].split(','); + names.forEach(function (str) { + str = str.replace(/(^[0-9]+)\//, function (before, num) { + num = Number(num); + return _prefixes[num] + '/'; + }); + all[str] = obj; + }); +}); +all['utc'] = { + offset: 0, + hem: 'n' //(sorry) + +}; //add etc/gmt+n + +for (var i = -14; i <= 14; i += 0.5) { + var num = i; + + if (num > 0) { + num = '+' + num; + } + + var name = 'etc/gmt' + num; + all[name] = { + offset: i * -1, + //they're negative! + hem: 'n' //(sorry) + + }; + name = 'utc/gmt' + num; //this one too, why not. + + all[name] = { + offset: i * -1, + hem: 'n' + }; +} // console.log(all) +// console.log(Object.keys(all).length) + + +var unpack = all; //find the implicit iana code for this machine. +//safely query the Intl object +//based on - https://bitbucket.org/pellepim/jstimezonedetect/src + +var fallbackTZ = 'utc'; // +//this Intl object is not supported often, yet + +var safeIntl = function safeIntl() { + if (typeof Intl === 'undefined' || typeof Intl.DateTimeFormat === 'undefined') { + return null; + } + + var format = Intl.DateTimeFormat(); + + if (typeof format === 'undefined' || typeof format.resolvedOptions === 'undefined') { + return null; + } + + var timezone = format.resolvedOptions().timeZone; + + if (!timezone) { + return null; + } + + return timezone.toLowerCase(); +}; + +var guessTz = function guessTz() { + var timezone = safeIntl(); + + if (timezone === null) { + return fallbackTZ; + } + + return timezone; +}; //do it once per computer + + +var guessTz_1 = guessTz; +var isOffset = /(\-?[0-9]+)h(rs)?/i; +var isNumber = /(\-?[0-9]+)/; +var utcOffset = /utc([\-+]?[0-9]+)/i; +var gmtOffset = /gmt([\-+]?[0-9]+)/i; + +var toIana = function toIana(num) { + num = Number(num); + + if (num > -13 && num < 13) { + num = num * -1; //it's opposite! + + num = (num > 0 ? '+' : '') + num; //add plus sign + + return 'etc/gmt' + num; + } + + return null; +}; + +var parseOffset = function parseOffset(tz) { + // '+5hrs' + var m = tz.match(isOffset); + + if (m !== null) { + return toIana(m[1]); + } // 'utc+5' + + + m = tz.match(utcOffset); + + if (m !== null) { + return toIana(m[1]); + } // 'GMT-5' (not opposite) + + + m = tz.match(gmtOffset); + + if (m !== null) { + var _num = Number(m[1]) * -1; + + return toIana(_num); + } // '+5' + + + m = tz.match(isNumber); + + if (m !== null) { + return toIana(m[1]); + } + + return null; +}; + +var parseOffset_1 = parseOffset; +var local = guessTz_1(); //add all the city names by themselves + +var cities = Object.keys(unpack).reduce(function (h, k) { + var city = k.split('/')[1] || ''; + city = city.replace(/_/g, ' '); + h[city] = k; + return h; +}, {}); //try to match these against iana form + +var normalize$1 = function normalize(tz) { + tz = tz.replace(/ time/g, ''); + tz = tz.replace(/ (standard|daylight|summer)/g, ''); + tz = tz.replace(/\b(east|west|north|south)ern/g, '$1'); + tz = tz.replace(/\b(africa|america|australia)n/g, '$1'); + tz = tz.replace(/\beuropean/g, 'europe'); + tz = tz.replace(/\islands/g, 'island'); + return tz; +}; // try our best to reconcile the timzone to this given string + + +var lookupTz = function lookupTz(str, zones) { + if (!str) { + return local; + } + + var tz = str.trim(); + var split = str.split('/'); //support long timezones like 'America/Argentina/Rio_Gallegos' + + if (split.length > 2 && zones.hasOwnProperty(tz) === false) { + tz = split[0] + '/' + split[1]; + } + + tz = tz.toLowerCase(); + + if (zones.hasOwnProperty(tz) === true) { + return tz; + } //lookup more loosely.. + + + tz = normalize$1(tz); + + if (zones.hasOwnProperty(tz) === true) { + return tz; + } //try city-names + + + if (cities.hasOwnProperty(tz) === true) { + return cities[tz]; + } // //try to parse '-5h' + + + if (/[0-9]/.test(tz) === true) { + var id = parseOffset_1(tz); + + if (id) { + return id; + } + } + + throw new Error("Spacetime: Cannot find timezone named: '" + str + "'. Please enter an IANA timezone id."); +}; + +var find = lookupTz; +var o = { + millisecond: 1 +}; +o.second = 1000; +o.minute = 60000; +o.hour = 3.6e6; // dst is supported post-hoc + +o.day = 8.64e7; // + +o.date = o.day; +o.month = 8.64e7 * 29.5; //(average) + +o.week = 6.048e8; +o.year = 3.154e10; // leap-years are supported post-hoc +//add plurals + +Object.keys(o).forEach(function (k) { + o[k + 's'] = o[k]; +}); +var milliseconds = o; //basically, step-forward/backward until js Date object says we're there. + +var walk = function walk(s, n, fn, unit, previous) { + var current = s.d[fn](); + + if (current === n) { + return; //already there + } + + var startUnit = previous === null ? null : s.d[previous](); + var original = s.epoch; //try to get it as close as we can + + var diff = n - current; + s.epoch += milliseconds[unit] * diff; //DST edge-case: if we are going many days, be a little conservative + + if (unit === 'day' && Math.abs(diff) > 28) { + //but don't push it over a month + if (n < 28) { + s.epoch += milliseconds.hour; + } + } //repair it if we've gone too far or something + //(go by half-steps, just in case) + + + var halfStep = milliseconds[unit] / 2; + + while (s.d[fn]() < n) { + s.epoch += halfStep; + } + + while (s.d[fn]() > n) { + s.epoch -= halfStep; + } //oops, did we change previous unit? revert it. + + + if (previous !== null && startUnit !== s.d[previous]()) { + // console.warn('spacetime warning: missed setting ' + unit) + s.epoch = original; // i mean, but make it close... + + s.epoch += milliseconds[unit] * diff * 0.89; // i guess? + } +}; //find the desired date by a increment/check while loop + + +var units = { + year: { + valid: function valid(n) { + return n > -4000 && n < 4000; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getFullYear', 'year', null); + } + }, + month: { + valid: function valid(n) { + return n >= 0 && n <= 11; + }, + walkTo: function walkTo(s, n) { + var d = s.d; + var current = d.getMonth(); + var original = s.epoch; + var startUnit = d.getFullYear(); + + if (current === n) { + return; + } //try to get it as close as we can.. + + + var diff = n - current; + s.epoch += milliseconds.day * (diff * 28); //special case + //oops, did we change the year? revert it. + + if (startUnit !== s.d.getFullYear()) { + s.epoch = original; + } //incriment by day + + + while (s.d.getMonth() < n) { + s.epoch += milliseconds.day; + } + + while (s.d.getMonth() > n) { + s.epoch -= milliseconds.day; + } + } + }, + date: { + valid: function valid(n) { + return n > 0 && n <= 31; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getDate', 'day', 'getMonth'); + } + }, + hour: { + valid: function valid(n) { + return n >= 0 && n < 24; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getHours', 'hour', 'getDate'); + } + }, + minute: { + valid: function valid(n) { + return n >= 0 && n < 60; + }, + walkTo: function walkTo(s, n) { + return walk(s, n, 'getMinutes', 'minute', 'getHours'); + } + }, + second: { + valid: function valid(n) { + return n >= 0 && n < 60; + }, + walkTo: function walkTo(s, n) { + //do this one directly + s.epoch = s.seconds(n).epoch; + } + }, + millisecond: { + valid: function valid(n) { + return n >= 0 && n < 1000; + }, + walkTo: function walkTo(s, n) { + //do this one directly + s.epoch = s.milliseconds(n).epoch; + } + } +}; + +var walkTo = function walkTo(s, wants) { + var keys = Object.keys(units); + var old = s.clone(); + + for (var _i = 0; _i < keys.length; _i++) { + var k = keys[_i]; + var n = wants[k]; + + if (n === undefined) { + n = old[k](); + } + + if (typeof n === 'string') { + n = parseInt(n, 10); + } //make-sure it's valid + + + if (!units[k].valid(n)) { + s.epoch = null; + + if (s.silent === false) { + console.warn('invalid ' + k + ': ' + n); + } + + return; + } // console.log(k, n) + + + units[k].walkTo(s, n); + } + + return; +}; + +var walk_1 = walkTo; +var shortMonths = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sept', 'oct', 'nov', 'dec']; +var longMonths = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; + +function buildMapping() { + var obj = { + sep: 8 //support this format + + }; + + for (var _i2 = 0; _i2 < shortMonths.length; _i2++) { + obj[shortMonths[_i2]] = _i2; + } + + for (var _i3 = 0; _i3 < longMonths.length; _i3++) { + obj[longMonths[_i3]] = _i3; + } + + return obj; +} + +var months = { + "short": function short() { + return shortMonths; + }, + "long": function long() { + return longMonths; + }, + mapping: function mapping() { + return buildMapping(); + }, + set: function set(i18n) { + shortMonths = i18n["short"] || shortMonths; + longMonths = i18n["long"] || longMonths; + } +}; //pull-apart ISO offsets, like "+0100" + +var parseOffset$1 = function parseOffset$1(s, offset) { + if (!offset) { + return s; + } //this is a fancy-move + + + if (offset === 'Z') { + offset = '+0000'; + } // according to ISO8601, tz could be hh:mm, hhmm or hh + // so need few more steps before the calculation. + + + var num = 0; // for (+-)hh:mm + + if (/^[\+-]?[0-9]{2}:[0-9]{2}$/.test(offset)) { + //support "+01:00" + if (/:00/.test(offset) === true) { + offset = offset.replace(/:00/, ''); + } //support "+01:30" + + + if (/:30/.test(offset) === true) { + offset = offset.replace(/:30/, '.5'); + } + } // for (+-)hhmm + + + if (/^[\+-]?[0-9]{4}$/.test(offset)) { + offset = offset.replace(/30$/, '.5'); + } + + num = parseFloat(offset); //divide by 100 or 10 - , "+0100", "+01" + + if (Math.abs(num) > 100) { + num = num / 100; + } //okay, try to match it to a utc timezone + //remember - this is opposite! a -5 offset maps to Etc/GMT+5 ¯\_(:/)_/¯ + //https://askubuntu.com/questions/519550/why-is-the-8-timezone-called-gmt-8-in-the-filesystem + + + num *= -1; + + if (num >= 0) { + num = '+' + num; + } + + var tz = 'etc/gmt' + num; + var zones = s.timezones; + + if (zones[tz]) { + // log a warning if we're over-writing a given timezone? + // console.log('changing timezone to: ' + tz) + s.tz = tz; + } + + return s; +}; + +var parseOffset_1$1 = parseOffset$1; + +var parseTime = function parseTime(s) { + var str = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + str = str.replace(/^\s+/, '').toLowerCase(); //trim + //formal time formats - 04:30.23 + + var arr = str.match(/([0-9]{1,2}):([0-9]{1,2}):?([0-9]{1,2})?[:\.]?([0-9]{1,4})?/); + + if (arr !== null) { + //validate it a little + var h = Number(arr[1]); + + if (h < 0 || h > 24) { + return s.startOf('day'); + } + + var m = Number(arr[2]); //don't accept '5:3pm' + + if (arr[2].length < 2 || m < 0 || m > 59) { + return s.startOf('day'); + } + + s = s.hour(h); + s = s.minute(m); + s = s.seconds(arr[3] || 0); + s = s.millisecond(arr[4] || 0); //parse-out am/pm + + var ampm = str.match(/[\b0-9](am|pm)\b/); + + if (ampm !== null && ampm[1]) { + s = s.ampm(ampm[1]); + } + + return s; + } //try an informal form - 5pm (no minutes) + + + arr = str.match(/([0-9]+) ?(am|pm)/); + + if (arr !== null && arr[1]) { + var _h = Number(arr[1]); //validate it a little.. + + + if (_h > 12 || _h < 1) { + return s.startOf('day'); + } + + s = s.hour(arr[1] || 0); + s = s.ampm(arr[2]); + s = s.startOf('hour'); + return s; + } //no time info found, use start-of-day + + + s = s.startOf('day'); + return s; +}; + +var parseTime_1 = parseTime; +var monthLengths = [31, // January - 31 days +28, // February - 28 days in a common year and 29 days in leap years +31, // March - 31 days +30, // April - 30 days +31, // May - 31 days +30, // June - 30 days +31, // July - 31 days +31, // August - 31 days +30, // September - 30 days +31, // October - 31 days +30, // November - 30 days +31 // December - 31 days +]; +var monthLengths_1 = monthLengths; +var isLeapYear = fns.isLeapYear; //given a month, return whether day number exists in it + +var hasDate = function hasDate(obj) { + //invalid values + if (monthLengths_1.hasOwnProperty(obj.month) !== true) { + return false; + } //support leap-year in february + + + if (obj.month === 1) { + if (isLeapYear(obj.year) && obj.date <= 29) { + return true; + } else { + return obj.date <= 28; + } + } //is this date too-big for this month? + + + var max = monthLengths_1[obj.month] || 0; + + if (obj.date <= max) { + return true; + } + + return false; +}; + +var hasDate_1 = hasDate; +var months$1 = months.mapping(); + +var parseYear = function parseYear() { + var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + //support '18 -> 2018 + // str = str.replace(/^'([0-9]{2})/, '20$1') + // str = str.replace('([0-9]+) ?b\.?c\.?$', '-$1') + var year = parseInt(str.trim(), 10); + year = year || new Date().getFullYear(); + return year; +}; + +var strFmt = [//iso-this 1998-05-30T22:00:00:000Z, iso-that 2017-04-03T08:00:00-0700 +{ + reg: /^(\-?0?0?[0-9]{3,4})-([0-9]{1,2})-([0-9]{1,2})[T| ]([0-9.:]+)(Z|[0-9\-\+:]+)?$/, + parse: function parse(s, arr, givenTz, options) { + var month = parseInt(arr[2], 10) - 1; + var obj = { + year: arr[1], + month: month, + date: arr[3] + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + parseOffset_1$1(s, arr[5]); + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } +}, //iso "2015-03-25" or "2015/03/25" or "2015/03/25 12:26:14 PM" +{ + reg: /^([0-9]{4})[\-\/]([0-9]{1,2})[\-\/]([0-9]{1,2}),?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i, + parse: function parse(s, arr) { + var obj = { + year: arr[1], + month: parseInt(arr[2], 10) - 1, + date: parseInt(arr[3], 10) + }; + + if (obj.month >= 12) { + //support yyyy/dd/mm (weird, but ok) + obj.date = parseInt(arr[2], 10); + obj.month = parseInt(arr[3], 10) - 1; + } + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } +}, //mm/dd/yyyy - uk/canada "6/28/2019, 12:26:14 PM" +{ + reg: /^([0-9]{1,2})[\-\/]([0-9]{1,2})[\-\/]?([0-9]{4})?,?( [0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i, + parse: function parse(s, arr) { + var month = parseInt(arr[1], 10) - 1; + var date = parseInt(arr[2], 10); //support dd/mm/yyy + + if (s.british || month >= 12) { + date = parseInt(arr[1], 10); + month = parseInt(arr[2], 10) - 1; + } + + var year = arr[3] || new Date().getFullYear(); + var obj = { + year: year, + month: month, + date: date + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } +}, //common british format - "25-feb-2015" +{ + reg: /^([0-9]{1,2})[\-\/]([a-z]+)[\-\/]?([0-9]{4})?$/i, + parse: function parse(s, arr) { + var month = months$1[arr[2].toLowerCase()]; + var year = parseYear(arr[3]); + var obj = { + year: year, + month: month, + date: fns.toCardinal(arr[1] || '') + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } +}, //Long "Mar 25 2015" +//February 22, 2017 15:30:00 +{ + reg: /^([a-z]+) ([0-9]{1,2}(?:st|nd|rd|th)?),?( [0-9]{4})?( ([0-9:]+( ?am| ?pm| ?gmt)?))?$/i, + parse: function parse(s, arr) { + var month = months$1[arr[1].toLowerCase()]; + var year = parseYear(arr[3]); + var obj = { + year: year, + month: month, + date: fns.toCardinal(arr[2] || '') + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } +}, //February 2017 (implied date) +{ + reg: /^([a-z]+) ([0-9]{4})$/i, + parse: function parse(s, arr) { + var month = months$1[arr[1].toLowerCase()]; + var year = parseYear(arr[2]); + var obj = { + year: year, + month: month, + date: 1 + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } +}, //Long "25 Mar 2015" +{ + reg: /^([0-9]{1,2}(?:st|nd|rd|th)?) ([a-z]+),?( [0-9]{4})?,? ?([0-9]{1,2}:[0-9]{2}:?[0-9]{0,2}? ?(am|pm|gmt))?$/i, + parse: function parse(s, arr) { + var month = months$1[arr[2].toLowerCase()]; + + if (!month) { + return null; + } + + var year = parseYear(arr[3]); + var obj = { + year: year, + month: month, + date: fns.toCardinal(arr[1]) + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s, arr[4]); + return s; + } +}, { + // '200bc' + reg: /^[0-9,]+ ?b\.?c\.?$/i, + parse: function parse(s, arr) { + var str = arr[0] || ''; //make negative-year + + str = str.replace(/^([0-9,]+) ?b\.?c\.?$/i, '-$1'); //remove commas + + str = str.replace(/,/g, ''); + var year = parseInt(str.trim(), 10); + var d = new Date(); + var obj = { + year: year, + month: d.getMonth(), + date: d.getDate() + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s); + return s; + } +}, { + // '200ad' + reg: /^[0-9,]+ ?(a\.?d\.?|c\.?e\.?)$/i, + parse: function parse(s, arr) { + var str = arr[0] || ''; //remove commas + + str = str.replace(/,/g, ''); + var year = parseInt(str.trim(), 10); + var d = new Date(); + var obj = { + year: year, + month: d.getMonth(), + date: d.getDate() + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s); + return s; + } +}, { + // '1992' + reg: /^[0-9]{4}( ?a\.?d\.?)?$/i, + parse: function parse(s, arr) { + var year = parseYear(arr[0]); + var d = new Date(); + var obj = { + year: year, + month: d.getMonth(), + date: d.getDate() + }; + + if (hasDate_1(obj) === false) { + s.epoch = null; + return s; + } + + walk_1(s, obj); + s = parseTime_1(s); + return s; + } +}]; +var strParse = strFmt; +var dates$1 = { + now: function now(s) { + s.epoch = Date.now(); + return s; + }, + tonight: function tonight(s) { + s.epoch = Date.now(); + s = s.hour(18); + return s; + }, + today: function today(s) { + s.epoch = Date.now(); + return s; + }, + tomorrow: function tomorrow(s) { + s.epoch = Date.now(); + s = s.add(1, 'day'); + s = s.startOf('day'); + return s; + }, + yesterday: function yesterday(s) { + s.epoch = Date.now(); + s = s.subtract(1, 'day'); + s = s.startOf('day'); + return s; + }, + christmas: function christmas(s) { + var year = new Date().getFullYear(); + s = s.set([year, 11, 25, 18, 0, 0]); // Dec 25 + + return s; + }, + 'new years': function newYears(s) { + var year = new Date().getFullYear(); + s = s.set([year, 11, 31, 18, 0, 0]); // Dec 31 + + return s; + } +}; +dates$1['new years eve'] = dates$1['new years']; +var namedDates = dates$1; //we have to actually parse these inputs ourselves +// - can't use built-in js parser ;( +//========================================= +// ISO Date "2015-03-25" +// Short Date "03/25/2015" or "2015/03/25" +// Long Date "Mar 25 2015" or "25 Mar 2015" +// Full Date "Wednesday March 25 2015" +//========================================= +//-- also - +// if the given epoch is really small, they've probably given seconds and not milliseconds +// anything below this number is likely (but not necessarily) a mistaken input. +// this may seem like an arbitrary number, but it's 'within jan 1970' +// this is only really ambiguous until 2054 or so + +var minimumEpoch = 2500000000; +var defaults = { + year: new Date().getFullYear(), + month: 0, + date: 1 +}; //support [2016, 03, 01] format + +var handleArray = function handleArray(s, arr) { + var order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond']; + + for (var _i4 = 0; _i4 < order.length; _i4++) { + var _num2 = arr[_i4] || defaults[order[_i4]] || 0; + + s = s[order[_i4]](_num2); + } + + return s; +}; //support {year:2016, month:3} format + + +var handleObject = function handleObject(s, obj) { + obj = Object.assign({}, defaults, obj); + var keys = Object.keys(obj); + + for (var _i5 = 0; _i5 < keys.length; _i5++) { + var unit = keys[_i5]; //make sure we have this method + + if (s[unit] === undefined || typeof s[unit] !== 'function') { + continue; + } //make sure the value is a number + + + if (obj[unit] === null || obj[unit] === undefined || obj[unit] === '') { + continue; + } + + var _num3 = obj[unit] || defaults[unit] || 0; + + s = s[unit](_num3); + } + + return s; +}; //find the epoch from different input styles + + +var parseInput = function parseInput(s, input, givenTz) { + //if we've been given a epoch number, it's easy + if (typeof input === 'number') { + if (input > 0 && input < minimumEpoch && s.silent === false) { + console.warn(' - Warning: You are setting the date to January 1970.'); + console.warn(' - did input seconds instead of milliseconds?'); + } + + s.epoch = input; + return s; + } //set tmp time + + + s.epoch = Date.now(); + + if (input === null || input === undefined) { + return s; //k, we're good. + } //support input of Date() object + + + if (fns.isDate(input) === true) { + s.epoch = input.getTime(); + return s; + } //support [2016, 03, 01] format + + + if (fns.isArray(input) === true) { + s = handleArray(s, input); + return s; + } //support {year:2016, month:3} format + + + if (fns.isObject(input) === true) { + //support spacetime object as input + if (input.epoch) { + s.epoch = input.epoch; + s.tz = input.tz; + return s; + } + + s = handleObject(s, input); + return s; + } //input as a string.. + + + if (typeof input !== 'string') { + return s; + } //little cleanup.. + + + input = input.replace(/\b(mon|tues|wed|wednes|thu|thurs|fri|sat|satur|sun)(day)?\b/i, ''); + input = input.replace(/,/g, ''); + input = input.replace(/ +/g, ' ').trim(); //try some known-words, like 'now' + + if (namedDates.hasOwnProperty(input) === true) { + s = namedDates[input](s); + return s; + } //try each text-parse template, use the first good result + + + for (var _i6 = 0; _i6 < strParse.length; _i6++) { + var m = input.match(strParse[_i6].reg); + + if (m) { + var res = strParse[_i6].parse(s, m, givenTz); + + if (res !== null) { + return res; + } + } + } + + if (s.silent === false) { + console.warn("Warning: couldn't parse date-string: '" + input + "'"); + } + + s.epoch = null; + return s; +}; + +var input = parseInput; +var shortDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; +var longDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']; +var days = { + "short": function short() { + return shortDays; + }, + "long": function long() { + return longDays; + }, + set: function set(i18n) { + shortDays = i18n["short"] || shortDays; + longDays = i18n["long"] || longDays; + } +}; // create the timezone offset part of an iso timestamp +// it's kind of nuts how involved this is +// "+01:00", "+0100", or simply "+01" + +var isoOffset = function isoOffset(s) { + var offset = s.timezone().current.offset; + var isNegative = offset < 0; + var minute = '00'; //handle 5.5 → '5:30' + + if (Math.abs(offset % 1) === 0.5) { + minute = '30'; + + if (offset >= 0) { + offset = Math.floor(offset); + } else { + offset = Math.ceil(offset); + } + } + + if (isNegative) { + //handle negative sign + offset *= -1; + offset = fns.zeroPad(offset, 2); + offset = '-' + offset; + } else { + offset = fns.zeroPad(offset, 2); + offset = '+' + offset; + } + + offset = offset + ':' + minute; //'Z' means 00 + + if (offset === '+00:00') { + offset = 'Z'; + } + + return offset; +}; + +var _offset = isoOffset; +var format = { + day: function day(s) { + return fns.titleCase(s.dayName()); + }, + 'day-short': function dayShort(s) { + return fns.titleCase(days["short"]()[s.day()]); + }, + 'day-number': function dayNumber(s) { + return s.day(); + }, + 'day-ordinal': function dayOrdinal(s) { + return fns.ordinal(s.day()); + }, + 'day-pad': function dayPad(s) { + return fns.zeroPad(s.day()); + }, + date: function date(s) { + return s.date(); + }, + 'date-ordinal': function dateOrdinal(s) { + return fns.ordinal(s.date()); + }, + 'date-pad': function datePad(s) { + return fns.zeroPad(s.date()); + }, + month: function month(s) { + return fns.titleCase(s.monthName()); + }, + 'month-short': function monthShort(s) { + return fns.titleCase(months["short"]()[s.month()]); + }, + 'month-number': function monthNumber(s) { + return s.month(); + }, + 'month-ordinal': function monthOrdinal(s) { + return fns.ordinal(s.month()); + }, + 'month-pad': function monthPad(s) { + return fns.zeroPad(s.month()); + }, + 'iso-month': function isoMonth(s) { + return fns.zeroPad(s.month() + 1); + }, + //1-based months + year: function year(s) { + var year = s.year(); + + if (year > 0) { + return year; + } + + year = Math.abs(year); + return year + ' BC'; + }, + 'year-short': function yearShort(s) { + var year = s.year(); + + if (year > 0) { + return "'".concat(String(s.year()).substr(2, 4)); + } + + year = Math.abs(year); + return year + ' BC'; + }, + 'iso-year': function isoYear(s) { + var year = s.year(); + var isNegative = year < 0; + var str = fns.zeroPad(Math.abs(year), 4); //0-padded + + if (isNegative) { + //negative years are for some reason 6-digits ('-00008') + str = fns.zeroPad(str, 6); + str = '-' + str; + } + + return str; + }, + time: function time(s) { + return s.time(); + }, + 'time-24': function time24(s) { + return "".concat(s.hour24(), ":").concat(fns.zeroPad(s.minute())); + }, + hour: function hour(s) { + return s.hour12(); + }, + 'hour-pad': function hourPad(s) { + return fns.zeroPad(s.hour12()); + }, + 'hour-24': function hour24(s) { + return s.hour24(); + }, + 'hour-24-pad': function hour24Pad(s) { + return fns.zeroPad(s.hour24()); + }, + minute: function minute(s) { + return s.minute(); + }, + 'minute-pad': function minutePad(s) { + return fns.zeroPad(s.minute()); + }, + second: function second(s) { + return s.second(); + }, + 'second-pad': function secondPad(s) { + return fns.zeroPad(s.second()); + }, + ampm: function ampm(s) { + return s.ampm(); + }, + quarter: function quarter(s) { + return 'Q' + s.quarter(); + }, + season: function season(s) { + return s.season(); + }, + era: function era(s) { + return s.era(); + }, + json: function json(s) { + return s.json(); + }, + timezone: function timezone(s) { + return s.timezone().name; + }, + offset: function offset(s) { + return _offset(s); + }, + numeric: function numeric(s) { + return "".concat(s.year(), "/").concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date())); + }, + // yyyy/mm/dd + 'numeric-us': function numericUs(s) { + return "".concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date()), "/").concat(s.year()); + }, + // mm/dd/yyyy + 'numeric-uk': function numericUk(s) { + return "".concat(fns.zeroPad(s.date()), "/").concat(fns.zeroPad(s.month() + 1), "/").concat(s.year()); + }, + //dd/mm/yyyy + 'mm/dd': function mmDd(s) { + return "".concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date())); + }, + //mm/dd + // ... https://en.wikipedia.org/wiki/ISO_8601 ;((( + iso: function iso(s) { + var year = s.format('iso-year'); + var month = fns.zeroPad(s.month() + 1); //1-based months + + var date = fns.zeroPad(s.date()); + var hour = fns.zeroPad(s.h24()); + var minute = fns.zeroPad(s.minute()); + var second = fns.zeroPad(s.second()); + var ms = fns.zeroPad(s.millisecond(), 3); + + var offset = _offset(s); + + return "".concat(year, "-").concat(month, "-").concat(date, "T").concat(hour, ":").concat(minute, ":").concat(second, ".").concat(ms).concat(offset); //2018-03-09T08:50:00.000-05:00 + }, + 'iso-short': function isoShort(s) { + var month = fns.zeroPad(s.month() + 1); //1-based months + + var date = fns.zeroPad(s.date()); + return "".concat(s.year(), "-").concat(month, "-").concat(date); //2017-02-15 + }, + 'iso-utc': function isoUtc(s) { + return new Date(s.epoch).toISOString(); //2017-03-08T19:45:28.367Z + }, + //i made these up + nice: function nice(s) { + return "".concat(months["short"]()[s.month()], " ").concat(fns.ordinal(s.date()), ", ").concat(s.time()); + }, + 'nice-year': function niceYear(s) { + return "".concat(months["short"]()[s.month()], " ").concat(fns.ordinal(s.date()), ", ").concat(s.year()); + }, + 'nice-day': function niceDay(s) { + return "".concat(days["short"]()[s.day()], " ").concat(fns.titleCase(months["short"]()[s.month()]), " ").concat(fns.ordinal(s.date())); + }, + 'nice-full': function niceFull(s) { + return "".concat(s.dayName(), " ").concat(fns.titleCase(s.monthName()), " ").concat(fns.ordinal(s.date()), ", ").concat(s.time()); + } +}; //aliases + +var aliases = { + 'day-name': 'day', + 'month-name': 'month', + 'iso 8601': 'iso', + 'time-h24': 'time-24', + 'time-12': 'time', + 'time-h12': 'time', + tz: 'timezone', + 'day-num': 'day-number', + 'month-num': 'month-number', + 'month-iso': 'iso-month', + 'year-iso': 'iso-year', + 'nice-short': 'nice', + mdy: 'numeric-us', + dmy: 'numeric-uk', + ymd: 'numeric', + 'yyyy/mm/dd': 'numeric', + 'mm/dd/yyyy': 'numeric-us', + 'dd/mm/yyyy': 'numeric-us', + 'little-endian': 'numeric-uk', + 'big-endian': 'numeric', + 'day-nice': 'nice-day' +}; +Object.keys(aliases).forEach(function (k) { + return format[k] = format[aliases[k]]; +}); + +var printFormat = function printFormat(s) { + var str = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + + //don't print anything if it's an invalid date + if (s.isValid() !== true) { + return ''; + } //support .format('month') + + + if (format.hasOwnProperty(str)) { + var out = format[str](s) || ''; + + if (str !== 'json') { + out = String(out); + + if (str !== 'ampm') { + out = fns.titleCase(out); + } + } + + return out; + } //support '{hour}:{minute}' notation + + + if (str.indexOf('{') !== -1) { + var sections = /\{(.+?)\}/g; + str = str.replace(sections, function (_, fmt) { + fmt = fmt.toLowerCase().trim(); + + if (format.hasOwnProperty(fmt)) { + return String(format[fmt](s) || ''); + } + + return ''; + }); + return str; + } + + return s.format('iso-short'); +}; + +var format_1 = printFormat; +var pad = fns.zeroPad; +var formatTimezone = fns.formatTimezone; //parse this insane unix-time-templating thing, from the 19th century +//http://unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns +//time-symbols we support + +var mapping = { + G: function G(s) { + return s.era(); + }, + GG: function GG(s) { + return s.era(); + }, + GGG: function GGG(s) { + return s.era(); + }, + GGGG: function GGGG(s) { + return s.era() === 'AD' ? 'Anno Domini' : 'Before Christ'; + }, + //year + y: function y(s) { + return s.year(); + }, + yy: function yy(s) { + //last two chars + return parseInt(String(s.year()).substr(2, 4), 10); + }, + yyy: function yyy(s) { + return s.year(); + }, + yyyy: function yyyy(s) { + return s.year(); + }, + yyyyy: function yyyyy(s) { + return '0' + s.year(); + }, + // u: (s) => {},//extended non-gregorian years + //quarter + Q: function Q(s) { + return s.quarter(); + }, + QQ: function QQ(s) { + return s.quarter(); + }, + QQQ: function QQQ(s) { + return s.quarter(); + }, + QQQQ: function QQQQ(s) { + return s.quarter(); + }, + //month + M: function M(s) { + return s.month() + 1; + }, + MM: function MM(s) { + return pad(s.month() + 1); + }, + MMM: function MMM(s) { + return s.format('month-short'); + }, + MMMM: function MMMM(s) { + return s.format('month'); + }, + //week + w: function w(s) { + return s.week(); + }, + ww: function ww(s) { + return pad(s.week()); + }, + //week of month + // W: (s) => s.week(), + //date of month + d: function d(s) { + return s.date(); + }, + dd: function dd(s) { + return pad(s.date()); + }, + //date of year + D: function D(s) { + return s.dayOfYear(); + }, + DD: function DD(s) { + return pad(s.dayOfYear()); + }, + DDD: function DDD(s) { + return pad(s.dayOfYear(), 3); + }, + // F: (s) => {},//date of week in month + // g: (s) => {},//modified julian day + //day + E: function E(s) { + return s.format('day-short'); + }, + EE: function EE(s) { + return s.format('day-short'); + }, + EEE: function EEE(s) { + return s.format('day-short'); + }, + EEEE: function EEEE(s) { + return s.format('day'); + }, + EEEEE: function EEEEE(s) { + return s.format('day')[0]; + }, + e: function e(s) { + return s.day(); + }, + ee: function ee(s) { + return s.day(); + }, + eee: function eee(s) { + return s.format('day-short'); + }, + eeee: function eeee(s) { + return s.format('day'); + }, + eeeee: function eeeee(s) { + return s.format('day')[0]; + }, + //am/pm + a: function a(s) { + return s.ampm().toUpperCase(); + }, + aa: function aa(s) { + return s.ampm().toUpperCase(); + }, + aaa: function aaa(s) { + return s.ampm().toUpperCase(); + }, + aaaa: function aaaa(s) { + return s.ampm().toUpperCase(); + }, + //hour + h: function h(s) { + return s.h12(); + }, + hh: function hh(s) { + return pad(s.h12()); + }, + H: function H(s) { + return s.hour(); + }, + HH: function HH(s) { + return pad(s.hour()); + }, + // j: (s) => {},//weird hour format + m: function m(s) { + return s.minute(); + }, + mm: function mm(s) { + return pad(s.minute()); + }, + s: function s(_s) { + return _s.second(); + }, + ss: function ss(s) { + return pad(s.second()); + }, + //milliseconds in the day + A: function A(s) { + return s.epoch - s.startOf('day').epoch; + }, + //timezone + z: function z(s) { + return s.timezone().name; + }, + zz: function zz(s) { + return s.timezone().name; + }, + zzz: function zzz(s) { + return s.timezone().name; + }, + zzzz: function zzzz(s) { + return s.timezone().name; + }, + Z: function Z(s) { + return formatTimezone(s.timezone().current.offset); + }, + ZZ: function ZZ(s) { + return formatTimezone(s.timezone().current.offset); + }, + ZZZ: function ZZZ(s) { + return formatTimezone(s.timezone().current.offset); + }, + ZZZZ: function ZZZZ(s) { + return formatTimezone(s.timezone().current.offset, ':'); + } +}; + +var addAlias = function addAlias(_char, to, n) { + var name = _char; + var toName = to; + + for (var _i7 = 0; _i7 < n; _i7 += 1) { + mapping[name] = mapping[toName]; + name += _char; + toName += to; + } +}; + +addAlias('q', 'Q', 4); +addAlias('L', 'M', 4); +addAlias('Y', 'y', 4); +addAlias('c', 'e', 4); +addAlias('k', 'H', 2); +addAlias('K', 'h', 2); +addAlias('S', 's', 2); +addAlias('v', 'z', 4); +addAlias('V', 'Z', 4); + +var unixFmt = function unixFmt(s, str) { + var chars = str.split(''); //combine consecutive chars, like 'yyyy' as one. + + var arr = [chars[0]]; + var quoteOn = false; + + for (var _i8 = 1; _i8 < chars.length; _i8 += 1) { + //support quoted substrings + if (chars[_i8] === "'") { + quoteOn = !quoteOn; //support '', meaning one tick + + if (quoteOn === true && chars[_i8 + 1] && chars[_i8 + 1] === "'") { + quoteOn = true; + } else { + continue; + } + } //merge it with the last one + + + if (quoteOn === true || chars[_i8] === arr[arr.length - 1][0]) { + arr[arr.length - 1] += chars[_i8]; + } else { + arr.push(chars[_i8]); + } + } + + return arr.reduce(function (txt, c) { + if (mapping[c] !== undefined) { + txt += mapping[c](s) || ''; + } else { + txt += c; + } + + return txt; + }, ''); +}; + +var unixFmt_1 = unixFmt; +var units$1 = ['year', 'season', 'quarter', 'month', 'week', 'day', 'quarterHour', 'hour', 'minute']; + +var doUnit = function doUnit(s, k) { + var start = s.clone().startOf(k); + var end = s.clone().endOf(k); + var duration = end.epoch - start.epoch; + var percent = (s.epoch - start.epoch) / duration; + return parseFloat(percent.toFixed(2)); +}; //how far it is along, from 0-1 + + +var progress = function progress(s, unit) { + if (unit) { + unit = fns.normalize(unit); + return doUnit(s, unit); + } + + var obj = {}; + units$1.forEach(function (k) { + obj[k] = doUnit(s, k); + }); + return obj; +}; + +var progress_1 = progress; //round to either current, or +1 of this unit + +var nearest = function nearest(s, unit) { + //how far have we gone? + var prog = s.progress(); + unit = fns.normalize(unit); //fix camel-case for this one + + if (unit === 'quarterhour') { + unit = 'quarterHour'; + } + + if (prog[unit] !== undefined) { + // go forward one? + if (prog[unit] > 0.5) { + s = s.add(1, unit); + } // go to start + + + s = s.startOf(unit); + } else if (s.silent === false) { + console.warn("no known unit '" + unit + "'"); + } + + return s; +}; + +var nearest_1 = nearest; //increment until dates are the same + +var climb = function climb(a, b, unit) { + var i = 0; + a = a.clone(); + + while (a.isBefore(b)) { + //do proper, expensive increment to catch all-the-tricks + a = a.add(1, unit); + i += 1; + } //oops, we went too-far.. + + + if (a.isAfter(b, unit)) { + i -= 1; + } + + return i; +}; // do a thurough +=1 on the unit, until they match +// for speed-reasons, only used on day, month, week. + + +var diffOne = function diffOne(a, b, unit) { + if (a.isBefore(b)) { + return climb(a, b, unit); + } else { + return climb(b, a, unit) * -1; //reverse it + } +}; + +var one = diffOne; // don't do anything too fancy here. +// 2020 - 2019 may be 1 year, or 0 years +// - '1 year difference' means 366 days during a leap year + +var fastYear = function fastYear(a, b) { + var years = b.year() - a.year(); // should we decrement it by 1? + + a = a.year(b.year()); + + if (a.isAfter(b)) { + years -= 1; + } + + return years; +}; // use a waterfall-method for computing a diff of any 'pre-knowable' units +// compute years, then compute months, etc.. +// ... then ms-math for any very-small units + + +var diff = function diff(a, b) { + // an hour is always the same # of milliseconds + // so these units can be 'pre-calculated' + var msDiff = b.epoch - a.epoch; + var obj = { + milliseconds: msDiff, + seconds: parseInt(msDiff / 1000, 10) + }; + obj.minutes = parseInt(obj.seconds / 60, 10); + obj.hours = parseInt(obj.minutes / 60, 10); //do the year + + var tmp = a.clone(); + obj.years = fastYear(tmp, b); + tmp = a.add(obj.years, 'year'); //there's always 12 months in a year... + + obj.months = obj.years * 12; + tmp = a.add(obj.months, 'month'); + obj.months += one(tmp, b, 'month'); // there's always atleast 52 weeks in a year.. + // (month * 4) isn't as close + + obj.weeks = obj.years * 52; + tmp = a.add(obj.weeks, 'week'); + obj.weeks += one(tmp, b, 'week'); // there's always atleast 7 days in a week + + obj.days = obj.weeks * 7; + tmp = a.add(obj.days, 'day'); + obj.days += one(tmp, b, 'day'); + return obj; +}; + +var waterfall = diff; + +var reverseDiff = function reverseDiff(obj) { + Object.keys(obj).forEach(function (k) { + obj[k] *= -1; + }); + return obj; +}; // this method counts a total # of each unit, between a, b. +// '1 month' means 28 days in february +// '1 year' means 366 days in a leap year + + +var main = function main(a, b, unit) { + b = fns.beADate(b, a); //reverse values, if necessary + + var reversed = false; + + if (a.isAfter(b)) { + var tmp = a; + a = b; + b = tmp; + reversed = true; + } //compute them all (i know!) + + + var obj = waterfall(a, b); + + if (reversed) { + obj = reverseDiff(obj); + } //return just the requested unit + + + if (unit) { + //make sure it's plural-form + unit = fns.normalize(unit); + + if (/s$/.test(unit) !== true) { + unit += 's'; + } + + if (unit === 'dates') { + unit = 'days'; + } + + return obj[unit]; + } + + return obj; +}; + +var diff$1 = main; //by spencermountain + Shaun Grady +//our conceptual 'break-points' for each unit + +var qualifiers = { + months: { + almost: 10, + over: 4 + }, + days: { + almost: 25, + over: 10 + }, + hours: { + almost: 20, + over: 8 + }, + minutes: { + almost: 50, + over: 20 + }, + seconds: { + almost: 50, + over: 20 + } +}; //get number of hours/minutes... between the two dates + +function getDiff(a, b) { + var isBefore = a.isBefore(b); + var later = isBefore ? b : a; + var earlier = isBefore ? a : b; + earlier = earlier.clone(); + var diff = { + years: 0, + months: 0, + days: 0, + hours: 0, + minutes: 0, + seconds: 0 + }; + Object.keys(diff).forEach(function (unit) { + if (earlier.isSame(later, unit)) { + return; + } + + var max = earlier.diff(later, unit); + earlier = earlier.add(max, unit); + diff[unit] = max; + }); //reverse it, if necessary + + if (isBefore) { + Object.keys(diff).forEach(function (u) { + if (diff[u] !== 0) { + diff[u] *= -1; + } + }); + } + + return diff; +} // Expects a plural unit arg + + +function pluralize(value, unit) { + if (value === 1) { + unit = unit.slice(0, -1); + } + + return value + ' ' + unit; +} //create the human-readable diff between the two dates + + +var since = function since(start, end) { + end = fns.beADate(end, start); + var diff = getDiff(start, end); + var isNow = Object.keys(diff).every(function (u) { + return !diff[u]; + }); + + if (isNow === true) { + return { + diff: diff, + rounded: 'now', + qualified: 'now', + precise: 'now' + }; + } + + var rounded; + var qualified; + var precise; + var englishValues = []; //go through each value and create its text-representation + + Object.keys(diff).forEach(function (unit, i, units) { + var value = Math.abs(diff[unit]); + + if (value === 0) { + return; + } + + var englishValue = pluralize(value, unit); + englishValues.push(englishValue); + + if (!rounded) { + rounded = qualified = englishValue; + + if (i > 4) { + return; + } //is it a 'almost' something, etc? + + + var nextUnit = units[i + 1]; + var nextValue = Math.abs(diff[nextUnit]); + + if (nextValue > qualifiers[nextUnit].almost) { + rounded = pluralize(value + 1, unit); + qualified = 'almost ' + rounded; + } else if (nextValue > qualifiers[nextUnit].over) qualified = 'over ' + englishValue; + } + }); //make them into a string + + precise = englishValues.splice(0, 2).join(', '); //handle before/after logic + + if (start.isAfter(end) === true) { + rounded += ' ago'; + qualified += ' ago'; + precise += ' ago'; + } else { + rounded = 'in ' + rounded; + qualified = 'in ' + qualified; + precise = 'in ' + precise; + } + + return { + diff: diff, + rounded: rounded, + qualified: qualified, + precise: precise + }; +}; + +var since_1 = since; //https://www.timeanddate.com/calendar/aboutseasons.html +// Spring - from March 1 to May 31; +// Summer - from June 1 to August 31; +// Fall (autumn) - from September 1 to November 30; and, +// Winter - from December 1 to February 28 (February 29 in a leap year). + +var seasons$1 = { + north: [['spring', 2, 1], //spring march 1 + ['summer', 5, 1], //june 1 + ['fall', 8, 1], //sept 1 + ['autumn', 8, 1], //sept 1 + ['winter', 11, 1] //dec 1 + ], + south: [['fall', 2, 1], //march 1 + ['autumn', 2, 1], //march 1 + ['winter', 5, 1], //june 1 + ['spring', 8, 1], //sept 1 + ['summer', 11, 1] //dec 1 + ] +}; +var quarters = [null, [0, 1], //jan 1 +[3, 1], //apr 1 +[6, 1], //july 1 +[9, 1] //oct 1 +]; +var units$2 = { + minute: function minute(s) { + walk_1(s, { + second: 0, + millisecond: 0 + }); + return s; + }, + quarterhour: function quarterhour(s) { + var minute = s.minutes(); + + if (minute >= 45) { + s = s.minutes(45); + } else if (minute >= 30) { + s = s.minutes(30); + } else if (minute >= 15) { + s = s.minutes(15); + } else { + s = s.minutes(0); + } + + walk_1(s, { + second: 0, + millisecond: 0 + }); + return s; + }, + hour: function hour(s) { + walk_1(s, { + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + day: function day(s) { + walk_1(s, { + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + week: function week(s) { + var original = s.clone(); + s = s.day(s._weekStart); //monday + + if (s.isAfter(original)) { + s = s.subtract(1, 'week'); + } + + walk_1(s, { + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + month: function month(s) { + walk_1(s, { + date: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + quarter: function quarter(s) { + var q = s.quarter(); + + if (quarters[q]) { + walk_1(s, { + month: quarters[q][0], + date: quarters[q][1], + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + } + + return s; + }, + season: function season(s) { + var current = s.season(); + var hem = 'north'; + + if (s.hemisphere() === 'South') { + hem = 'south'; + } + + for (var _i9 = 0; _i9 < seasons$1[hem].length; _i9++) { + if (seasons$1[hem][_i9][0] === current) { + //winter goes between years + var year = s.year(); + + if (current === 'winter' && s.month() < 3) { + year -= 1; + } + + walk_1(s, { + year: year, + month: seasons$1[hem][_i9][1], + date: seasons$1[hem][_i9][2], + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + } + } + + return s; + }, + year: function year(s) { + walk_1(s, { + month: 0, + date: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0 + }); + return s; + }, + decade: function decade(s) { + s = s.startOf('year'); + var year = s.year(); + var decade = parseInt(year / 10, 10) * 10; + s = s.year(decade); + return s; + }, + century: function century(s) { + s = s.startOf('year'); + var year = s.year(); // near 0AD goes '-1 | +1' + + var decade = parseInt(year / 100, 10) * 100; + s = s.year(decade); + return s; + } +}; +units$2.date = units$2.day; + +var startOf = function startOf(a, unit) { + var s = a.clone(); + unit = fns.normalize(unit); + + if (units$2[unit]) { + return units$2[unit](s); + } + + if (unit === 'summer' || unit === 'winter') { + s = s.season(unit); + return units$2.season(s); + } + + return s; +}; //piggy-backs off startOf + + +var endOf = function endOf(a, unit) { + var s = a.clone(); + unit = fns.normalize(unit); + + if (units$2[unit]) { + s = units$2[unit](s); + s = s.add(1, unit); + s = s.subtract(1, 'milliseconds'); + return s; + } + + return s; +}; + +var startOf_1 = { + startOf: startOf, + endOf: endOf +}; //is it 'wednesday'? + +var isDay = function isDay(unit) { + if (days["short"]().find(function (s) { + return s === unit; + })) { + return true; + } + + if (days["long"]().find(function (s) { + return s === unit; + })) { + return true; + } + + return false; +}; // return a list of the weeks/months/days between a -> b +// returns spacetime objects in the timezone of the input + + +var every = function every(start) { + var unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var end = arguments.length > 2 ? arguments[2] : undefined; + + if (!unit || !end) { + return []; + } //cleanup unit param + + + unit = fns.normalize(unit); //cleanup to param + + end = start.clone().set(end); //swap them, if they're backwards + + if (start.isAfter(end)) { + var tmp = start; + start = end; + end = tmp; + } //support 'every wednesday' + + + var d = start.clone(); + + if (isDay(unit)) { + d = d.next(unit); + unit = 'week'; + } else { + d = d.next(unit); + } //okay, actually start doing it + + + var result = []; + + while (d.isBefore(end)) { + result.push(d); + d = d.add(1, unit); + } + + return result; +}; + +var every_1 = every; + +var parseDst = function parseDst(dst) { + if (!dst) { + return []; + } + + return dst.split('->'); +}; + +var titleCase = function titleCase(str) { + str = str[0].toUpperCase() + str.substr(1); + str = str.replace(/\/gmt/, '/GMT'); + str = str.replace(/[\/_]([a-z])/gi, function (s) { + return s.toUpperCase(); + }); + return str; +}; //get metadata about this timezone + + +var timezone = function timezone(s) { + var zones = s.timezones; + var tz = s.tz; + + if (zones.hasOwnProperty(tz) === false) { + tz = find(s.tz, zones); + } + + if (tz === null) { + if (s.silent === false) { + console.warn("Warn: could not find given or local timezone - '" + s.tz + "'"); + } + + return { + current: { + epochShift: 0 + } + }; + } + + var found = zones[tz]; + var result = { + name: titleCase(tz), + hasDst: Boolean(found.dst), + default_offset: found.offset, + //do north-hemisphere version as default (sorry!) + hemisphere: found.hem === 's' ? 'South' : 'North', + current: {} + }; + + if (result.hasDst) { + var arr = parseDst(found.dst); + result.change = { + start: arr[0], + back: arr[1] + }; + } //find the offsets for summer/winter times + //(these variable names are north-centric) + + + var summer = found.offset; // (july) + + var winter = summer; // (january) assume it's the same for now + + if (result.hasDst === true) { + if (result.hemisphere === 'North') { + winter = summer - 1; + } else { + //southern hemisphere + winter = found.offset + 1; + } + } //find out which offset to use right now + //use 'summer' time july-time + + + if (result.hasDst === false) { + result.current.offset = summer; + result.current.isDST = false; + } else if (summerTime(s.epoch, result.change.start, result.change.back, summer) === true) { + result.current.offset = summer; + result.current.isDST = result.hemisphere === 'North'; //dst 'on' in winter in north + } else { + //use 'winter' january-time + result.current.offset = winter; + result.current.isDST = result.hemisphere === 'South'; //dst 'on' in summer in south + } + + return result; +}; + +var timezone_1 = timezone; +var units$3 = ['century', 'decade', 'year', 'month', 'date', 'day', 'hour', 'minute', 'second', 'millisecond']; //the spacetime instance methods (also, the API) + +var methods$1 = { + set: function set(input$1, tz) { + var s = this.clone(); + s = input(s, input$1); + + if (tz) { + this.tz = find(tz); + } + + return s; + }, + timezone: function timezone() { + return timezone_1(this); + }, + isDST: function isDST() { + return timezone_1(this).current.isDST; + }, + hasDST: function hasDST() { + return timezone_1(this).hasDst; + }, + offset: function offset() { + return timezone_1(this).current.offset * 60; + }, + hemisphere: function hemisphere() { + return timezone_1(this).hemisphere; + }, + format: function format(fmt) { + return format_1(this, fmt); + }, + unixFmt: function unixFmt(fmt) { + return unixFmt_1(this, fmt); + }, + startOf: function startOf(unit) { + return startOf_1.startOf(this, unit); + }, + endOf: function endOf(unit) { + return startOf_1.endOf(this, unit); + }, + leapYear: function leapYear() { + var year = this.year(); + return fns.isLeapYear(year); + }, + progress: function progress(unit) { + return progress_1(this, unit); + }, + nearest: function nearest(unit) { + return nearest_1(this, unit); + }, + diff: function diff(d, unit) { + return diff$1(this, d, unit); + }, + since: function since(d) { + if (!d) { + d = this.clone().set(); + } + + return since_1(this, d); + }, + next: function next(unit) { + var s = this.add(1, unit); + return s.startOf(unit); + }, + //the start of the previous year/week/century + last: function last(unit) { + var s = this.subtract(1, unit); + return s.startOf(unit); + }, + isValid: function isValid() { + //null/undefined epochs + if (!this.epoch && this.epoch !== 0) { + return false; + } + + return !isNaN(this.d.getTime()); + }, + //travel to this timezone + "goto": function goto(tz) { + var s = this.clone(); + s.tz = find(tz, s.timezones); //science! + + return s; + }, + //get each week/month/day between a -> b + every: function every(unit, to) { + return every_1(this, unit, to); + }, + isAwake: function isAwake() { + var hour = this.hour(); //10pm -> 8am + + if (hour < 8 || hour > 22) { + return false; + } + + return true; + }, + isAsleep: function isAsleep() { + return !this.isAwake(); + }, + //pretty-printing + log: function log() { + console.log(''); + console.log(format_1(this, 'nice-short')); + return this; + }, + logYear: function logYear() { + console.log(''); + console.log(format_1(this, 'full-short')); + return this; + }, + json: function json() { + var _this = this; + + return units$3.reduce(function (h, unit) { + h[unit] = _this[unit](); + return h; + }, {}); + }, + debug: function debug() { + var tz = this.timezone(); + var date = this.format('MM') + ' ' + this.format('date-ordinal') + ' ' + this.year(); + date += '\n - ' + this.format('time'); + console.log('\n\n', date + '\n - ' + tz.name + ' (' + tz.current.offset + ')'); + return this; + }, + //alias of 'since' but opposite - like moment.js + from: function from(d) { + d = this.clone().set(d); + return d.since(this); + }, + fromNow: function fromNow() { + var d = this.clone().set(Date.now()); + return d.since(this); + }, + weekStart: function weekStart(input) { + //accept a number directly + if (typeof input === 'number') { + this._weekStart = input; + return this; + } + + if (typeof input === 'string') { + // accept 'wednesday' + input = input.toLowerCase().trim(); + + var _num4 = days["short"]().indexOf(input); + + if (_num4 === -1) { + _num4 = days["long"]().indexOf(input); + } + + if (_num4 === -1) { + _num4 = 1; //go back to default + } + + this._weekStart = _num4; + } else { + console.warn('Spacetime Error: Cannot understand .weekStart() input:', input); + } + + return this; + } +}; // aliases + +methods$1.inDST = methods$1.isDST; +methods$1.round = methods$1.nearest; +methods$1.each = methods$1.every; +var methods_1 = methods$1; // javascript setX methods like setDate() can't be used because of the local bias +//these methods wrap around them. + +var validate = function validate(n) { + //handle number as a string + if (typeof n === 'string') { + n = parseInt(n, 10); + } + + return n; +}; + +var order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond']; //reduce hostile micro-changes when moving dates by millisecond + +var confirm = function confirm(s, tmp, unit) { + var n = order.indexOf(unit); + var arr = order.slice(n, order.length); + + for (var _i10 = 0; _i10 < arr.length; _i10++) { + var want = tmp[arr[_i10]](); + + s[arr[_i10]](want); + } + + return s; +}; + +var set = { + milliseconds: function milliseconds(s, n) { + n = validate(n); + var current = s.millisecond(); + var diff = current - n; //milliseconds to shift by + + return s.epoch - diff; + }, + seconds: function seconds(s, n) { + n = validate(n); + var diff = s.second() - n; + var shift = diff * milliseconds.second; + return s.epoch - shift; + }, + minutes: function minutes(s, n) { + n = validate(n); + var old = s.clone(); + var diff = s.minute() - n; + var shift = diff * milliseconds.minute; + s.epoch -= shift; + confirm(s, old, 'second'); + return s.epoch; + }, + hours: function hours(s, n) { + n = validate(n); + + if (n >= 24) { + n = 24; + } else if (n < 0) { + n = 0; + } + + var old = s.clone(); + var diff = s.hour() - n; + var shift = diff * milliseconds.hour; + s.epoch -= shift; + walk_1(s, { + hour: n + }); + confirm(s, old, 'minute'); + return s.epoch; + }, + //support setting time by '4:25pm' - this isn't very-well developed.. + time: function time(s, str) { + var m = str.match(/([0-9]{1,2}):([0-9]{1,2})(am|pm)?/); + + if (!m) { + //fallback to support just '2am' + m = str.match(/([0-9]{1,2})(am|pm)/); + + if (!m) { + return s.epoch; + } + + m.splice(2, 0, '0'); //add implicit 0 minutes + } + + var h24 = false; + var hour = parseInt(m[1], 10); + var minute = parseInt(m[2], 10); + + if (hour > 12) { + h24 = true; + } //make the hour into proper 24h time + + + if (h24 === false) { + if (m[3] === 'am' && hour === 12) { + //12am is midnight + hour = 0; + } + + if (m[3] === 'pm' && hour < 12) { + //12pm is noon + hour += 12; + } + } + + s = s.hour(hour); + s = s.minute(minute); + s = s.second(0); + s = s.millisecond(0); + return s.epoch; + }, + date: function date(s, n) { + n = validate(n); //avoid setting february 31st + + if (n > 28) { + var max = monthLengths_1[s.month()]; + + if (n > max) { + n = max; + } + } //avoid setting < 0 + + + if (n <= 0) { + n = 1; + } + + walk_1(s, { + date: n + }); + return s.epoch; + }, + //this one's tricky + month: function month(s, n) { + if (typeof n === 'string') { + n = months.mapping()[n.toLowerCase()]; + } + + n = validate(n); //don't go past december + + if (n >= 12) { + n = 11; + } + + if (n <= 0) { + n = 0; + } + + var date = s.date(); //there's no 30th of february, etc. + + if (date > monthLengths_1[n]) { + //make it as close as we can.. + date = monthLengths_1[n]; + } + + walk_1(s, { + month: n, + date: date + }); + return s.epoch; + }, + year: function year(s, n) { + n = validate(n); + walk_1(s, { + year: n + }); + return s.epoch; + }, + dayOfYear: function dayOfYear(s, n) { + n = validate(n); + var old = s.clone(); + n -= 1; //days are 1-based + + if (n <= 0) { + n = 0; + } else if (n >= 365) { + n = 364; + } + + s = s.startOf('year'); + s = s.add(n, 'day'); + confirm(s, old, 'hour'); + return s.epoch; + } +}; +var methods$1$1 = { + millisecond: function millisecond(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.milliseconds(s, num); + return s; + } + + return this.d.getMilliseconds(); + }, + second: function second(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.seconds(s, num); + return s; + } + + return this.d.getSeconds(); + }, + minute: function minute(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.minutes(s, num); + return s; + } + + return this.d.getMinutes(); + }, + hour: function hour(num) { + var d = this.d; + + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.hours(s, num); + return s; + } + + return d.getHours(); + }, + //'3:30' is 3.5 + hourFloat: function hourFloat(num) { + if (num !== undefined) { + var s = this.clone(); + + var _minute = num % 1; + + _minute = _minute * 60; + + var _hour = parseInt(num, 10); + + s.epoch = set.hours(s, _hour); + s.epoch = set.minutes(s, _minute); + return s; + } + + var d = this.d; + var hour = d.getHours(); + var minute = d.getMinutes(); + minute = minute / 60; + return hour + minute; + }, + // hour in 12h format + hour12: function hour12(str) { + var d = this.d; + + if (str !== undefined) { + var s = this.clone(); + str = '' + str; + var m = str.match(/^([0-9]+)(am|pm)$/); + + if (m) { + var hour = parseInt(m[1], 10); + + if (m[2] === 'pm') { + hour += 12; + } + + s.epoch = set.hours(s, hour); + } + + return s; + } //get the hour + + + var hour12 = d.getHours(); + + if (hour12 > 12) { + hour12 = hour12 - 12; + } + + if (hour12 === 0) { + hour12 = 12; + } + + return hour12; + }, + //some ambiguity here with 12/24h + time: function time(str) { + if (str !== undefined) { + var s = this.clone(); + s.epoch = set.time(s, str); + return s; + } + + return "".concat(this.h12(), ":").concat(fns.zeroPad(this.minute())).concat(this.ampm()); + }, + // either 'am' or 'pm' + ampm: function ampm(input) { + var which = 'am'; + var hour = this.hour(); + + if (hour >= 12) { + which = 'pm'; + } + + if (typeof input !== 'string') { + return which; + } //okay, we're doing a setter + + + var s = this.clone(); + input = input.toLowerCase().trim(); //ampm should never change the day + // - so use `.hour(n)` instead of `.minus(12,'hour')` + + if (hour >= 12 && input === 'am') { + //noon is 12pm + hour -= 12; + return s.hour(hour); + } + + if (hour < 12 && input === 'pm') { + hour += 12; + return s.hour(hour); + } + + return s; + }, + //some hard-coded times of day, like 'noon' + dayTime: function dayTime(str) { + if (str !== undefined) { + var times = { + morning: '7:00am', + breakfast: '7:00am', + noon: '12:00am', + lunch: '12:00pm', + afternoon: '2:00pm', + evening: '6:00pm', + dinner: '6:00pm', + night: '11:00pm', + midnight: '23:59pm' + }; + var s = this.clone(); + str = str || ''; + str = str.toLowerCase(); + + if (times.hasOwnProperty(str) === true) { + s = s.time(times[str]); + } + + return s; + } + + var h = this.hour(); + + if (h < 6) { + return 'night'; + } + + if (h < 12) { + //until noon + return 'morning'; + } + + if (h < 17) { + //until 5pm + return 'afternoon'; + } + + if (h < 22) { + //until 10pm + return 'evening'; + } + + return 'night'; + }, + //parse a proper iso string + iso: function iso(num) { + if (num !== undefined) { + return this.set(num); + } + + return this.format('iso'); + } +}; +var _01Time = methods$1$1; +var methods$2 = { + // # day in the month + date: function date(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.date(s, num); + return s; + } + + return this.d.getDate(); + }, + //like 'wednesday' (hard!) + day: function day(input) { + if (input === undefined) { + return this.d.getDay(); + } + + var original = this.clone(); + var want = input; // accept 'wednesday' + + if (typeof input === 'string') { + input = input.toLowerCase(); + want = days["short"]().indexOf(input); + + if (want === -1) { + want = days["long"]().indexOf(input); + } + } //move approx + + + var day = this.d.getDay(); + var diff = day - want; + var s = this.subtract(diff * 24, 'hours'); //tighten it back up + + walk_1(s, { + hour: original.hour(), + minute: original.minute(), + second: original.second() + }); + return s; + }, + //these are helpful name-wrappers + dayName: function dayName(input) { + if (input === undefined) { + return days["long"]()[this.day()]; + } + + var s = this.clone(); + s = s.day(input); + return s; + }, + //either name or number + month: function month(input) { + if (input !== undefined) { + var s = this.clone(); + s.epoch = set.month(s, input); + return s; + } + + return this.d.getMonth(); + } +}; +var _02Date = methods$2; + +var clearMinutes = function clearMinutes(s) { + s = s.minute(0); + s = s.second(0); + s = s.millisecond(1); + return s; +}; + +var methods$3 = { + // day 0-366 + dayOfYear: function dayOfYear(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.dayOfYear(s, num); + return s; + } //days since newyears - jan 1st is 1, jan 2nd is 2... + + + var sum = 0; + var month = this.d.getMonth(); + var tmp; //count the num days in each month + + for (var _i11 = 1; _i11 <= month; _i11++) { + tmp = new Date(); + tmp.setDate(1); + tmp.setFullYear(this.d.getFullYear()); //the year matters, because leap-years + + tmp.setHours(1); + tmp.setMinutes(1); + tmp.setMonth(_i11); + tmp.setHours(-2); //the last day of the month + + sum += tmp.getDate(); + } + + return sum + this.d.getDate(); + }, + //since the start of the year + week: function week(num) { + // week-setter + if (num !== undefined) { + var s = this.clone(); + s = s.month(0); + s = s.date(1); + s = s.day('monday'); + s = clearMinutes(s); //don't go into last-year + + if (s.monthName() === 'december') { + s = s.add(1, 'week'); + } + + num -= 1; //1-based + + s = s.add(num, 'weeks'); + return s; + } //find-out which week it is + + + var tmp = this.clone(); + tmp = tmp.month(0); + tmp = tmp.date(1); + tmp = clearMinutes(tmp); + tmp = tmp.day('monday'); //don't go into last-year + + if (tmp.monthName() === 'december') { + tmp = tmp.add(1, 'week'); + } // is first monday the 1st? + + + var toAdd = 1; + + if (tmp.date() === 1) { + toAdd = 0; + } + + tmp = tmp.minus(1, 'second'); + var thisOne = this.epoch; //if the week technically hasn't started yet + + if (tmp.epoch > thisOne) { + return 1; + } //speed it up, if we can + + + var i = 0; + var skipWeeks = this.month() * 4; + tmp.epoch += milliseconds.week * skipWeeks; + i += skipWeeks; + + for (; i < 52; i++) { + if (tmp.epoch > thisOne) { + return i + toAdd; + } + + tmp = tmp.add(1, 'week'); + } + + return 52; + }, + //'january' + monthName: function monthName(input) { + if (input === undefined) { + return months["long"]()[this.month()]; + } + + var s = this.clone(); + s = s.month(input); + return s; + }, + //q1, q2, q3, q4 + quarter: function quarter(num) { + if (num !== undefined) { + if (typeof num === 'string') { + num = num.replace(/^q/i, ''); + num = parseInt(num, 10); + } + + if (quarters[num]) { + var s = this.clone(); + var _month = quarters[num][0]; + s = s.month(_month); + s = s.date(1); + s = s.startOf('day'); + return s; + } + } + + var month = this.d.getMonth(); + + for (var _i12 = 1; _i12 < quarters.length; _i12++) { + if (month < quarters[_i12][0]) { + return _i12 - 1; + } + } + + return 4; + }, + //spring, summer, winter, fall + season: function season(input) { + var hem = 'north'; + + if (this.hemisphere() === 'South') { + hem = 'south'; + } + + if (input !== undefined) { + var s = this.clone(); + + for (var _i13 = 0; _i13 < seasons$1[hem].length; _i13++) { + if (input === seasons$1[hem][_i13][0]) { + s = s.month(seasons$1[hem][_i13][1]); + s = s.date(1); + s = s.startOf('day'); + } + } + + return s; + } + + var month = this.d.getMonth(); + + for (var _i14 = 0; _i14 < seasons$1[hem].length - 1; _i14++) { + if (month >= seasons$1[hem][_i14][1] && month < seasons$1[hem][_i14 + 1][1]) { + return seasons$1[hem][_i14][0]; + } + } + + return 'winter'; + }, + //the year number + year: function year(num) { + if (num !== undefined) { + var s = this.clone(); + s.epoch = set.year(s, num); + return s; + } + + return this.d.getFullYear(); + }, + //bc/ad years + era: function era(str) { + if (str !== undefined) { + var s = this.clone(); + str = str.toLowerCase(); //TODO: there is no year-0AD i think. may have off-by-1 error here + + var year = s.d.getFullYear(); //make '1992' into 1992bc.. + + if (str === 'bc' && year > 0) { + s.epoch = set.year(s, year * -1); + } //make '1992bc' into '1992' + + + if (str === 'ad' && year < 0) { + s.epoch = set.year(s, year * -1); + } + + return s; + } + + if (this.d.getFullYear() < 0) { + return 'BC'; + } + + return 'AD'; + }, + // 2019 -> 2010 + decade: function decade(input) { + if (input !== undefined) { + input = String(input); + input = input.replace(/([0-9])'?s$/, '$1'); //1950's + + input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals + + if (!input) { + console.warn('Spacetime: Invalid decade input'); + return this; + } // assume 20th century?? for '70s'. + + + if (input.length === 2 && /[0-9][0-9]/.test(input)) { + input = '19' + input; + } + + var year = Number(input); + + if (isNaN(year)) { + return this; + } // round it down to the decade + + + year = Math.floor(year / 10) * 10; + return this.year(year); //.startOf('decade') + } + + return this.startOf('decade').year(); + }, + // 1950 -> 19+1 + century: function century(input) { + if (input !== undefined) { + if (typeof input === 'string') { + input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals + + input = input.replace(/([0-9]+) ?(b\.?c\.?|a\.?d\.?)/i, function (a, b, c) { + if (c.match(/b\.?c\.?/i)) { + b = '-' + b; + } + + return b; + }); + input = input.replace(/c$/, ''); //20thC + } + + var year = Number(input); + + if (isNaN(input)) { + console.warn('Spacetime: Invalid century input'); + return this; + } // there is no century 0 + + + if (year === 0) { + year = 1; + } + + if (year >= 0) { + year = (year - 1) * 100; + } else { + year = (year + 1) * 100; + } + + return this.year(year); + } // century getter + + + var num = this.startOf('century').year(); + num = Math.floor(num / 100); + + if (num < 0) { + return num - 1; + } + + return num + 1; + }, + // 2019 -> 2+1 + millenium: function millenium(input) { + if (input !== undefined) { + if (typeof input === 'string') { + input = input.replace(/([0-9])(th|rd|st|nd)/, '$1'); //fix ordinals + + input = Number(input); + + if (isNaN(input)) { + console.warn('Spacetime: Invalid millenium input'); + return this; + } + } + + if (input > 0) { + input -= 1; + } + + var year = input * 1000; // there is no year 0 + + if (year === 0) { + year = 1; + } + + return this.year(year); + } // get the current millenium + + + var num = Math.floor(this.year() / 1000); + + if (num >= 0) { + num += 1; + } + + return num; + } +}; +var _03Year = methods$3; +var methods$4 = Object.assign({}, _01Time, _02Date, _03Year); //aliases + +methods$4.milliseconds = methods$4.millisecond; +methods$4.seconds = methods$4.second; +methods$4.minutes = methods$4.minute; +methods$4.hours = methods$4.hour; +methods$4.hour24 = methods$4.hour; +methods$4.h12 = methods$4.hour12; +methods$4.h24 = methods$4.hour24; +methods$4.days = methods$4.day; + +var addMethods = function addMethods(Space) { + //hook the methods into prototype + Object.keys(methods$4).forEach(function (k) { + Space.prototype[k] = methods$4[k]; + }); +}; + +var query = addMethods; +var order$1 = ['millisecond', 'second', 'minute', 'hour', 'date', 'month']; +var keep = { + second: order$1.slice(0, 1), + minute: order$1.slice(0, 2), + quarterhour: order$1.slice(0, 2), + hour: order$1.slice(0, 3), + date: order$1.slice(0, 4), + month: order$1.slice(0, 4), + quarter: order$1.slice(0, 4), + season: order$1.slice(0, 4), + year: order$1, + decade: order$1, + century: order$1 +}; +keep.week = keep.hour; +keep.season = keep.date; +keep.quarter = keep.date; // Units need to be dst adjuested + +var dstAwareUnits = { + year: true, + quarter: true, + season: true, + month: true, + week: true, + day: true +}; +var keepDate = { + month: true, + quarter: true, + season: true, + year: true +}; //month is the only thing we 'model/compute' +//- because ms-shifting can be off by enough + +var rollMonth = function rollMonth(want, old) { + //increment year + if (want.month > 0) { + var years = parseInt(want.month / 12, 10); + want.year = old.year() + years; + want.month = want.month % 12; + } else if (want.month < 0) { + //decrement year + var _years = Math.floor(Math.abs(want.month) / 13, 10); + + _years = Math.abs(_years) + 1; + want.year = old.year() - _years; //ignore extras + + want.month = want.month % 12; + want.month = want.month + 12; + + if (want.month === 12) { + want.month = 0; + } + } + + return want; +}; + +var addMethods$1 = function addMethods$1(SpaceTime) { + SpaceTime.prototype.add = function (num, unit) { + var s = this.clone(); + + if (!unit || num === 0) { + return s; //don't bother + } + + var old = this.clone(); + unit = fns.normalize(unit); //move forward by the estimated milliseconds (rough) + + if (milliseconds[unit]) { + s.epoch += milliseconds[unit] * num; + } else if (unit === 'week') { + s.epoch += milliseconds.day * (num * 7); + } else if (unit === 'quarter' || unit === 'season') { + s.epoch += milliseconds.month * (num * 4); + } else if (unit === 'season') { + s.epoch += milliseconds.month * (num * 4); + } else if (unit === 'quarterhour') { + s.epoch += milliseconds.minute * 15 * num; + } //now ensure our milliseconds/etc are in-line + + + var want = {}; + + if (keep[unit]) { + keep[unit].forEach(function (u) { + want[u] = old[u](); + }); + } + + if (dstAwareUnits[unit]) { + var _diff = old.timezone().current.offset - s.timezone().current.offset; + + s.epoch += _diff * 3600 * 1000; + } //ensure month/year has ticked-over + + + if (unit === 'month') { + want.month = old.month() + num; //month is the one unit we 'model' directly + + want = rollMonth(want, old); + } //support coercing a week, too + + + if (unit === 'week') { + var sum = old.date() + num * 7; + + if (sum <= 28 && sum > 1) { + want.date = sum; + } + } //support 25-hour day-changes on dst-changes + else if (unit === 'date') { + //specify a naive date number, if it's easy to do... + var _sum = old.date() + num; + + if (_sum <= 28 && _sum > 1) { + want.date = _sum; + } //or if we haven't moved at all.. + else if (num !== 0 && old.isSame(s, 'day')) { + want.date = old.date() + num; + } + } //ensure year has changed (leap-years) + else if (unit === 'year' && s.year() === old.year()) { + s.epoch += milliseconds.week; + } //these are easier + else if (unit === 'decade') { + want.year = s.year() + 10; + } else if (unit === 'century') { + want.year = s.year() + 100; + } //keep current date, unless the month doesn't have it. + + + if (keepDate[unit]) { + var max = monthLengths_1[want.month]; + want.date = old.date(); + + if (want.date > max) { + want.date = max; + } + } + + walk_1(s, want); + return s; + }; //subtract is only add *-1 + + + SpaceTime.prototype.subtract = function (num, unit) { + var s = this.clone(); + return s.add(num * -1, unit); + }; //add aliases + + + SpaceTime.prototype.minus = SpaceTime.prototype.subtract; + SpaceTime.prototype.plus = SpaceTime.prototype.add; +}; + +var add = addMethods$1; //make a string, for easy comparison between dates + +var print = { + millisecond: function millisecond(s) { + return s.epoch; + }, + second: function second(s) { + return [s.year(), s.month(), s.date(), s.hour(), s.minute(), s.second()].join('-'); + }, + minute: function minute(s) { + return [s.year(), s.month(), s.date(), s.hour(), s.minute()].join('-'); + }, + hour: function hour(s) { + return [s.year(), s.month(), s.date(), s.hour()].join('-'); + }, + day: function day(s) { + return [s.year(), s.month(), s.date()].join('-'); + }, + week: function week(s) { + return [s.year(), s.week()].join('-'); + }, + month: function month(s) { + return [s.year(), s.month()].join('-'); + }, + quarter: function quarter(s) { + return [s.year(), s.quarter()].join('-'); + }, + year: function year(s) { + return s.year(); + } +}; +print.date = print.day; + +var addMethods$2 = function addMethods$2(SpaceTime) { + SpaceTime.prototype.isSame = function (b, unit) { + var a = this; + + if (!unit) { + return null; + } + + if (typeof b === 'string' || typeof b === 'number') { + b = new SpaceTime(b, this.timezone.name); + } //support 'seconds' aswell as 'second' + + + unit = unit.replace(/s$/, ''); + + if (print[unit]) { + return print[unit](a) === print[unit](b); + } + + return null; + }; +}; + +var same = addMethods$2; + +var addMethods$3 = function addMethods$3(SpaceTime) { + var methods = { + isAfter: function isAfter(d) { + d = fns.beADate(d, this); + var epoch = fns.getEpoch(d); + + if (epoch === null) { + return null; + } + + return this.epoch > epoch; + }, + isBefore: function isBefore(d) { + d = fns.beADate(d, this); + var epoch = fns.getEpoch(d); + + if (epoch === null) { + return null; + } + + return this.epoch < epoch; + }, + isEqual: function isEqual(d) { + d = fns.beADate(d, this); + var epoch = fns.getEpoch(d); + + if (epoch === null) { + return null; + } + + return this.epoch === epoch; + }, + isBetween: function isBetween(start, end) { + start = fns.beADate(start, this); + end = fns.beADate(end, this); + var startEpoch = fns.getEpoch(start); + + if (startEpoch === null) { + return null; + } + + var endEpoch = fns.getEpoch(end); + + if (endEpoch === null) { + return null; + } + + return startEpoch < this.epoch && this.epoch < endEpoch; + } + }; //hook them into proto + + Object.keys(methods).forEach(function (k) { + SpaceTime.prototype[k] = methods[k]; + }); +}; + +var compare = addMethods$3; + +var addMethods$4 = function addMethods$4(SpaceTime) { + var methods = { + i18n: function i18n(data) { + //change the day names + if (fns.isObject(data.days)) { + days.set(data.days); + } //change the month names + + + if (fns.isObject(data.months)) { + months.set(data.months); + } + } + }; //hook them into proto + + Object.keys(methods).forEach(function (k) { + SpaceTime.prototype[k] = methods[k]; + }); +}; + +var i18n = addMethods$4; +var timezones = unpack; //fake timezone-support, for fakers (es5 class) + +var SpaceTime = function SpaceTime(input$1, tz) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + //the holy moment + this.epoch = null; //the shift for the given timezone + + this.tz = find(tz, timezones); //whether to output warnings to console + + this.silent = options.silent || true; // favour british interpretation of 02/02/2018, etc + + this.british = options.dmy || options.british; //does the week start on sunday, or monday: + + this._weekStart = 1; //default to monday + + if (options.weekStart !== undefined) { + this._weekStart = options.weekStart; + } //add getter/setters + + + Object.defineProperty(this, 'd', { + //return a js date object + get: function get() { + var offset = quick(this); //every computer is somewhere- get this computer's built-in offset + + var bias = new Date(this.epoch).getTimezoneOffset() || 0; //movement + + var shift = bias + offset * 60; //in minutes + + shift = shift * 60 * 1000; //in ms + //remove this computer's offset + + var epoch = this.epoch + shift; + var d = new Date(epoch); + return d; + } + }); //add this data on the object, to allow adding new timezones + + Object.defineProperty(this, 'timezones', { + get: function get() { + return timezones; + }, + set: function set(obj) { + timezones = obj; + return obj; + } + }); //parse the various formats + + if (input$1 !== undefined || input$1 === null) { + var tmp = input(this, input$1, tz); + this.epoch = tmp.epoch; + } +}; //(add instance methods to prototype) + + +Object.keys(methods_1).forEach(function (k) { + SpaceTime.prototype[k] = methods_1[k]; +}); // ¯\_(ツ)_/¯ + +SpaceTime.prototype.clone = function () { + return new SpaceTime(this.epoch, this.tz, { + silent: this.silent, + weekStart: this._weekStart + }); +}; //append more methods + + +query(SpaceTime); +add(SpaceTime); +same(SpaceTime); +compare(SpaceTime); +i18n(SpaceTime); +var spacetime = SpaceTime; // const timezones = require('../data'); + +var whereIts = function whereIts(a, b) { + var start = new spacetime(null); + var end = new spacetime(null); + start = start.time(a); //if b is undefined, use as 'within one hour' + + if (b) { + end = end.time(b); + } else { + end = start.add(59, 'minutes'); + } + + var startHour = start.hour(); + var endHour = end.hour(); + var tzs = Object.keys(start.timezones).filter(function (tz) { + if (tz.indexOf('/') === -1) { + return false; + } + + var m = new spacetime(null, tz); + var hour = m.hour(); //do 'calendar-compare' not real-time-compare + + if (hour >= startHour && hour <= endHour) { + //test minutes too, if applicable + if (hour === startHour && m.minute() < start.minute()) { + return false; + } + + if (hour === endHour && m.minute() > end.minute()) { + return false; + } + + return true; + } + + return false; + }); + return tzs; +}; + +var whereIts_1 = whereIts; +var _version = '6.3.0'; + +var main$1 = function main$1(input, tz, options) { + return new spacetime(input, tz, options); +}; //some helper functions on the main method + + +main$1.now = function (tz, options) { + return new spacetime(new Date().getTime(), tz, options); +}; + +main$1.today = function (tz, options) { + var s = new spacetime(new Date().getTime(), tz, options); + return s.startOf('day'); +}; + +main$1.tomorrow = function (tz, options) { + var s = new spacetime(new Date().getTime(), tz, options); + return s.add(1, 'day').startOf('day'); +}; + +main$1.yesterday = function (tz, options) { + var s = new spacetime(new Date().getTime(), tz, options); + return s.subtract(1, 'day').startOf('day'); +}; + +main$1.extend = function (obj) { + Object.keys(obj).forEach(function (k) { + spacetime.prototype[k] = obj[k]; + }); + return this; +}; //find tz by time + + +main$1.whereIts = whereIts_1; +main$1.version = _version; //aliases: + +main$1.plugin = main$1.extend; +var src = main$1; + +var spacetime$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': src +}); + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function createCommonjsModule$1(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +function getCjsExportFromNamespace$1 (n) { + return n && n['default'] || n; +} + +var require$$0 = getCjsExportFromNamespace$1(spacetime$1); + +var halfPast = function halfPast(m, s) { + var hour = m.match('#Cardinal$').text('reduced'); + var term = m.match('(half|quarter|25|15|10|5)'); + var mins = term.text('reduced'); + + if (term.has('half')) { + mins = '30'; + } + + if (term.has('quarter')) { + mins = '15'; + } + + var behind = m.has('to'); // apply it + + s = s.hour(hour); + s = s.startOf('hour'); + + if (behind) { + s = s.subtract(mins, 'minutes'); + } else { + s = s.add(mins, 'minutes'); + } + + return s; +}; + +var parseTime$1 = function parseTime(doc) { + var time = doc.match('(at|by|for|before)? #Time+'); + + if (time.found) { + doc.remove(time); + } // get the main part of the time + + + time = time.not('(at|by|for|before|sharp)'); + time = time.not('on the dot'); + var s = require$$0.now(); + var now = s.clone(); // '5 oclock' + + var m = time.match('^#Cardinal oclock (am|pm)?'); + + if (m.found) { + m = m.not('oclock'); + s = s.hour(m.text('reduced')); + + if (s.isValid() && !s.isEqual(now)) { + return s.time(); + } + } // 'quarter to two' + + + m = time.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal'); + + if (m.found) { + s = halfPast(m, s); + + if (s.isValid() && !s.isEqual(now)) { + return s.time(); + } + } // parse random a time like '4:54pm' + + + var str = time.text('reduced'); + s = s.time(str); + + if (s.isValid() && !s.isEqual(now)) { + return s.time(); + } + + return null; +}; + +var _02Time = parseTime$1; + +// interpret 'this halloween' or 'next june' +var parseRelative = function parseRelative(doc) { + var rel = null; + + if (doc.has('^this? (next|upcoming)')) { + rel = 'next'; + } + + if (doc.has('^this? (last|previous)')) { + rel = 'last'; + } + + if (doc.has('^(this|current)')) { + rel = 'this'; + } // finally, remove it from our text + + + doc.remove('^(this|current|next|upcoming|last|previous)'); + return rel; +}; + +var _03Relative = parseRelative; + +var Unit = +/*#__PURE__*/ +function () { + function Unit(str, unit) { + _classCallCheck(this, Unit); + + this.str = str; + this.unit = unit || 'day'; // set it to the beginning of the given unit + + var d = require$$0(str); // set to beginning + + if (d.isValid()) { + d = d.startOf(unit); + } + + Object.defineProperty(this, 'd', { + enumerable: false, + writable: true, + value: d + }); + } // make a new one + + + _createClass(Unit, [{ + key: "clone", + value: function clone() { + var d = new Unit(this.str); + d.unit = this.unit; + return d; + } + }, { + key: "applyShift", + value: function applyShift(obj) { + var _this = this; + + Object.keys(obj).forEach(function (k) { + _this.d = _this.d.add(obj[k], k); + }); + return this; + } + }, { + key: "applyTime", + value: function applyTime(str) { + if (str) { + this.d = this.d.time(str); + } else { + this.d = this.d.startOf('day'); //zero-out time + } + + return this; + } + }, { + key: "format", + value: function format(fmt) { + return this.d.format(fmt); + } + }, { + key: "start", + value: function start() { + this.d = this.d.startOf(this.unit); + return this; + } + }, { + key: "end", + value: function end() { + this.d = this.d.endOf(this.unit); + return this; + } // 'before 2019' + + }, { + key: "before", + value: function before() { + this.d = require$$0.now(); // ??? + + return this; + } // 'after 2019' + + }, { + key: "after", + value: function after() { + this.d = this.d.add(1, this.unit); + this.d = this.d.startOf(this.unit); + return this; + } // tricky: 'next june' 'next tuesday' + + }, { + key: "next", + value: function next() { + this.d = this.d.add(1, this.unit); + this.d = this.d.startOf(this.unit); + return this; + } // tricky: 'last june' 'last tuesday' + + }, { + key: "last", + value: function last() { + this.d = this.d.minus(1, this.unit); + this.d = this.d.startOf(this.unit); + return this; + } + }]); + + return Unit; +}(); + +var Unit_1 = Unit; + +var Day = +/*#__PURE__*/ +function (_Unit) { + _inherits(Day, _Unit); + + function Day(str, unit) { + var _this; + + _classCallCheck(this, Day); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Day).call(this, str, unit)); + _this.unit = 'day'; + return _this; + } + + return Day; +}(Unit_1); + +var Month = +/*#__PURE__*/ +function (_Unit2) { + _inherits(Month, _Unit2); + + function Month(str, unit) { + var _this2; + + _classCallCheck(this, Month); + + _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Month).call(this, str, unit)); + _this2.unit = 'month'; + return _this2; + } + + return Month; +}(Unit_1); + +var Quarter = +/*#__PURE__*/ +function (_Unit3) { + _inherits(Quarter, _Unit3); + + function Quarter(str, unit) { + var _this3; + + _classCallCheck(this, Quarter); + + _this3 = _possibleConstructorReturn(this, _getPrototypeOf(Quarter).call(this, str, unit)); + _this3.unit = 'quarter'; + return _this3; + } + + return Quarter; +}(Unit_1); + +var Year = +/*#__PURE__*/ +function (_Unit4) { + _inherits(Year, _Unit4); + + function Year(str, unit) { + var _this4; + + _classCallCheck(this, Year); + + _this4 = _possibleConstructorReturn(this, _getPrototypeOf(Year).call(this, str, unit)); + _this4.unit = 'year'; + return _this4; + } + + return Year; +}(Unit_1); + +var WeekDay = +/*#__PURE__*/ +function (_Unit5) { + _inherits(WeekDay, _Unit5); + + function WeekDay(str, unit) { + var _this5; + + _classCallCheck(this, WeekDay); + + _this5 = _possibleConstructorReturn(this, _getPrototypeOf(WeekDay).call(this, str, unit)); + _this5.unit = 'week'; + _this5.d = _this5.d.day(str); //assume a wednesday in the future + + if (_this5.d.date() < require$$0.now().date()) { + _this5.d = _this5.d.add(7, 'days'); + } + + return _this5; + } + + _createClass(WeekDay, [{ + key: "next", + value: function next() { + this.d = this.d.add(7, 'days'); + this.d = this.d.day(this.str); + return this; + } + }, { + key: "last", + value: function last() { + this.d = this.d.minus(7, 'days'); + this.d = this.d.day(this.str); + return this; + } + }]); + + return WeekDay; +}(Unit_1); // like 'feb 2' + + +var CalendarDate = +/*#__PURE__*/ +function (_Unit6) { + _inherits(CalendarDate, _Unit6); + + function CalendarDate(str, unit) { + var _this6; + + _classCallCheck(this, CalendarDate); + + _this6 = _possibleConstructorReturn(this, _getPrototypeOf(CalendarDate).call(this, str, unit)); + _this6.unit = 'day'; + return _this6; + } + + _createClass(CalendarDate, [{ + key: "next", + value: function next() { + this.d = this.d.add(1, 'year'); + return this; + } + }, { + key: "last", + value: function last() { + this.d = this.d.minus(1, 'year'); + return this; + } + }]); + + return CalendarDate; +}(Unit_1); + +var units$4 = { + Unit: Unit_1, + Day: Day, + Month: Month, + Quarter: Quarter, + Year: Year, + WeekDay: WeekDay, + CalendarDate: CalendarDate +}; + +var mapping$1 = { + week: units$4.Week, + month: units$4.Month, + quarter: units$4.Quarter, + year: units$4.Year, + season: units$4.Season +}; // when a unit of time is spoken of as 'this month' - instead of 'february' + +var namedUnit = function namedUnit(doc) { + //this month, last quarter, next year + var m = doc.match('(weekday|week|month|quarter|season|year)'); + + if (m.found === true) { + var str = m.lastTerm().text('reduced'); + + if (mapping$1.hasOwnProperty(str)) { + var Model = mapping$1[str]; + + if (!Model) { + return null; + } + + var unit = new Model(null, str); + return unit; + } + } //try this version - 'next friday, last thursday' + + + m = doc.match('(monday|tuesday|wednesday|thursday|friday|saturday|sunday)'); + + if (m.found === true) { + var _str = m.lastTerm().text('reduced'); + + var _unit = new units$4.WeekDay(_str); + + return _unit; + } + + return null; +}; + +var _01NamedUnit = namedUnit; + +var spacetimeHoliday = createCommonjsModule$1(function (module, exports) { + (function (global, factory) { + module.exports = factory(require$$0) ; + })(commonjsGlobal, function (spacetime) { + + spacetime = spacetime && spacetime.hasOwnProperty('default') ? spacetime['default'] : spacetime; //yep, + + var jan = 'january'; + var feb = 'february'; + var mar = 'march'; + var apr = 'april'; + var may = 'may'; + var jun = 'june'; + var jul = 'july'; + var aug = 'august'; + var sep = 'september'; + var oct = 'october'; + var nov = 'november'; + var dec = 'december'; + var fixedHolidays = { + 'new years eve': [dec, 31], + 'new years': [jan, 1], + 'new years day': [jan, 1], + 'inauguration day': [jan, 20], + 'australia day': [jan, 26], + 'national freedom day': [feb, 1], + 'groundhog day': [feb, 2], + 'rosa parks day': [feb, 4], + 'valentines day': [feb, 14], + 'saint valentines day': [feb, 14], + 'st valentines day ': [feb, 14], + 'saint patricks day': [mar, 17], + 'st patricks day': [mar, 17], + 'april fools': [apr, 1], + 'april fools day': [apr, 1], + 'emancipation day': [apr, 16], + 'tax day': [apr, 15], + //US + 'labour day': [may, 1], + 'cinco de mayo': [may, 5], + 'national nurses day': [may, 6], + 'harvey milk day': [may, 22], + 'victoria day': [may, 24], + juneteenth: [jun, 19], + 'canada day': [jul, 1], + 'independence day': [jul, 4], + 'independents day': [jul, 4], + 'bastille day': [jul, 14], + 'purple heart day': [aug, 7], + 'womens equality day': [aug, 26], + '16 de septiembre': [sep, 16], + 'dieciseis de septiembre': [sep, 16], + 'grito de dolores': [sep, 16], + halloween: [oct, 31], + 'all hallows eve': [oct, 31], + 'day of the dead': [oct, 31], + // Ranged holiday [nov, 2], + 'dia de muertos': [oct, 31], + // Ranged holiday [nov, 2], + 'veterans day': [nov, 11], + 'st andrews day': [nov, 30], + 'saint andrews day': [nov, 30], + 'all saints day': [nov, 1], + 'all sts day': [nov, 1], + 'armistice day': [nov, 11], + 'rememberance day': [nov, 11], + 'christmas eve': [dec, 24], + christmas: [dec, 25], + xmas: [dec, 25], + 'boxing day': [dec, 26], + 'st stephens day': [dec, 26], + 'saint stephens day': [dec, 26], + // Fixed religious and cultural holidays + // Catholic + Christian + epiphany: [jan, 6], + 'orthodox christmas day': [jan, 7], + 'orthodox new year': [jan, 14], + 'assumption of mary': [aug, 15], + 'all souls day': [nov, 2], + 'feast of the immaculate conception': [dec, 8], + 'feast of our lady of guadalupe': [dec, 12], + // Kwanzaa + kwanzaa: [dec, 26], + // Ranged holiday [jan, 1], + // Pagan / metal 🤘 + imbolc: [feb, 2], + beltaine: [may, 1], + lughnassadh: [aug, 1], + samhain: [oct, 31] + }; + + var fixedDates = function fixedDates(str, normal, year) { + if (fixedHolidays.hasOwnProperty(str) || fixedHolidays.hasOwnProperty(normal)) { + var arr = fixedHolidays[str] || fixedHolidays[normal] || []; + var s = spacetime.now(); + s = s.year(year); + s = s.startOf('year'); + s = s.month(arr[0]); + s = s.date(arr[1]); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _01FixedDates = fixedDates; //these are holidays on the 'nth weekday of month' + + var jan$1 = 'january'; + var feb$1 = 'february'; + var mar$1 = 'march'; // const apr = 'april' + + var may$1 = 'may'; + var jun$1 = 'june'; // const jul = 'july' + // const aug = 'august' + + var sep$1 = 'september'; + var oct$1 = 'october'; + var nov$1 = 'november'; // const dec = 'december' + + var mon = 'monday'; // const tues = 'tuesday' + // const wed = 'wednesday' + + var thurs = 'thursday'; + var fri = 'friday'; // const sat = 'saturday' + + var sun = 'sunday'; + var holidays = { + 'martin luther king day': [3, mon, jan$1], + //[third monday in january], + 'presidents day': [3, mon, feb$1], + //[third monday in february], + 'commonwealth day': [2, mon, mar$1], + //[second monday in march], + 'mothers day': [2, sun, may$1], + //[second Sunday in May], + 'fathers day': [3, sun, jun$1], + //[third Sunday in June], + 'labor day': [1, mon, sep$1], + //[first monday in september], + 'columbus day': [2, mon, oct$1], + //[second monday in october], + 'canadian thanksgiving': [2, mon, oct$1], + //[second monday in october], + thanksgiving: [4, thurs, nov$1], + // [fourth Thursday in November], + 'black friday': [4, fri, nov$1] //[fourth friday in november], + // 'memorial day': [may], //[last monday in may], + // 'us election': [nov], // [Tuesday following the first Monday in November], + // 'cyber monday': [nov] + // 'advent': [] // fourth Sunday before Christmas + + }; // add aliases + + holidays['turday day'] = holidays.thanksgiving; + holidays['indigenous peoples day'] = holidays['columbus day']; + holidays['mlk day'] = holidays['martin luther king day']; + var calendarHolidays = holidays; + + var fixedDates$1 = function fixedDates(str, normal, year) { + if (calendarHolidays.hasOwnProperty(str) || calendarHolidays.hasOwnProperty(normal)) { + var arr = calendarHolidays[str] || calendarHolidays[normal] || []; + var s = spacetime.now(); + s = s.year(year); // [3rd, 'monday', 'january'] + + s = s.month(arr[2]); + s = s.startOf('month'); // make it january + + var month = s.month(); // make it the 1st monday + + s = s.day(arr[1]); + + if (s.month() !== month) { + s = s.add(1, 'week'); + } // make it nth monday + + + if (arr[0] > 1) { + s = s.add(arr[0] - 1, 'week'); + } + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _02NthWeekday = fixedDates$1; // https://www.timeanddate.com/calendar/determining-easter-date.html + + var dates = { + easter: 0, + 'ash wednesday': -46, + // (46 days before easter) + 'palm sunday': 7, + // (1 week before easter) + 'maundy thursday': -3, + // (3 days before easter) + 'good friday': -2, + // (2 days before easter) + 'holy saturday': -1, + // (1 days before easter) + 'easter saturday': -1, + // (1 day before easter) + 'easter monday': 1, + // (1 day after easter) + 'ascension day': 39, + // (39 days after easter) + 'whit sunday': 49, + // / pentecost (49 days after easter) + 'whit monday': 50, + // (50 days after easter) + 'trinity sunday': 65, + // (56 days after easter) + 'corpus christi': 60, + // (60 days after easter) + 'mardi gras': -47 //(47 days before easter) + + }; + dates['easter sunday'] = dates.easter; + dates['pentecost'] = dates['whit sunday']; + dates['whitsun'] = dates['whit sunday']; + var easterHolidays = dates; // by John Dyer + // based on the algorithm by Oudin (1940) from http://www.tondering.dk/claus/cal/easter.php + + var calcEaster = function calcEaster(year) { + var f = Math.floor, + // Golden Number - 1 + G = year % 19, + C = f(year / 100), + // related to Epact + H = (C - f(C / 4) - f((8 * C + 13) / 25) + 19 * G + 15) % 30, + // number of days from 21 March to the Paschal full moon + I = H - f(H / 28) * (1 - f(29 / (H + 1)) * f((21 - G) / 11)), + // weekday for the Paschal full moon + J = (year + f(year / 4) + I + 2 - C + f(C / 4)) % 7, + // number of days from 21 March to the Sunday on or before the Paschal full moon + L = I - J, + month = 3 + f((L + 40) / 44), + date = L + 28 - 31 * f(month / 4); + month = month === 4 ? 'April' : 'March'; + return month + ' ' + date; + }; + + var calcEaster_1 = calcEaster; + + var easterDates = function easterDates(str, normal, year) { + if (easterHolidays.hasOwnProperty(str) || easterHolidays.hasOwnProperty(normal)) { + var days = easterHolidays[str] || easterHolidays[normal] || []; + var date = calcEaster_1(year); + + if (!date) { + return null; //no easter for this year + } + + var e = spacetime(date); + e = e.year(year); + var s = e.add(days, 'day'); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _03EasterDates = easterDates; // http://www.astropixels.com/ephemeris/soleq2001.html + // years 2000-2100 + + var exceptions = { + spring: [2003, 2007, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 2072, 2076, 2077, 2080, 2081, 2084, 2085, 2088, 2089, 2092, 2093, 2096, 2097], + summer: [2021, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2041, 2044, 2045, 2048, 2049, 2052, 2053, 2056, 2057, 2060, 2061, 2064, 2065, 2068, 2069, 2070, 2072, 2073, 2074, 2076, 2077, 2078, 2080, 2081, 2082, 2084, 2085, 2086, 2088, 2089, 2090, 2092, 2093, 2094, 2096, 2097, 2098, 2099], + fall: [2002, 2003, 2004, 2006, 2007, 2010, 2011, 2014, 2015, 2018, 2019, 2022, 2023, 2026, 2027, 2031, 2035, 2039, 2043, 2047, 2051, 2055, 2059, 2092, 2096], + winter: [2002, 2003, 2006, 2007, 2011, 2015, 2019, 2023, 2027, 2031, 2035, 2039, 2043, 2080, 2084, 2088, 2092, 2096] + }; + var winter20th = [2080, 2084, 2088, 2092, 2096]; + + var calcSeasons = function calcSeasons(year) { + // most common defaults + var res = { + spring: 'March 20 ' + year, + summer: 'June 21 ' + year, + fall: 'Sept 22 ' + year, + winter: 'Dec 21 ' + year + }; + + if (exceptions.spring.indexOf(year) !== -1) { + res.spring = 'March 19 ' + year; + } + + if (exceptions.summer.indexOf(year) !== -1) { + res.summer = 'June 20 ' + year; + } + + if (exceptions.fall.indexOf(year) !== -1) { + res.fall = 'Sept 21 ' + year; + } // winter can be 20th, 21st, or 22nd + + + if (exceptions.winter.indexOf(year) !== -1) { + res.winter = 'Dec 22 ' + year; + } + + if (winter20th.indexOf(year) !== -1) { + res.winter = 'Dec 20 ' + year; + } + + return res; + }; + + var seasons = calcSeasons; // these are properly calculated in ./lib/seasons + + var dates$1 = { + 'spring equinox': 'spring', + 'summer solistice': 'summer', + 'fall equinox': 'fall', + 'winter solstice': 'winter' + }; // aliases + + dates$1['march equinox'] = dates$1['spring equinox']; + dates$1['vernal equinox'] = dates$1['spring equinox']; + dates$1['ostara'] = dates$1['spring equinox']; + dates$1['june solstice'] = dates$1['summer solistice']; + dates$1['litha'] = dates$1['summer solistice']; + dates$1['autumn equinox'] = dates$1['fall equinox']; + dates$1['autumnal equinox'] = dates$1['fall equinox']; + dates$1['september equinox'] = dates$1['fall equinox']; + dates$1['sept equinox'] = dates$1['fall equinox']; + dates$1['mabon'] = dates$1['fall equinox']; + dates$1['december solstice'] = dates$1['winter solistice']; + dates$1['dec solstice'] = dates$1['winter solistice']; + dates$1['yule'] = dates$1['winter solistice']; + var astroHolidays = dates$1; + + var astroDates = function astroDates(str, normal, year) { + if (astroHolidays.hasOwnProperty(str) || astroHolidays.hasOwnProperty(normal)) { + var season = astroHolidays[str] || astroHolidays[normal]; + var seasons$1 = seasons(year); + + if (!season || !seasons$1 || !seasons$1[season]) { + return null; // couldn't figure it out + } + + var s = spacetime(seasons$1[season]); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _04Astronomical = astroDates; + var dates$2 = { + // Muslim holidays + 'isra and miraj': 'april 13', + 'lailat al-qadr': 'june 10', + 'eid al-fitr': 'june 15', + 'id al-Fitr': 'june 15', + 'eid ul-Fitr': 'june 15', + ramadan: 'may 16', + // Range holiday + 'eid al-adha': 'sep 22', + muharram: 'sep 12', + 'prophets birthday': 'nov 21' + }; + var lunarHolidays = dates$2; + var dayDiff = -10.64; + + var lunarDates = function lunarDates(str, normal, year) { + if (lunarHolidays.hasOwnProperty(str) || lunarHolidays.hasOwnProperty(normal)) { + var date = lunarHolidays[str] || lunarHolidays[normal] || []; + + if (!date) { + return null; + } // start at 2018 + + + var s = spacetime(date + ' 2018'); + var diff = year - 2018; + var toAdd = diff * dayDiff; + s = s.add(toAdd, 'day'); + s = s.startOf('day'); // now set the correct year + + s = s.year(year); + + if (s.isValid()) { + return s; + } + } + + return null; + }; + + var _05LunarDates = lunarDates; + var nowYear = spacetime.now().year(); + + var spacetimeHoliday = function spacetimeHoliday(str, year) { + year = year || nowYear; + str = str || ''; + str = String(str); + str = str.trim().toLowerCase(); + str = str.replace(/'s/, 's'); // 'mother's day' + + var normal = str.replace(/ day$/, ''); + normal = normal.replace(/^the /, ''); + normal = normal.replace(/^orthodox /, ''); //orthodox good friday + // try easier, unmoving holidays + + var s = _01FixedDates(str, normal, year); + + if (s !== null) { + return s; + } // try 'nth monday' holidays + + + s = _02NthWeekday(str, normal, year); + + if (s !== null) { + return s; + } // easter-based holidays + + + s = _03EasterDates(str, normal, year); + + if (s !== null) { + return s; + } // solar-based holidays + + + s = _04Astronomical(str, normal, year); + + if (s !== null) { + return s; + } // mostly muslim holidays + + + s = _05LunarDates(str, normal, year); + + if (s !== null) { + return s; + } + + return null; + }; + + var src = spacetimeHoliday; + return src; + }); +}); + +var parseHoliday = function parseHoliday(doc) { + var d = null; + var str = doc.match('#Holiday+').text('reduced'); + var year = 2020; //change me! + + var s = spacetimeHoliday(str, year); + + if (s !== null) { + d = new units$4.CalendarDate(s); + } + + return d; +}; + +var _02Holidays = parseHoliday; + +var Unit$1 = units$4.Unit; // parse things like 'june 5th 2019' + +var parseExplicit = function parseExplicit(doc) { + if (doc.has('#Number of #Month')) ; + + var str = doc.text('reduced'); // spacetime does the heavy-lifting + + var d = new Unit$1(str); // did we find a date? + + if (d.d.isValid() === false) { + return null; + } + + return d; +}; + +var _03Explicit = parseExplicit; + +var Unit$2 = units$4.Unit; + +var parseDate = function parseDate(doc) { + var shift = _01Shift(doc); + var time = _02Time(doc); + var rel = _03Relative(doc); + var d = null; // let str = doc.text('reduced') + // console.log(str, ' - ', rel, ' - ', shift, ' - ', time) + // do we have just a time? + + if (doc.found === false && time !== null) { + d = new Unit$2(); // choose today + } // this month + + + d = d || _01NamedUnit(doc); // this haloween + + d = d || _02Holidays(doc); // this june 2nd + + d = d || _03Explicit(doc); + + if (!d) { + return null; + } // // apply relative + + + if (rel === 'last') { + d.last(); + } + + if (rel === 'next') { + d.next(); + } // apply shift + + + if (shift) { + d.applyShift(shift); + } // apply time + + + d.applyTime(time); + return d; +}; + +var toDate = parseDate; + +var logic = function logic(doc, context) { + // two explicit dates - 'between friday and sunday' + var m = doc.match('between * and *'); + + if (m.found) { + var start = m.match('between [.*] and').not('^between').not('and$'); + start = toDate(start); + var end = m.match('and *').not('^and'); + end = toDate(end); + + if (start) { + return { + start: start, + end: end + }; + } + } // two months, one year - 'june 5 to june 7 1998' + + + m = doc.match('#Month #Value to #Month #Value of? #Year'); + + if (m.found) ; // two months, no year - 'june 5 to june 7' + + + m = doc.match('#Month #Value to #Month #Value'); + + if (m.found) ; // one month, one year, first form - 'january 5 to 7 1998' + + + m = doc.match('#Month #Value to #Value of? #Year'); + + if (m.found) ; // one month, one year, second form - '5 to 7 of january 1998' + + + m = doc.match('#Value to #Value of? #Month of? #Year'); + + if (m.found) ; // one month, no year - '5 to 7 of january' + + + m = doc.match('#Value to #Value of? #Month'); + + if (m.found) ; // one month, no year - 'january 5 to 7' + + + m = doc.match('#Month #Value to #Value'); + + if (m.found) ; // 'from A to B' + + + m = doc.match('from? * (to|@hasHyphen|until|upto) [*]'); + + if (m.found) ; // 'before june' + + + m = doc.match('^due (by|before|on|in)? [*]'); + + if (m.found) ; // 'after june' + + + m = doc.match('^(after|following|from) [*]'); + + if (m.found) ; // 'in june' + + + m = doc.match('^(on|during|in) [*]'); + + if (m.found) { + var _d = toDate(m); + + if (_d) { + return { + start: _d, + end: _d.clone().end() + }; + } + } //else, try whole thing + + + var d = toDate(doc); + return { + start: d, + end: null + }; +}; + +var _02Ranges = logic; + +var parse = function parse(doc, context) { + doc = _01Normalize(doc); + return _02Ranges(doc); +}; + +var parse_1 = parse; + +var arr = [['mon', 'monday'], ['tue', 'tuesday'], ['tues', 'tuesday'], ['wed', 'wednesday'], ['thu', 'thursday'], ['thurs', 'thursday'], ['fri', 'friday'], ['sat', 'saturday'], ['sun', 'sunday'], ['jan', 'january'], ['feb', 'february'], ['mar', 'march'], ['apr', 'april'], ['jun', 'june'], ['jul', 'july'], ['aug', 'august'], ['sep', 'september'], ['sept', 'september'], ['oct', 'october'], ['nov', 'november'], ['dec', 'december']]; +arr = arr.map(function (a) { + return { + "short": a[0], + "long": a[1] + }; +}); +var abbrevs = arr; + +var addMethods$5 = function addMethods(Doc, world) { + // our new tags + world.addTags(tags); // add info for the date plugin + + world.addWords(words); // run our tagger + + world.postProcess(tagger); + /** */ + + var Dates = + /*#__PURE__*/ + function (_Doc) { + _inherits(Dates, _Doc); + + function Dates(list, from, w) { + var _this; + + _classCallCheck(this, Dates); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Dates).call(this, list, from, w)); + _this.context = {}; + return _this; + } + /** overload the original json with noun information */ + + + _createClass(Dates, [{ + key: "json", + value: function json(options) { + var _this2 = this; + + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + terms: false + }; + var res = []; + var format = options.format || 'iso'; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var obj = parse_1(doc, _this2.context); + var start = obj.start ? obj.start.format(format) : null; + var end = obj.end ? obj.end.format(format) : null; // set iso strings to json result + + json.date = { + start: start, + end: end + }; // add duration + + if (start && end) { + json.date.duration = obj.start.d.diff(obj.end.d); // we don't need these + + delete json.date.duration.milliseconds; + delete json.date.duration.seconds; + } + + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + } + /** render all dates according to a specific format */ + + }, { + key: "format", + value: function format(fmt) { + var _this3 = this; + + this.forEach(function (doc) { + var obj = parse_1(doc, _this3.context); + var str = ''; + + if (obj.start) { + str = obj.start.format(fmt); + + if (obj.end) { + str += ' to ' + obj.start.format(fmt); + } + + doc.replaceWith(str, true); + } + }); + return this; + } + /** replace 'Fri' with 'Friday', etc*/ + + }, { + key: "toLongForm", + value: function toLongForm() { + var _this4 = this; + + abbrevs.forEach(function (a) { + _this4.replace(a["short"], a["long"], true, true); + }); + return this; + } + /** replace 'Friday' with 'Fri', etc*/ + + }, { + key: "toShortForm", + value: function toShortForm() { + var _this5 = this; + + abbrevs.forEach(function (a) { + _this5.replace(a["long"], a["short"], true, true); + }); + return this; + } + }]); + + return Dates; + }(Doc); + + Doc.prototype.dates = function (n) { + var context = {}; + + if (n && _typeof(n) === 'object') { + context = n; + n = null; + } + + var r = this.clauses(); + var dates = r.match('#Date+'); + + if (typeof n === 'number') { + dates = dates.get(n); + } + + if (typeof n === 'number') { + dates = dates.get(n); + } + + var d = new Dates(dates.list, this, this.world); + d.context = context; + return d; + }; +}; + +var src$1 = addMethods$5; + +export default src$1; diff --git a/plugins/dates/package-lock.json b/plugins/dates/package-lock.json new file mode 100644 index 000000000..eedf4c857 --- /dev/null +++ b/plugins/dates/package-lock.json @@ -0,0 +1,679 @@ +{ + "name": "compromise-dates", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz", + "integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "@types/node": { + "version": "12.7.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", + "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "commander": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz", + "integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" + }, + "is-reference": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", + "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "magic-string": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz", + "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==", + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=" + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==" + }, + "spacetime": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/spacetime/-/spacetime-6.3.0.tgz", + "integrity": "sha512-zOZJgt49OxFjsyX0vEUwIxKJH55lQ03n94qzqLa0miSacGIyaTTrbMEbsYyVYi9B7yBc0wcV/QhLVx791mfpEA==" + }, + "spacetime-holiday": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spacetime-holiday/-/spacetime-holiday-0.0.2.tgz", + "integrity": "sha512-1OK3LQvKf/xTk5BGKXwwxASiSRBkf6OodYm8Uh2pX3BKegrL9IVSgOYbAgl5xlqW2CCCsD7h1KHkXVwgbUzqRQ==" + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.8.tgz", + "integrity": "sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } +} diff --git a/plugins/dates/package.json b/plugins/dates/package.json new file mode 100644 index 000000000..47898d97c --- /dev/null +++ b/plugins/dates/package.json @@ -0,0 +1,50 @@ +{ + "name": "compromise-dates", + "description": "plugin for nlp-compromise", + "version": "0.0.2", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-dates.js", + "unpkg": "./builds/compromise-dates.min.js", + "module": "./builds/compromise-dates.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 120 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*", + "compromise-numbers": "latest" + }, + "dependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "spacetime": "6.3.0", + "spacetime-holiday": "0.0.2", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "devDependencies": {}, + "license": "MIT" +} diff --git a/plugins/dates/rollup.config.js b/plugins/dates/rollup.config.js new file mode 100644 index 000000000..880a05275 --- /dev/null +++ b/plugins/dates/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-dates' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseDates', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseDates', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/dates/src/abbrevs.js b/plugins/dates/src/abbrevs.js new file mode 100644 index 000000000..efd7adbcc --- /dev/null +++ b/plugins/dates/src/abbrevs.js @@ -0,0 +1,30 @@ +let arr = [ + ['mon', 'monday'], + ['tue', 'tuesday'], + ['tues', 'tuesday'], + ['wed', 'wednesday'], + ['thu', 'thursday'], + ['thurs', 'thursday'], + ['fri', 'friday'], + ['sat', 'saturday'], + ['sun', 'sunday'], + + ['jan', 'january'], + ['feb', 'february'], + ['mar', 'march'], + ['apr', 'april'], + ['jun', 'june'], + ['jul', 'july'], + ['aug', 'august'], + ['sep', 'september'], + ['sept', 'september'], + ['oct', 'october'], + ['nov', 'november'], + ['dec', 'december'], +] + +arr = arr.map(a => { + return { short: a[0], long: a[1] } +}) + +module.exports = arr diff --git a/plugins/dates/src/index.js b/plugins/dates/src/index.js new file mode 100644 index 000000000..c43305cd6 --- /dev/null +++ b/plugins/dates/src/index.js @@ -0,0 +1,107 @@ +const tagger = require('./tagger') +const tags = require('./tags') +const words = require('./words') +const parse = require('./parse') +const abbrevs = require('./abbrevs') + +const addMethods = function(Doc, world) { + // our new tags + world.addTags(tags) + // add info for the date plugin + world.addWords(words) + // run our tagger + world.postProcess(tagger) + + /** */ + class Dates extends Doc { + constructor(list, from, w) { + super(list, from, w) + this.context = {} + } + /** overload the original json with noun information */ + json(options) { + let n = null + if (typeof options === 'number') { + n = options + options = null + } + options = options || { terms: false } + let res = [] + let format = options.format || 'iso' + this.forEach(doc => { + let json = doc.json(options)[0] + let obj = parse(doc, this.context) + let start = obj.start ? obj.start.format(format) : null + let end = obj.end ? obj.end.format(format) : null + // set iso strings to json result + json.date = { + start: start, + end: end, + } + // add duration + if (start && end) { + json.date.duration = obj.start.d.diff(obj.end.d) + // we don't need these + delete json.date.duration.milliseconds + delete json.date.duration.seconds + } + res.push(json) + }) + if (n !== null) { + return res[n] + } + return res + } + + /** render all dates according to a specific format */ + format(fmt) { + this.forEach(doc => { + let obj = parse(doc, this.context) + let str = '' + if (obj.start) { + str = obj.start.format(fmt) + if (obj.end) { + str += ' to ' + obj.start.format(fmt) + } + doc.replaceWith(str, true) + } + }) + return this + } + /** replace 'Fri' with 'Friday', etc*/ + toLongForm() { + abbrevs.forEach(a => { + this.replace(a.short, a.long, true, true) + }) + return this + } + /** replace 'Friday' with 'Fri', etc*/ + toShortForm() { + abbrevs.forEach(a => { + this.replace(a.long, a.short, true, true) + }) + return this + } + } + + Doc.prototype.dates = function(n) { + let context = {} + if (n && typeof n === 'object') { + context = n + n = null + } + let r = this.clauses() + let dates = r.match('#Date+') + if (typeof n === 'number') { + dates = dates.get(n) + } + if (typeof n === 'number') { + dates = dates.get(n) + } + let d = new Dates(dates.list, this, this.world) + d.context = context + return d + } +} + +module.exports = addMethods diff --git a/plugins/dates/src/parse/01-normalize.js b/plugins/dates/src/parse/01-normalize.js new file mode 100644 index 000000000..dac7f0d09 --- /dev/null +++ b/plugins/dates/src/parse/01-normalize.js @@ -0,0 +1,16 @@ +const normalize = function(doc) { + doc = doc.clone() + + if (!doc.numbers) { + console.warn("Compromise: compromise-dates cannot find plugin dependency 'compromise-number'") + } else { + // convert 'two' to 2 + let num = doc.numbers() + num.toNumber() + num.toCardinal() + } + // remove adverbs + doc.adverbs().remove() + return doc +} +module.exports = normalize diff --git a/plugins/dates/src/parse/02-ranges.js b/plugins/dates/src/parse/02-ranges.js new file mode 100644 index 000000000..83b2964d7 --- /dev/null +++ b/plugins/dates/src/parse/02-ranges.js @@ -0,0 +1,76 @@ +const parseDate = require('./toDate') + +// +const logic = function(doc, context) { + // two explicit dates - 'between friday and sunday' + let m = doc.match('between * and *') + if (m.found) { + let start = m + .match('between [.*] and') + .not('^between') + .not('and$') + start = parseDate(start, context) + let end = m.match('and *').not('^and') + end = parseDate(end, context) + if (start) { + return { + start: start, + end: end, + } + } + } + // two months, one year - 'june 5 to june 7 1998' + m = doc.match('#Month #Value to #Month #Value of? #Year') + if (m.found) { + } + // two months, no year - 'june 5 to june 7' + m = doc.match('#Month #Value to #Month #Value') + if (m.found) { + } + // one month, one year, first form - 'january 5 to 7 1998' + m = doc.match('#Month #Value to #Value of? #Year') + if (m.found) { + } + // one month, one year, second form - '5 to 7 of january 1998' + m = doc.match('#Value to #Value of? #Month of? #Year') + if (m.found) { + } + // one month, no year - '5 to 7 of january' + m = doc.match('#Value to #Value of? #Month') + if (m.found) { + } + // one month, no year - 'january 5 to 7' + m = doc.match('#Month #Value to #Value') + if (m.found) { + } + // 'from A to B' + m = doc.match('from? * (to|@hasHyphen|until|upto) [*]') + if (m.found) { + } + // 'before june' + m = doc.match('^due (by|before|on|in)? [*]') + if (m.found) { + } + // 'after june' + m = doc.match('^(after|following|from) [*]') + if (m.found) { + } + // 'in june' + m = doc.match('^(on|during|in) [*]') + if (m.found) { + let d = parseDate(m, context) + if (d) { + return { + start: d, + end: d.clone().end(), + } + } + } + //else, try whole thing + let d = parseDate(doc, context) + return { + start: d, + end: null, + } +} +module.exports = logic diff --git a/plugins/dates/src/parse/index.js b/plugins/dates/src/parse/index.js new file mode 100644 index 000000000..b233095f9 --- /dev/null +++ b/plugins/dates/src/parse/index.js @@ -0,0 +1,8 @@ +const normalize = require('./01-normalize') +const parseRanges = require('./02-ranges') + +const parse = function(doc, context) { + doc = normalize(doc) + return parseRanges(doc, context) +} +module.exports = parse diff --git a/plugins/dates/src/parse/toDate/01-namedUnit.js b/plugins/dates/src/parse/toDate/01-namedUnit.js new file mode 100644 index 000000000..83e1ad233 --- /dev/null +++ b/plugins/dates/src/parse/toDate/01-namedUnit.js @@ -0,0 +1,35 @@ +const units = require('./units') +const mapping = { + week: units.Week, + month: units.Month, + quarter: units.Quarter, + year: units.Year, + season: units.Season, +} + +// when a unit of time is spoken of as 'this month' - instead of 'february' +const namedUnit = function(doc) { + //this month, last quarter, next year + let m = doc.match('(weekday|week|month|quarter|season|year)') + if (m.found === true) { + let str = m.lastTerm().text('reduced') + if (mapping.hasOwnProperty(str)) { + let Model = mapping[str] + if (!Model) { + return null + } + let unit = new Model(null, str) + return unit + } + } + + //try this version - 'next friday, last thursday' + m = doc.match('(monday|tuesday|wednesday|thursday|friday|saturday|sunday)') + if (m.found === true) { + let str = m.lastTerm().text('reduced') + let unit = new units.WeekDay(str) + return unit + } + return null +} +module.exports = namedUnit diff --git a/plugins/dates/src/parse/toDate/02-holidays.js b/plugins/dates/src/parse/toDate/02-holidays.js new file mode 100644 index 000000000..b318f8fe6 --- /dev/null +++ b/plugins/dates/src/parse/toDate/02-holidays.js @@ -0,0 +1,14 @@ +const units = require('./units') +const spacetimeHoliday = require('spacetime-holiday') + +const parseHoliday = function(doc) { + let d = null + let str = doc.match('#Holiday+').text('reduced') + let year = 2020 //change me! + let s = spacetimeHoliday(str, year) + if (s !== null) { + d = new units.CalendarDate(s) + } + return d +} +module.exports = parseHoliday diff --git a/plugins/dates/src/parse/toDate/03-explicit.js b/plugins/dates/src/parse/toDate/03-explicit.js new file mode 100644 index 000000000..07a314a06 --- /dev/null +++ b/plugins/dates/src/parse/toDate/03-explicit.js @@ -0,0 +1,17 @@ +const { Unit } = require('./units') + +// parse things like 'june 5th 2019' +const parseExplicit = function(doc) { + if (doc.has('#Number of #Month')) { + } + + let str = doc.text('reduced') + // spacetime does the heavy-lifting + let d = new Unit(str) + // did we find a date? + if (d.d.isValid() === false) { + return null + } + return d +} +module.exports = parseExplicit diff --git a/plugins/dates/src/parse/toDate/index.js b/plugins/dates/src/parse/toDate/index.js new file mode 100644 index 000000000..4cfc6dfb1 --- /dev/null +++ b/plugins/dates/src/parse/toDate/index.js @@ -0,0 +1,49 @@ +const parseShift = require('./tokenize/01-shift') +const parseTime = require('./tokenize/02-time') +const parseRelative = require('./tokenize/03-relative') +const namedUnit = require('./01-namedUnit') +const parseHoliday = require('./02-holidays') +const explicit = require('./03-explicit') +const { Unit } = require('./units') + +const parseDate = function(doc) { + let shift = parseShift(doc) + let time = parseTime(doc) + let rel = parseRelative(doc) + let d = null + // let str = doc.text('reduced') + // console.log(str, ' - ', rel, ' - ', shift, ' - ', time) + + // do we have just a time? + if (doc.found === false && time !== null) { + d = new Unit() // choose today + } + + // this month + d = d || namedUnit(doc) + // this haloween + d = d || parseHoliday(doc) + // this june 2nd + d = d || explicit(doc) + + if (!d) { + return null + } + + // // apply relative + if (rel === 'last') { + d.last() + } + if (rel === 'next') { + d.next() + } + // apply shift + if (shift) { + d.applyShift(shift) + } + // apply time + d.applyTime(time) + + return d +} +module.exports = parseDate diff --git a/plugins/dates/src/parse/toDate/tokenize/01-shift.js b/plugins/dates/src/parse/toDate/tokenize/01-shift.js new file mode 100644 index 000000000..dabe2801c --- /dev/null +++ b/plugins/dates/src/parse/toDate/tokenize/01-shift.js @@ -0,0 +1,40 @@ +const knownUnits = { + second: true, + minute: true, + hour: true, + day: true, + week: true, + month: true, + season: true, + quarter: true, + year: true, +} + +//turn '5 weeks before' to {weeks:5} +const parseShift = function(doc) { + let result = {} + + let m = doc.match('#DateShift+') + if (m.found === false) { + return result + } + m.match('#Cardinal #Duration').forEach(ts => { + let num = ts.match('#Cardinal').text('normal') + num = parseFloat(num) + if (num && typeof num === 'number') { + let unit = ts.match('#Duration').text('normal') + unit = unit.replace(/s$/, '') + if (unit && knownUnits.hasOwnProperty(unit)) { + result[unit] = num + } + } + }) + //is it 2 weeks before? → -2 + if (m.has('before$') === true) { + Object.keys(result).forEach(k => (result[k] *= -1)) + } + // finally, remove it from our text + doc.remove('#DateShift') + return result +} +module.exports = parseShift diff --git a/plugins/dates/src/parse/toDate/tokenize/02-time.js b/plugins/dates/src/parse/toDate/tokenize/02-time.js new file mode 100644 index 000000000..85dd44549 --- /dev/null +++ b/plugins/dates/src/parse/toDate/tokenize/02-time.js @@ -0,0 +1,64 @@ +const spacetime = require('spacetime') +//hmmm: 'june 5th between 9 and 10am' + +const halfPast = function(m, s) { + let hour = m.match('#Cardinal$').text('reduced') + + let term = m.match('(half|quarter|25|15|10|5)') + let mins = term.text('reduced') + if (term.has('half')) { + mins = '30' + } + if (term.has('quarter')) { + mins = '15' + } + let behind = m.has('to') + // apply it + s = s.hour(hour) + s = s.startOf('hour') + if (behind) { + s = s.subtract(mins, 'minutes') + } else { + s = s.add(mins, 'minutes') + } + return s +} + +const parseTime = function(doc) { + let time = doc.match('(at|by|for|before)? #Time+') + if (time.found) { + doc.remove(time) + } + // get the main part of the time + time = time.not('(at|by|for|before|sharp)') + time = time.not('on the dot') + let s = spacetime.now() + let now = s.clone() + + // '5 oclock' + let m = time.match('^#Cardinal oclock (am|pm)?') + if (m.found) { + m = m.not('oclock') + s = s.hour(m.text('reduced')) + if (s.isValid() && !s.isEqual(now)) { + return s.time() + } + } + + // 'quarter to two' + m = time.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal') + if (m.found) { + s = halfPast(m, s) + if (s.isValid() && !s.isEqual(now)) { + return s.time() + } + } + // parse random a time like '4:54pm' + let str = time.text('reduced') + s = s.time(str) + if (s.isValid() && !s.isEqual(now)) { + return s.time() + } + return null +} +module.exports = parseTime diff --git a/plugins/dates/src/parse/toDate/tokenize/03-relative.js b/plugins/dates/src/parse/toDate/tokenize/03-relative.js new file mode 100644 index 000000000..8f6700b93 --- /dev/null +++ b/plugins/dates/src/parse/toDate/tokenize/03-relative.js @@ -0,0 +1,17 @@ +// interpret 'this halloween' or 'next june' +const parseRelative = function(doc) { + let rel = null + if (doc.has('^this? (next|upcoming)')) { + rel = 'next' + } + if (doc.has('^this? (last|previous)')) { + rel = 'last' + } + if (doc.has('^(this|current)')) { + rel = 'this' + } + // finally, remove it from our text + doc.remove('^(this|current|next|upcoming|last|previous)') + return rel +} +module.exports = parseRelative diff --git a/plugins/dates/src/parse/toDate/units/Unit.js b/plugins/dates/src/parse/toDate/units/Unit.js new file mode 100644 index 000000000..316750aa9 --- /dev/null +++ b/plugins/dates/src/parse/toDate/units/Unit.js @@ -0,0 +1,74 @@ +const spacetime = require('spacetime') + +class Unit { + constructor(str, unit) { + this.str = str + this.unit = unit || 'day' + // set it to the beginning of the given unit + let d = spacetime(str) + // set to beginning + if (d.isValid()) { + d = d.startOf(unit) + } + Object.defineProperty(this, 'd', { + enumerable: false, + writable: true, + value: d, + }) + } + // make a new one + clone() { + let d = new Unit(this.str) + d.unit = this.unit + return d + } + applyShift(obj) { + Object.keys(obj).forEach(k => { + this.d = this.d.add(obj[k], k) + }) + return this + } + applyTime(str) { + if (str) { + this.d = this.d.time(str) + } else { + this.d = this.d.startOf('day') //zero-out time + } + return this + } + format(fmt) { + return this.d.format(fmt) + } + start() { + this.d = this.d.startOf(this.unit) + return this + } + end() { + this.d = this.d.endOf(this.unit) + return this + } + // 'before 2019' + before() { + this.d = spacetime.now() // ??? + return this + } + // 'after 2019' + after() { + this.d = this.d.add(1, this.unit) + this.d = this.d.startOf(this.unit) + return this + } + // tricky: 'next june' 'next tuesday' + next() { + this.d = this.d.add(1, this.unit) + this.d = this.d.startOf(this.unit) + return this + } + // tricky: 'last june' 'last tuesday' + last() { + this.d = this.d.minus(1, this.unit) + this.d = this.d.startOf(this.unit) + return this + } +} +module.exports = Unit diff --git a/plugins/dates/src/parse/toDate/units/index.js b/plugins/dates/src/parse/toDate/units/index.js new file mode 100644 index 000000000..210662d46 --- /dev/null +++ b/plugins/dates/src/parse/toDate/units/index.js @@ -0,0 +1,73 @@ +const spacetime = require('spacetime') +const Unit = require('./Unit') + +class Day extends Unit { + constructor(str, unit) { + super(str, unit) + this.unit = 'day' + } +} +class Month extends Unit { + constructor(str, unit) { + super(str, unit) + this.unit = 'month' + } +} +class Quarter extends Unit { + constructor(str, unit) { + super(str, unit) + this.unit = 'quarter' + } +} +class Year extends Unit { + constructor(str, unit) { + super(str, unit) + this.unit = 'year' + } +} +class WeekDay extends Unit { + constructor(str, unit) { + super(str, unit) + this.unit = 'week' + this.d = this.d.day(str) + //assume a wednesday in the future + if (this.d.date() < spacetime.now().date()) { + this.d = this.d.add(7, 'days') + } + } + next() { + this.d = this.d.add(7, 'days') + this.d = this.d.day(this.str) + return this + } + last() { + this.d = this.d.minus(7, 'days') + this.d = this.d.day(this.str) + return this + } +} +// like 'feb 2' +class CalendarDate extends Unit { + constructor(str, unit) { + super(str, unit) + this.unit = 'day' + } + next() { + this.d = this.d.add(1, 'year') + return this + } + last() { + this.d = this.d.minus(1, 'year') + return this + } +} + +module.exports = { + Unit: Unit, + Day: Day, + Month: Month, + Quarter: Quarter, + Year: Year, + WeekDay: WeekDay, + CalendarDate: CalendarDate, +} diff --git a/plugins/dates/src/tagger/00-basic.js b/plugins/dates/src/tagger/00-basic.js new file mode 100644 index 000000000..4605cf60d --- /dev/null +++ b/plugins/dates/src/tagger/00-basic.js @@ -0,0 +1,182 @@ +//ambiguous 'may' and 'march' +const preps = '(in|by|before|during|on|until|after|of|within|all)' //6 +const thisNext = '(last|next|this|previous|current|upcoming|coming)' //2 +const sections = '(start|end|middle|starting|ending|midpoint|beginning)' //2 +const seasons = '(spring|summer|winter|fall|autumn)' + +//ensure a year is approximately typical for common years +//please change in one thousand years +const tagYear = (m, reason) => { + if (m.found !== true) { + return + } + let term = m.termList()[0] + if (term) { + let num = parseInt(term.clean, 10) + if (num && num > 1000 && num < 3000) { + m.tag('Year', reason) + } + } +} +//same, but for less-confident values +const tagYearSafe = (m, reason) => { + if (m.found !== true) { + return + } + let term = m.termList()[0] + if (term) { + let num = parseInt(term.clean, 10) + if (num && num > 1900 && num < 2030) { + m.tag('Year', reason) + } + } +} + +const fixDates = function(doc) { + doc.match('in the (night|evening|morning|afternoon|day|daytime)').tag('Time', 'in-the-night') + doc.match('(#Value|#Time) (am|pm)').tag('Time', 'value-ampm') + + //months: + let month = doc.if('#Month') + if (month.found === true) { + //June 5-7th + month.match(`#Month #DateRange+`).tag('Date', 'correction-numberRange') + //5th of March + month.match('#Value of #Month').tag('Date', 'value-of-month') + //5 March + month.match('#Cardinal #Month').tag('Date', 'cardinal-month') + //march 5 to 7 + month.match('#Month #Value to #Value').tag('Date', 'value-to-value') + //march the 12th + month.match('#Month the #Value').tag('Date', 'month-the-value') + } + + //months: + let val = doc.if('#Value') + if (val.found === true) { + //june 7 + val + .match('(#WeekDay|#Month) #Value') + .ifNo('#Money') + .tag('Date', 'date-value') + + //7 june + val + .match('#Value (#WeekDay|#Month)') + .ifNo('#Money') + .tag('Date', 'value-date') + + //may twenty five + val + .match('#TextValue #TextValue') + .if('#Date') + .tag('#Date', 'textvalue-date') + + //eg 'year' + let duration = val.if('#Duration') + if (duration.found === true) { + //for 4 months + duration.match('for #Value #Duration').tag('Date', 'for-x-duration') + //two days before + duration.match('#Value #Duration #Conjunction').tag('Date', 'val-duration-conjunction') + //for four days + duration.match(`${preps}? #Value #Duration`).tag('Date', 'value-duration') + //two years old + duration.match('#Value #Duration old').unTag('Date', 'val-years-old') + } + } + + //seasons + let season = doc.if(seasons) + if (season.found === true) { + season.match(`${preps}? ${thisNext} ${seasons}`).tag('Date', 'thisNext-season') + season.match(`the? ${sections} of ${seasons}`).tag('Date', 'section-season') + season.match(`${seasons} ${preps}? #Cardinal`).tag('Date', 'season-year') + } + + //rest-dates + let date = doc.if('#Date') + if (date.found === true) { + //june the 5th + date.match('#Date the? #Ordinal').tag('Date', 'correction') + //last month + date.match(`${thisNext} #Date`).tag('Date', 'thisNext') + //by 5 March + date.match('due? (by|before|after|until) #Date').tag('Date', 'by') + //next feb + date + .match('(last|next|this|previous|current|upcoming|coming|the) #Date') + .tag('Date', 'next-feb') + //start of june + date.match(`the? ${sections} of #Date`).tag('Date', 'section-of') + //fifth week in 1998 + date.match('#Ordinal #Duration in #Date').tag('Date', 'duration-in') + //early in june + date.match('(early|late) (at|in)? the? #Date').tag('Time', 'early-evening') + //tomorrow before 3 + date + .match('#Date (by|before|after|at|@|about) #Cardinal') + .not('^#Date') + .tag('Time', 'date-before-Cardinal') + //saturday am + date + .match('#Date [(am|pm)]') + .unTag('Verb') + .unTag('Copula') + .tag('Time', 'date-am') + //feb to june + date + .match('#Date (#Preposition|to) #Date') + .ifNo('#Duration') + .tag('Date', 'date-prep-date') + } + + //year/cardinal tagging + let cardinal = doc.if('#Cardinal') + if (cardinal.found === true) { + let v = cardinal.match(`#Date #Value [#Cardinal]`) + tagYear(v, 'date-value-year') + //scoops up a bunch + v = cardinal.match(`#Date+ [#Cardinal]`) + tagYear(v, 'date-year') + //feb 8 2018 + v = cardinal.match(`#Month #Value [#Cardinal]`) + tagYear(v, 'month-value-year') + //feb 8 to 10th 2018 + v = cardinal.match(`#Month #Value to #Value [#Cardinal]`) + tagYear(v, 'month-range-year') + //in 1998 + v = cardinal.match(`(in|of|by|during|before|starting|ending|for|year) [#Cardinal]`) + tagYear(v, 'in-year') + //q2 2009 + v = cardinal.match('(q1|q2|q3|q4) [#Cardinal]') + tagYear(v, 'in-year') + //2nd quarter 2009 + v = cardinal.match('#Ordinal quarter [#Cardinal]') + tagYear(v, 'in-year') + //in the year 1998 + v = cardinal.match('the year [#Cardinal]') + tagYear(v, 'in-year') + //it was 1998 + v = cardinal.match('it (is|was) [#Cardinal]') + tagYearSafe(v, 'in-year') + } + + let time = doc.if('#Time') + if (time.found === true) { + //by 6pm + time.match('(by|before|after|at|@|about) #Time').tag('Time', 'preposition-time') + //7 7pm + time + .match('#Cardinal #Time') + .not('#Year') + .tag('Time', 'value-time') + //2pm est + time.match('#Time [(eastern|pacific|central|mountain)]').tag('Time', 'timezone') + //6pm est + time.match('#Time [(est|pst|gmt)]').tag('Time', 'timezone abbr') + } + + return doc +} +module.exports = fixDates diff --git a/plugins/dates/src/tagger/01-values.js b/plugins/dates/src/tagger/01-values.js new file mode 100644 index 000000000..be4bf8d59 --- /dev/null +++ b/plugins/dates/src/tagger/01-values.js @@ -0,0 +1,30 @@ +const here = 'date-values' +// +const values = function(doc) { + if (doc.has('#Value')) { + //june 5 to 7th + doc.match('#Month #Value to #Value of? #Year?').tag('Date', here); + //5 to 7th june + doc.match('#Value to #Value of? #Month #Year?').tag('Date', here); + //third week of may + doc.match('#Value #Duration of #Date').tag('Date', here); + //two days after + doc.match('#Value+ #Duration (after|before|into|later|afterwards|ago)?').tag('Date', here); + //two days + doc.match('#Value #Date').tag('Date', here); + //june 5th + doc.match('#Date #Value').tag('Date', here); + //tuesday at 5 + doc.match('#Date #Preposition #Value').tag('Date', here); + //tomorrow before 3 + doc.match('#Date (after|before|during|on|in) #Value').tag('Date', here); + //a year and a half + doc.match('#Value (year|month|week|day) and a half').tag('Date', here); + //5 and a half years + doc.match('#Value and a half (years|months|weeks|days)').tag('Date', here); + //on the fifth + doc.match('on the #Ordinal').tag('Date', here); + } + return doc +} +module.exports = values diff --git a/plugins/dates/src/tagger/02-dates.js b/plugins/dates/src/tagger/02-dates.js new file mode 100644 index 000000000..bfaced4c6 --- /dev/null +++ b/plugins/dates/src/tagger/02-dates.js @@ -0,0 +1,36 @@ +const here = 'date-tagger' +// +const dateTagger = function(doc) { + + doc.match('(spring|summer|winter|fall|autumn|springtime|wintertime|summertime)').match('#Noun').tag('Season', here) + doc.match('(q1|q2|q3|q4)').tag('FinancialQuarter', here) + doc.match('(this|next|last|current) quarter').tag('FinancialQuarter', here) + doc.match('(this|next|last|current) season').tag('Season', here) + + if (doc.has('#Date')) { + //friday to sunday + doc.match('#Date #Preposition #Date').tag('Date', here); + //once a day.. + doc.match('(once|twice) (a|an|each) #Date').tag('Date', here); + //TODO:fixme + doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here); + //tuesday + doc.match('#Date+').tag('Date', here); + //by June + doc.match('(by|until|on|in|at|during|over|every|each|due) the? #Date').tag('Date', here); + //a year after.. + doc.match('a #Duration').tag('Date', here); + //between x and y + doc.match('(between|from) #Date').tag('Date', here); + doc.match('(to|until|upto) #Date').tag('Date', here); + doc.match('#Date and #Date').tag('Date', here); + //during this june + doc.match('(by|until|after|before|during|on|in|following) (next|this|last)? (#Date|#Date)').tag('Date', here); + //day after next + doc.match('the? #Date after next one?').tag('Date', here); + //approximately... + doc.match('(about|approx|approximately|around) #Date').tag('Date', here); + } + return doc +} +module.exports = dateTagger diff --git a/plugins/dates/src/tagger/03-sections.js b/plugins/dates/src/tagger/03-sections.js new file mode 100644 index 000000000..6876755cb --- /dev/null +++ b/plugins/dates/src/tagger/03-sections.js @@ -0,0 +1,16 @@ +const here = 'section-tagger' +// +const sectionTagger = function(doc) { + if (doc.has('#Date')) { + // //next september + doc.match('this? (last|next|past|this|previous|current|upcoming|coming|the) #Date').tag('Date', here); + //starting this june + doc.match('(starting|beginning|ending) #Date').tag('Date', here); + //start of june + doc.match('the? (start|end|middle|beginning) of (last|next|this|the) (#Date|#Date)').tag('Date', here); + //this coming june + doc.match('(the|this) #Date').tag('Date', here); + } + return doc +} +module.exports = sectionTagger diff --git a/plugins/dates/src/tagger/04-time.js b/plugins/dates/src/tagger/04-time.js new file mode 100644 index 000000000..c2c903587 --- /dev/null +++ b/plugins/dates/src/tagger/04-time.js @@ -0,0 +1,21 @@ +const here = 'time-tagger' + +// +const timeTagger = function(doc) { + if (doc.has('#Time')) { + //eastern daylight time + doc.match('#Noun (standard|daylight|central|mountain)? time').tag('Timezone', here) + } + // https://raw.githubusercontent.com/davispuh/TimezoneParser/master/data/abbreviations.yml + if (doc.has('#Acronym')) { + let abbr = + '(acdt|acst|ace|dmt|ist|tse|addt|adt|aedt|aest|ahdt|ahst|akdt|akst|amt|nst|apt|awt|gmt|awdt|awst|bdst|bst|bdt|nwt|bmt|wet|bost|cddt|cdt|cet|cmt|cpt|cst|cwt|chst|gst|eat|eddt|edt|eest|eet|emt|ept|ewt|est|ffmt|fmt|hdt|hst|hkst|hkt|hmt|iddt|idt|jmt|imt|jdt|jst|kdt|kst|kmt|lst|mddt|mdst|msd|msk|mdt|mmt|mpt|pdt|pst|mst|mwt|nddt|ndt|npt|nzdt|nzmt|nzst|pddt|pkst|pkt|plmt|pmmt|pmt|ppmt|ppt|pwt|qmt|rmt|sast|sdmt|set|sjmt|smt|sst|tbmt|tmt|utc|wast|wemt|wib|wit|wita|wmt|yddt|ydt|ypt|ywt|yst)' + doc.match(abbr).tag('Timezone', here) + } + // quarter to seven + if (doc.has('#Cardinal')) { + doc.match('(half|quarter|25|15|10|5) (past|after|to) #Cardinal').tag('Time') + } + return doc +} +module.exports = timeTagger diff --git a/plugins/dates/src/tagger/05-shifts.js b/plugins/dates/src/tagger/05-shifts.js new file mode 100644 index 000000000..1445d623c --- /dev/null +++ b/plugins/dates/src/tagger/05-shifts.js @@ -0,0 +1,14 @@ +const here = 'shift-tagger' +// +const shiftTagger = function(doc) { + if (doc.has('#Date')) { + //two weeks before + doc.match('#Cardinal #Duration (before|after)').tag('#DateShift', here) + //two weeks and three days before + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here) + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here) + doc.match('#Cardinal #Duration and? #DateShift').tag('#DateShift', here) + } + return doc +} +module.exports = shiftTagger diff --git a/plugins/dates/src/tagger/06-fixup.js b/plugins/dates/src/tagger/06-fixup.js new file mode 100644 index 000000000..c48a19836 --- /dev/null +++ b/plugins/dates/src/tagger/06-fixup.js @@ -0,0 +1,82 @@ +const here = 'fix-tagger' +// +const fixUp = function(doc) { + //fixups + if (doc.has('#Date')) { + //first day by monday + let oops = doc.match('#Date+ by #Date+') + if (oops.found && !oops.has('^due')) { + oops.match('^#Date+').unTag('Date', 'by-monday') + } + + let d = doc.match('#Date+') + //'spa day' + d.match('^day$').unTag('Date', 'spa-day') + + let knownDate = '(yesterday|today|tomorrow)' + if (d.has(knownDate)) { + //yesterday 7 + d.match(`${knownDate} [#Value]$`).unTag('Date', 'yesterday-7') + //7 yesterday + d.match(`^[#Value] ${knownDate}$`).unTag('Date', '7 yesterday') + //friday yesterday + d.match(`#WeekDay+ ${knownDate}$`) + .unTag('Date') + .lastTerm() + .tag('Date', 'fri-yesterday') + + // yesterday yesterday + // d.match(`${knownDate}+ ${knownDate}$`) + // .unTag('Date') + // .lastTerm() + // .tag('Date', here) + d.match(`(this|last|next) #Date ${knownDate}$`) + .unTag('Date') + .lastTerm() + .tag('Date', 'this month yesterday') + } + //tomorrow on 5 + d.match(`on #Cardinal$`).unTag('Date', here) + //this tomorrow + d.match(`this tomorrow`) + .terms(0) + .unTag('Date', 'this-tomorrow') + //q2 2019 + d.match(`(q1|q2|q3|q4) #Year`).tag('Date', here) + //5 tuesday + // d.match(`^#Value #WeekDay`).terms(0).unTag('Date'); + //5 next week + d.match(`^#Value (this|next|last)`) + .terms(0) + .unTag('Date', here) + + if (d.has('(last|this|next)')) { + //this month 7 + d.match(`(last|this|next) #Duration #Value`) + .terms(2) + .unTag('Date', here) + //7 this month + d.match(`!#Month #Value (last|this|next) #Date`) + .terms(0) + .unTag('Date', here) + } + //january 5 5 + if (d.has('(#Year|#Time|#TextValue|#NumberRange)') === false) { + d.match('(#Month|#WeekDay) #Value #Value') + .terms(2) + .unTag('Date', here) + } + //between june + if (d.has('^between') && !d.has('and .')) { + d.unTag('Date', here) + } + //june june + if (d.has('#Month #Month') && !d.has('@hasHyphen') && !d.has('@hasComma')) { + d.match('#Month') + .lastTerm() + .unTag('Date', 'month-month') + } + } + return doc +} +module.exports = fixUp diff --git a/plugins/dates/src/tagger/index.js b/plugins/dates/src/tagger/index.js new file mode 100644 index 000000000..9845dc9ef --- /dev/null +++ b/plugins/dates/src/tagger/index.js @@ -0,0 +1,15 @@ +const methods = [ + require('./00-basic'), + require('./01-values'), + require('./02-dates'), + require('./03-sections'), + require('./04-time'), + require('./05-shifts'), + require('./06-fixup'), +] +// run each of the taggers +const tagDate = function(doc) { + methods.forEach(fn => fn(doc)) + return doc +} +module.exports = tagDate diff --git a/plugins/dates/src/tags.js b/plugins/dates/src/tags.js new file mode 100644 index 000000000..b2e8e1d83 --- /dev/null +++ b/plugins/dates/src/tags.js @@ -0,0 +1,34 @@ +module.exports = { + FinancialQuarter: { + isA: 'Date', + }, + // 'summer' + Season: { + isA: 'Date', + }, + // '1982' + Year: { + isA: ['Date'], + notA: 'RomanNumeral', + }, + // 'months' + Duration: { + isA: ['Date', 'Noun'], + }, + // '9:20pm' + Time: { + isA: ['Date'], + }, + // 'easter' + Holiday: { + isA: ['Date', 'Noun'], + }, + // 'PST' + Timezone: { + isA: ['Date', 'Noun'], + }, + // 'two weeks before' + DateShift: { + isA: ['Date'], + }, +} diff --git a/plugins/dates/src/words/dates.js b/plugins/dates/src/words/dates.js new file mode 100644 index 000000000..4a163db63 --- /dev/null +++ b/plugins/dates/src/words/dates.js @@ -0,0 +1,24 @@ +module.exports = [ + 'weekend', + 'weekday', + + 'summer', + 'winter', + 'autumn', + + 'some day', + 'one day', + 'all day', + 'some point', + + 'eod', + 'eom', + 'standard time', + 'daylight time', + + 'today', + 'tomorrow', + 'tmr', + 'tmrw', + 'yesterday', +] diff --git a/data/words/dates/durations.js b/plugins/dates/src/words/durations.js similarity index 94% rename from data/words/dates/durations.js rename to plugins/dates/src/words/durations.js index d81731eb8..0cd8497e7 100644 --- a/data/words/dates/durations.js +++ b/plugins/dates/src/words/durations.js @@ -17,5 +17,5 @@ module.exports = [ 'week', 'weeks', 'year', - 'years' -]; + 'years', +] diff --git a/data/words/dates/holidays.js b/plugins/dates/src/words/holidays.js similarity index 98% rename from data/words/dates/holidays.js rename to plugins/dates/src/words/holidays.js index b689a6f6f..72284e683 100644 --- a/data/words/dates/holidays.js +++ b/plugins/dates/src/words/holidays.js @@ -8,17 +8,16 @@ module.exports = [ 'bastille day', 'boxing day', 'canada day', - 'christmas', 'christmas eve', + 'christmas', 'cinco de mayo', + 'day of the dead', + 'dia de muertos', + 'dieciseis de septiembre', 'emancipation day', + 'grito de dolores', 'groundhog day', 'halloween', - '16 de septiembre', - 'dieciseis de septiembre', - 'grito de dolores', - 'day of the dead', - 'dia de muertos', 'harvey milk day', 'inauguration day', 'independence day', @@ -27,8 +26,8 @@ module.exports = [ 'labour day', 'national freedom day', 'national nurses day', - 'new years', 'new years eve', + 'new years', 'purple heart day', 'rememberance day', 'rosa parks day', @@ -136,11 +135,12 @@ module.exports = [ 'summer solistice', 'mabon', 'september equinox', + 'fall equinox', 'autumnal equinox', 'yule', 'december solstice', 'winter solstice', // Additional important holidays 'chinese new year', - 'diwali' -]; + 'diwali', +] diff --git a/plugins/dates/src/words/index.js b/plugins/dates/src/words/index.js new file mode 100644 index 000000000..e4982e0c3 --- /dev/null +++ b/plugins/dates/src/words/index.js @@ -0,0 +1,15 @@ +let lex = {} + +const data = [ + [require('./dates'), ['#Date']], + [require('./durations'), ['#Duration']], + [require('./holidays'), ['#Holiday']], + [require('./times'), ['#Time']], +] +data.forEach(a => { + for (let i = 0; i < a[0].length; i++) { + lex[a[0][i]] = a[1] + } +}) + +module.exports = lex diff --git a/data/words/dates/times.js b/plugins/dates/src/words/times.js similarity index 88% rename from data/words/dates/times.js rename to plugins/dates/src/words/times.js index 1c626f210..a89dd502e 100644 --- a/data/words/dates/times.js +++ b/plugins/dates/src/words/times.js @@ -14,6 +14,7 @@ module.exports = [ 'sometime', 'eod', 'oclock', + 'oclock', 'all day', - 'at night' -]; + 'at night', +] diff --git a/plugins/dates/tests/_lib.js b/plugins/dates/tests/_lib.js new file mode 100644 index 000000000..3dfba94ba --- /dev/null +++ b/plugins/dates/tests/_lib.js @@ -0,0 +1,14 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + nlp.extend(require(`../../numbers/`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + nlp.extend(require(`../../numbers/src`)) + } + + module.exports = nlp +} diff --git a/plugins/dates/tests/basic_date.ignore.js b/plugins/dates/tests/basic_date.ignore.js new file mode 100644 index 000000000..c1bb35fd7 --- /dev/null +++ b/plugins/dates/tests/basic_date.ignore.js @@ -0,0 +1,73 @@ +const test = require('tape') +const nlp = require('./_lib') + +let d = Date.now() +d.setFullYear(2019) +const config = { + now: d, +} + +test('date-parse :', function(t) { + ;[ + ['june 5th 1999', [5, 5, 1999]], + ['june 5th 1999', [5, 5, 1999]], + ['january 1st 1644', [0, 1, 1644]], + ['jan 1st 1644', [0, 1, 1644]], + ['June 4th 1993', [5, 4, 1993]], + ['March 1st 1987', [2, 1, 1987]], + ['June 22nd 2014', [5, 22, 2014]], + ['may 22nd 2014', [4, 22, 2014]], + ['sep 22nd 2014', [8, 22, 2014]], + ['apr 22nd 2014', [3, 22, 2014]], + ['June 22nd 1997', [5, 22, 1997]], + ['3rd of March 1969', [2, 3, 1969]], + ['2nd of April 1929', [3, 2, 1929]], + ['2nd of jul 1929', [6, 2, 1929]], + //incomplete dates + ['March 1969', [2, null, 1969]], + ['March 18th', [2, 18, null]], + ['August 28th', [7, 28, null]], + ['18th of March', [2, 18, null]], + ['27th of March', [2, 27, null]], + // ['2012-2014', [null, null, 2012]], + // ['1997-1998', [null, null, 1997]], + // ['1998', [null, null, 1998]], + // ['1672', [null, null, 1672]], + // ['2015', [null, null, 2015]], + ['january 5th 1998', [0, 5, 1998]], + ['february 10th', [1, 10, null]], + ['february 30th', [1, 30, null]], + ['jan 1921', [0, null, 1921]], + //invalid dates + // ['303rd of March 1969', [2, null, 1969]], + // ['4103', [null, null, null]], + + // ['January 5th 4032', [0, 5, null]], + ].forEach(function(a) { + let arr = nlp(a[0]) + .dates(config) + .json({ format: 'json' }) + + let o = (arr[0].date || {}).start || {} + let got = [o.month, o.date, o.year] + let msg = 'date "' + a[0] + '" got: [' + got.join(',') + '] want: [' + a[1].join(',') + ']' + t.deepEqual(got, a[1], msg) + }) + t.end() +}) + +// durations // + +// ['March 7th-11th 1987', [2, 7, 1987]], +// ['June 1st-11th 1999', [5, 1, 1999]], +// ['28th of September to 5th of October 2008', [8, 28, 2008]], +// ['2nd of January to 5th of October 2008', [9, 5, 2008]], +// ['March 7th to june 11th 1987', [2, 7, 1987]], +// ['April 17th to september 11th 1981', [3, 17, 1981]], +// ['June 1st to June 11th 2014', [5, 1, 2014]], +// ['between 13 February and 15 February 1945', [1, 13, 1945]], +// ['between March 7th and june 11th 1987', [2, 7, 1987]], +// ['3rd - 5th of March 1969', [2, 3, 1969]], +// ["September 1939 to April 1945", ["month":null,"day":null,"year":1939]], +// ["June 1969 to April 1975", ["month":null,"day":null,"year":1969]], +// ["2014-1998", ["month":null,"day":null,"year":null]], diff --git a/test/unit/subset/date/date_tag.test.js b/plugins/dates/tests/date_tag.test.js similarity index 96% rename from test/unit/subset/date/date_tag.test.js rename to plugins/dates/tests/date_tag.test.js index 9e56ec338..4b6260ce8 100644 --- a/test/unit/subset/date/date_tag.test.js +++ b/plugins/dates/tests/date_tag.test.js @@ -1,8 +1,8 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); +const test = require('tape') +const nlp = require('./_lib') test('date-tag :', function(t) { - [ + ;[ 'yesterday', 'today', 'tomorrow', @@ -284,15 +284,17 @@ test('date-tag :', function(t) { 'fri 3 months ago at 5am', 'wednesday 1 month ago at 8pm', 'October 2006', - '27/5/1979' + '27/5/1979', // '-5min', // '+2d', // '100th day to 200th', // 'march' ].forEach(function(first) { - var str = nlp(first).match('#Date+').out('text'); - var msg = first + ' -> ' + str; - t.equal(str, first, msg); - }); - t.end(); -}); + const str = nlp(first) + .match('#Date+') + .out('text') + const msg = first + ' -> ' + str + t.equal(str, first, msg) + }) + t.end() +}) diff --git a/plugins/dates/tests/misc.test.js b/plugins/dates/tests/misc.test.js new file mode 100644 index 000000000..33102b0a9 --- /dev/null +++ b/plugins/dates/tests/misc.test.js @@ -0,0 +1,49 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('misc dates', function(t) { + let doc = nlp('my birthday is June 5th 1998') + t.equal(doc.dates().length, 1, 'one-date') + + let json = doc.dates().json({ normal: true }) + t.equal(json[0].normal, 'june 5th 1998', 'date-normal') + t.end() +}) + +test('date-tagger', function(t) { + let arr = [ + ['june 2009', ['Month', 'Year']], + ['june 5th 2009', ['Month', 'Date', 'Year']], + ['q2 2009', ['Date', 'Year']], + ['spring 1980', ['Date', 'Year']], + ['summer of 1999', ['Date', 'Date', 'Year']], + ['today', ['Date']], + ['minute', ['Duration']], + ['valentines day', ['Holiday', 'Holiday']], + ['ash wednesday', ['Holiday', 'Holiday']], + ] + arr.forEach(function(a) { + let terms = nlp(a[0]).json(0).terms + terms.forEach((term, i) => { + let tag = a[1][i] + let found = term.tags.some(tg => tg === tag) + t.equal(found, true, term.text + ' ' + tag) + }) + }) + t.end() +}) + +test('date-format', function(t) { + let doc = nlp(`i'm going skiing two days after November 1st 2019 at 7pm`) + // doc.dates().format('{day} {month} {date-ordinal}, {time}') //TODO: November 0th?? + // t.equal(doc.text(), `i'm going skiing Wednesday November 3rd, 7:00pm`, 'format-test') + + doc = nlp(`halloween`) + doc.dates().format('{month} {date-ordinal}') + t.equal(doc.text(), `October 31st`, 'format-test-holiday') + + doc = nlp(`two days after halloween`) + doc.dates().format('{month} {date-ordinal}, {time}') + t.equal(doc.text(), `November 2nd, 12:00am`, 'format-test-punt') + t.end() +}) diff --git a/plugins/dates/tests/misc_date.test.js b/plugins/dates/tests/misc_date.test.js new file mode 100644 index 000000000..0e7ead4e8 --- /dev/null +++ b/plugins/dates/tests/misc_date.test.js @@ -0,0 +1,64 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('short+long form', function(t) { + let r = nlp('wednesday, january 2nd, 2016') + let shorter = r + .dates() + .toShortForm() + .text() + t.equal(shorter, 'wed, jan 2nd, 2016') + + let r2 = nlp('Thurs, feb 2nd, 2016') + let longer = r2 + .dates() + .toLongForm() + .text() + t.equal(longer, 'Thursday, february 2nd, 2016') + + let doc = nlp('April, June, and Sept') + shorter = doc + .dates() + .toShortForm() + .all() + .text() + t.equal(shorter, 'Apr, Jun, and Sept', 'months-short') + + longer = doc + .dates() + .toLongForm() + .all() + .text() + t.equal(longer, 'April, June, and September', 'months-longer') + + r2 = nlp('Thurs, feb 2nd, 2016') + longer = r2 + .dates() + .toLongForm() + .text() + t.equal(longer, 'Thursday, february 2nd, 2016') + + let str = nlp('April, June, and Sept') + .dates() + .toShortForm() + .all() + .out() + t.equal('Apr, Jun, and Sept', str, 'toShortForm-comma') + + str = nlp('Apr, June, and Sept') + .dates() + .toLongForm() + .all() + .out() + t.equal('April, June, and September', str, 'toShortForm-comma') + + // doc = nlp('January 10, 2018 7:20 AM') + // let obj = doc.dates().json()[0].date + // t.equal(obj.month, 0, 'month') + // t.equal(obj.date, 10, 'date') + // t.equal(obj.year, 2018, 'year') + // t.equal(obj.time.hour, 7, 'hour') + // t.equal(obj.time.minute, 20, 'minute') + + t.end() +}) diff --git a/plugins/ngrams/.gitignore b/plugins/ngrams/.gitignore new file mode 100644 index 000000000..8b9247097 --- /dev/null +++ b/plugins/ngrams/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +coverage/ +.DS_Store +.env +.nyc_output/ +.vscode \ No newline at end of file diff --git a/plugins/ngrams/README.md b/plugins/ngrams/README.md new file mode 100644 index 000000000..e4c2c4563 --- /dev/null +++ b/plugins/ngrams/README.md @@ -0,0 +1,48 @@ +
+ + +
a plugin for compromise
+ + + + + + + + + + +
+
+ +
+ npm install compromise-ngrams +
+ +```js +const nlp = require('compromise') +nlp.extend(require('compromise-ngrams')) + +let doc = nlp(`bake 'em away, toys`) +doc.bigrams().data() +//[{normal:'bake em', size:2, count:1}, {normal:'em away', size:2, count:1}, {normal:'em toys', size:2, count:1}] + +//same for: +doc.unigrams() +doc.trigrams() +doc.ngrams({ size: 3 }) +``` + +### [Demo](https://observablehq.com/@spencermountain/compromise-ngram) + +### API: + +- **.ngrams({})** - list all repeating sub-phrases, by word-count +- **.unigrams()** - n-grams with one word +- **.bigrams()** - n-grams with two words +- **.trigrams()** - n-grams with three words +- **.startgrams()** - n-grams including the first term of a phrase +- **.endgrams()** - n-grams including the last term of a phrase +- **.edgegrams()** - n-grams including the first or last term of a phrase + +MIT diff --git a/plugins/ngrams/builds/compromise-ngrams.js b/plugins/ngrams/builds/compromise-ngrams.js new file mode 100644 index 000000000..25fb545ec --- /dev/null +++ b/plugins/ngrams/builds/compromise-ngrams.js @@ -0,0 +1,328 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseNgrams = factory()); +}(this, (function () { 'use strict'; + + var defaults = { + max: 4, + min: 1 + }; + + var oneSize = function oneSize(list, size) { + var grams = {}; // count each instance + + list.forEach(function (terms) { + for (var i = 0; i < terms.length; i += 1) { + var slice = terms.slice(i, i + size); + + if (slice.length === size) { + var str = slice.join(' '); + + if (grams.hasOwnProperty(str)) { + grams[str].count += 1; + } else { + grams[str] = { + size: size, + count: 1 + }; + } + } + } + }); // turn them into an array + + var arr = Object.keys(grams).map(function (k) { + grams[k].normal = k; + return grams[k]; + }); + return arr; + }; + + var allGrams = function allGrams(list, options) { + // support {size:2} syntax + if (options.size) { + options.min = options.size; + options.max = options.size; + } + + var max = options.max || defaults.max; + var min = options.min || defaults.min; + var arr = []; + + for (var size = min; size <= max; size += 1) { + arr = arr.concat(oneSize(list, size)); + } + + return arr; + }; + + var getGrams = allGrams; + + var defaults$1 = { + max: 4, + min: 1 + }; + + var oneSize$1 = function oneSize(list, size) { + var grams = {}; // count each instance + + list.forEach(function (terms) { + for (var i = 0; i <= terms.length; i += 1) { + var slice = terms.slice(0, i); + + if (slice.length === size) { + var str = slice.join(' '); + + if (grams.hasOwnProperty(str)) { + grams[str].count += 1; + } else { + grams[str] = { + size: size, + count: 1 + }; + } + } + } + }); // turn them into an array + + var arr = Object.keys(grams).map(function (k) { + grams[k].normal = k; + return grams[k]; + }); + return arr; + }; + + var startGrams = function startGrams(list, options) { + // support {size:2} syntax + if (options.size) { + options.min = options.size; + options.max = options.size; + } + + var max = options.max || defaults$1.max; + var min = options.min || defaults$1.min; + var arr = []; + + for (var size = min; size <= max; size++) { + arr = arr.concat(oneSize$1(list, size)); + } + + return arr; + }; + + var startGrams_1 = startGrams; + + var defaults$2 = { + max: 4, + min: 1 + }; + + var oneSize$2 = function oneSize(list, size) { + var grams = {}; // count each instance + + list.forEach(function (terms) { + var len = terms.length; + + for (var i = 0; i <= terms.length; i += 1) { + var slice = terms.slice(len - i, len); + + if (slice.length === size) { + var str = slice.join(' '); + + if (grams.hasOwnProperty(str)) { + grams[str].count += 1; + } else { + grams[str] = { + size: size, + count: 1 + }; + } + } + } + }); // turn them into an array + + var arr = Object.keys(grams).map(function (k) { + grams[k].normal = k; + return grams[k]; + }); + return arr; + }; + + var endGrams = function endGrams(list, options) { + // support {size:2} syntax + if (options.size) { + options.min = options.size; + options.max = options.size; + } + + var max = options.max || defaults$2.max; + var min = options.min || defaults$2.min; + var arr = []; + + for (var size = min; size <= max; size++) { + arr = arr.concat(oneSize$2(list, size)); + } + + return arr; + }; + + var endGrams_1 = endGrams; + + // tokenize by term + var tokenize = function tokenize(doc) { + var list = doc.json({ + terms: { + clean: true + }, + text: false + }).map(function (o) { + return o.terms.map(function (t) { + return t.clean; + }); + }); + return list; + }; + + var tokenize_1 = tokenize; + + var sort = function sort(arr) { + arr = arr.sort(function (a, b) { + //first sort them by count + if (a.count > b.count) { + return -1; + } + + if (a.count < b.count) { + return 1; + } // in a tie, sort them by size + + + if (a.size > b.size) { + return -1; + } + + if (a.size < b.size) { + return 1; + } + + return 0; + }); + return arr; + }; + + var sort_1 = sort; + + var addMethod = function addMethod(Doc) { + /** list all repeating sub-phrases, by word-count */ + Doc.prototype.ngrams = function (obj) { + var list = tokenize_1(this); + var arr = getGrams(list, obj || {}); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.nGrams = Doc.prototype.ngrams; + /** n-grams with one word */ + + Doc.prototype.unigrams = function (n) { + var arr = getGrams(tokenize_1(this), { + max: 1, + min: 1 + }); + arr = sort_1(arr); + + if (typeof n === 'number') { + arr = arr[n]; + } + + return arr; + }; + + Doc.prototype.uniGrams = Doc.prototype.unigrams; + /** n-grams with two words */ + + Doc.prototype.bigrams = function (n) { + var arr = getGrams(tokenize_1(this), { + max: 2, + min: 2 + }); + arr = sort_1(arr); + + if (typeof n === 'number') { + arr = arr[n]; + } + + return arr; + }; + + Doc.prototype.biGrams = Doc.prototype.bigrams; + /** n-grams with three words */ + + Doc.prototype.trigrams = function (n) { + var arr = getGrams(tokenize_1(this), { + max: 3, + min: 3 + }); + arr = sort_1(arr); + + if (typeof n === 'number') { + arr = arr[n]; + } + + return arr; + }; + + Doc.prototype.triGrams = Doc.prototype.trigrams; + /** list all repeating sub-phrases, using the first word */ + + Doc.prototype.startgrams = function (obj) { + var list = tokenize_1(this); + var arr = startGrams_1(list, obj || {}); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.startGrams = Doc.prototype.startgrams; + /** list all repeating sub-phrases, connected to the last word of each phrase */ + + Doc.prototype.endgrams = function (obj) { + var list = tokenize_1(this); + var arr = endGrams_1(list, obj || {}); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.endGrams = Doc.prototype.endgrams; + /** list all repeating sub-phrases, connected to the last word of each phrase */ + + Doc.prototype.edgegrams = function (obj) { + var list = tokenize_1(this); + var start = startGrams_1(list, obj || {}); + var end = endGrams_1(list, obj || {}); // combine them together + + var all = start.concat(end); + var combine = all.reduce(function (h, a) { + if (h[a.normal]) { + h[a.normal].count += a.count; + } else { + h[a.normal] = a; + } + + return h; + }, {}); + var arr = Object.keys(combine).map(function (k) { + return combine[k]; + }); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.edgeGrams = Doc.prototype.edgegrams; + }; + + var src = addMethod; + + return src; + +}))); +//# sourceMappingURL=compromise-ngrams.js.map diff --git a/plugins/ngrams/builds/compromise-ngrams.js.map b/plugins/ngrams/builds/compromise-ngrams.js.map new file mode 100644 index 000000000..85ba56517 --- /dev/null +++ b/plugins/ngrams/builds/compromise-ngrams.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-ngrams.js","sources":["../src/getGrams.js","../src/startGrams.js","../src/endGrams.js","../src/tokenize.js","../src/sort.js","../src/index.js"],"sourcesContent":["const defaults = {\n max: 4,\n min: 1,\n}\n\nconst oneSize = function(list, size) {\n let grams = {}\n // count each instance\n list.forEach(terms => {\n for (let i = 0; i < terms.length; i += 1) {\n let slice = terms.slice(i, i + size)\n if (slice.length === size) {\n let str = slice.join(' ')\n if (grams.hasOwnProperty(str)) {\n grams[str].count += 1\n } else {\n grams[str] = {\n size: size,\n count: 1,\n }\n }\n }\n }\n })\n // turn them into an array\n let arr = Object.keys(grams).map(k => {\n grams[k].normal = k\n return grams[k]\n })\n return arr\n}\n\nconst allGrams = function(list, options) {\n // support {size:2} syntax\n if (options.size) {\n options.min = options.size\n options.max = options.size\n }\n let max = options.max || defaults.max\n let min = options.min || defaults.min\n let arr = []\n for (let size = min; size <= max; size += 1) {\n arr = arr.concat(oneSize(list, size))\n }\n return arr\n}\nmodule.exports = allGrams\n","const defaults = {\n max: 4,\n min: 1,\n}\n\nconst oneSize = function(list, size) {\n let grams = {}\n // count each instance\n list.forEach(terms => {\n for (let i = 0; i <= terms.length; i += 1) {\n let slice = terms.slice(0, i)\n if (slice.length === size) {\n let str = slice.join(' ')\n if (grams.hasOwnProperty(str)) {\n grams[str].count += 1\n } else {\n grams[str] = {\n size: size,\n count: 1,\n }\n }\n }\n }\n })\n // turn them into an array\n let arr = Object.keys(grams).map(k => {\n grams[k].normal = k\n return grams[k]\n })\n return arr\n}\n\nconst startGrams = function(list, options) {\n // support {size:2} syntax\n if (options.size) {\n options.min = options.size\n options.max = options.size\n }\n let max = options.max || defaults.max\n let min = options.min || defaults.min\n let arr = []\n for (let size = min; size <= max; size++) {\n arr = arr.concat(oneSize(list, size))\n }\n return arr\n}\nmodule.exports = startGrams\n","const defaults = {\n max: 4,\n min: 1,\n}\n\nconst oneSize = function(list, size) {\n let grams = {}\n // count each instance\n list.forEach(terms => {\n let len = terms.length\n for (let i = 0; i <= terms.length; i += 1) {\n let slice = terms.slice(len - i, len)\n if (slice.length === size) {\n let str = slice.join(' ')\n if (grams.hasOwnProperty(str)) {\n grams[str].count += 1\n } else {\n grams[str] = {\n size: size,\n count: 1,\n }\n }\n }\n }\n })\n // turn them into an array\n let arr = Object.keys(grams).map(k => {\n grams[k].normal = k\n return grams[k]\n })\n return arr\n}\n\nconst endGrams = function(list, options) {\n // support {size:2} syntax\n if (options.size) {\n options.min = options.size\n options.max = options.size\n }\n let max = options.max || defaults.max\n let min = options.min || defaults.min\n let arr = []\n for (let size = min; size <= max; size++) {\n arr = arr.concat(oneSize(list, size))\n }\n return arr\n}\nmodule.exports = endGrams\n","// tokenize by term\nconst tokenize = function(doc) {\n let list = doc.json({ terms: { clean: true }, text: false }).map(o => {\n return o.terms.map(t => t.clean)\n })\n return list\n}\nmodule.exports = tokenize\n","const sort = function(arr) {\n arr = arr.sort((a, b) => {\n //first sort them by count\n if (a.count > b.count) {\n return -1\n }\n if (a.count < b.count) {\n return 1\n }\n // in a tie, sort them by size\n if (a.size > b.size) {\n return -1\n }\n if (a.size < b.size) {\n return 1\n }\n return 0\n })\n return arr\n}\nmodule.exports = sort\n","const getGrams = require('./getGrams')\nconst startGrams = require('./startGrams')\nconst endGrams = require('./endGrams')\nconst tokenize = require('./tokenize')\nconst sort = require('./sort')\n\nconst addMethod = function(Doc) {\n /** list all repeating sub-phrases, by word-count */\n Doc.prototype.ngrams = function(obj) {\n let list = tokenize(this)\n let arr = getGrams(list, obj || {})\n arr = sort(arr)\n return arr\n }\n Doc.prototype.nGrams = Doc.prototype.ngrams\n\n /** n-grams with one word */\n Doc.prototype.unigrams = function(n) {\n let arr = getGrams(tokenize(this), { max: 1, min: 1 })\n arr = sort(arr)\n if (typeof n === 'number') {\n arr = arr[n]\n }\n return arr\n }\n Doc.prototype.uniGrams = Doc.prototype.unigrams\n\n /** n-grams with two words */\n Doc.prototype.bigrams = function(n) {\n let arr = getGrams(tokenize(this), { max: 2, min: 2 })\n arr = sort(arr)\n if (typeof n === 'number') {\n arr = arr[n]\n }\n return arr\n }\n Doc.prototype.biGrams = Doc.prototype.bigrams\n\n /** n-grams with three words */\n Doc.prototype.trigrams = function(n) {\n let arr = getGrams(tokenize(this), { max: 3, min: 3 })\n arr = sort(arr)\n if (typeof n === 'number') {\n arr = arr[n]\n }\n return arr\n }\n Doc.prototype.triGrams = Doc.prototype.trigrams\n\n /** list all repeating sub-phrases, using the first word */\n Doc.prototype.startgrams = function(obj) {\n let list = tokenize(this)\n let arr = startGrams(list, obj || {})\n arr = sort(arr)\n return arr\n }\n Doc.prototype.startGrams = Doc.prototype.startgrams\n\n /** list all repeating sub-phrases, connected to the last word of each phrase */\n Doc.prototype.endgrams = function(obj) {\n let list = tokenize(this)\n let arr = endGrams(list, obj || {})\n arr = sort(arr)\n return arr\n }\n Doc.prototype.endGrams = Doc.prototype.endgrams\n\n /** list all repeating sub-phrases, connected to the last word of each phrase */\n Doc.prototype.edgegrams = function(obj) {\n let list = tokenize(this)\n let start = startGrams(list, obj || {})\n let end = endGrams(list, obj || {})\n // combine them together\n let all = start.concat(end)\n let combine = all.reduce((h, a) => {\n if (h[a.normal]) {\n h[a.normal].count += a.count\n } else {\n h[a.normal] = a\n }\n return h\n }, {})\n let arr = Object.keys(combine).map(k => combine[k])\n arr = sort(arr)\n return arr\n }\n Doc.prototype.edgeGrams = Doc.prototype.edgegrams\n}\nmodule.exports = addMethod\n"],"names":["defaults","max","min","oneSize","list","size","grams","forEach","terms","i","length","slice","str","join","hasOwnProperty","count","arr","Object","keys","map","k","normal","allGrams","options","concat","startGrams","len","endGrams","tokenize","doc","json","clean","text","o","t","sort","a","b","addMethod","Doc","prototype","ngrams","obj","getGrams","nGrams","unigrams","n","uniGrams","bigrams","biGrams","trigrams","triGrams","startgrams","endgrams","edgegrams","start","end","all","combine","reduce","h","edgeGrams"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/ngrams/builds/compromise-ngrams.min.js b/plugins/ngrams/builds/compromise-ngrams.min.js new file mode 100644 index 000000000..65e60b836 --- /dev/null +++ b/plugins/ngrams/builds/compromise-ngrams.min.js @@ -0,0 +1 @@ +!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(t=t||self).compromiseNgrams=r()}(this,(function(){"use strict";var t=4,r=1,n=function(t,r){var n={};return t.forEach((function(t){for(var o=0;or.count?-1:t.countr.size?-1:t.size b.count) { + return -1; + } + + if (a.count < b.count) { + return 1; + } // in a tie, sort them by size + + + if (a.size > b.size) { + return -1; + } + + if (a.size < b.size) { + return 1; + } + + return 0; + }); + return arr; +}; + +var sort_1 = sort; + +var addMethod = function addMethod(Doc) { + /** list all repeating sub-phrases, by word-count */ + Doc.prototype.ngrams = function (obj) { + var list = tokenize_1(this); + var arr = getGrams(list, obj || {}); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.nGrams = Doc.prototype.ngrams; + /** n-grams with one word */ + + Doc.prototype.unigrams = function (n) { + var arr = getGrams(tokenize_1(this), { + max: 1, + min: 1 + }); + arr = sort_1(arr); + + if (typeof n === 'number') { + arr = arr[n]; + } + + return arr; + }; + + Doc.prototype.uniGrams = Doc.prototype.unigrams; + /** n-grams with two words */ + + Doc.prototype.bigrams = function (n) { + var arr = getGrams(tokenize_1(this), { + max: 2, + min: 2 + }); + arr = sort_1(arr); + + if (typeof n === 'number') { + arr = arr[n]; + } + + return arr; + }; + + Doc.prototype.biGrams = Doc.prototype.bigrams; + /** n-grams with three words */ + + Doc.prototype.trigrams = function (n) { + var arr = getGrams(tokenize_1(this), { + max: 3, + min: 3 + }); + arr = sort_1(arr); + + if (typeof n === 'number') { + arr = arr[n]; + } + + return arr; + }; + + Doc.prototype.triGrams = Doc.prototype.trigrams; + /** list all repeating sub-phrases, using the first word */ + + Doc.prototype.startgrams = function (obj) { + var list = tokenize_1(this); + var arr = startGrams_1(list, obj || {}); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.startGrams = Doc.prototype.startgrams; + /** list all repeating sub-phrases, connected to the last word of each phrase */ + + Doc.prototype.endgrams = function (obj) { + var list = tokenize_1(this); + var arr = endGrams_1(list, obj || {}); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.endGrams = Doc.prototype.endgrams; + /** list all repeating sub-phrases, connected to the last word of each phrase */ + + Doc.prototype.edgegrams = function (obj) { + var list = tokenize_1(this); + var start = startGrams_1(list, obj || {}); + var end = endGrams_1(list, obj || {}); // combine them together + + var all = start.concat(end); + var combine = all.reduce(function (h, a) { + if (h[a.normal]) { + h[a.normal].count += a.count; + } else { + h[a.normal] = a; + } + + return h; + }, {}); + var arr = Object.keys(combine).map(function (k) { + return combine[k]; + }); + arr = sort_1(arr); + return arr; + }; + + Doc.prototype.edgeGrams = Doc.prototype.edgegrams; +}; + +var src = addMethod; + +export default src; diff --git a/plugins/ngrams/package-lock.json b/plugins/ngrams/package-lock.json new file mode 100644 index 000000000..78ac20654 --- /dev/null +++ b/plugins/ngrams/package-lock.json @@ -0,0 +1,772 @@ +{ + "name": "compromise-ngrams", + "version": "0.0.3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", + "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz", + "integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.1.tgz", + "integrity": "sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/plugins/ngrams/package.json b/plugins/ngrams/package.json new file mode 100644 index 000000000..51ef60db3 --- /dev/null +++ b/plugins/ngrams/package.json @@ -0,0 +1,47 @@ +{ + "name": "compromise-ngrams", + "description": "plugin for nlp-compromise", + "version": "0.0.3", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-ngrams.js", + "unpkg": "./builds/compromise-ngrams.min.js", + "module": "./builds/compromise-ngrams.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*" + }, + "dependencies": {}, + "devDependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/plugins/ngrams/rollup.config.js b/plugins/ngrams/rollup.config.js new file mode 100644 index 000000000..a81166928 --- /dev/null +++ b/plugins/ngrams/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-ngrams' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseNgrams', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseNgrams', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/ngrams/src/endGrams.js b/plugins/ngrams/src/endGrams.js new file mode 100644 index 000000000..1cbeb3638 --- /dev/null +++ b/plugins/ngrams/src/endGrams.js @@ -0,0 +1,48 @@ +const defaults = { + max: 4, + min: 1, +} + +const oneSize = function(list, size) { + let grams = {} + // count each instance + list.forEach(terms => { + let len = terms.length + for (let i = 0; i <= terms.length; i += 1) { + let slice = terms.slice(len - i, len) + if (slice.length === size) { + let str = slice.join(' ') + if (grams.hasOwnProperty(str)) { + grams[str].count += 1 + } else { + grams[str] = { + size: size, + count: 1, + } + } + } + } + }) + // turn them into an array + let arr = Object.keys(grams).map(k => { + grams[k].normal = k + return grams[k] + }) + return arr +} + +const endGrams = function(list, options) { + // support {size:2} syntax + if (options.size) { + options.min = options.size + options.max = options.size + } + let max = options.max || defaults.max + let min = options.min || defaults.min + let arr = [] + for (let size = min; size <= max; size++) { + arr = arr.concat(oneSize(list, size)) + } + return arr +} +module.exports = endGrams diff --git a/plugins/ngrams/src/getGrams.js b/plugins/ngrams/src/getGrams.js new file mode 100644 index 000000000..229915411 --- /dev/null +++ b/plugins/ngrams/src/getGrams.js @@ -0,0 +1,47 @@ +const defaults = { + max: 4, + min: 1, +} + +const oneSize = function(list, size) { + let grams = {} + // count each instance + list.forEach(terms => { + for (let i = 0; i < terms.length; i += 1) { + let slice = terms.slice(i, i + size) + if (slice.length === size) { + let str = slice.join(' ') + if (grams.hasOwnProperty(str)) { + grams[str].count += 1 + } else { + grams[str] = { + size: size, + count: 1, + } + } + } + } + }) + // turn them into an array + let arr = Object.keys(grams).map(k => { + grams[k].normal = k + return grams[k] + }) + return arr +} + +const allGrams = function(list, options) { + // support {size:2} syntax + if (options.size) { + options.min = options.size + options.max = options.size + } + let max = options.max || defaults.max + let min = options.min || defaults.min + let arr = [] + for (let size = min; size <= max; size += 1) { + arr = arr.concat(oneSize(list, size)) + } + return arr +} +module.exports = allGrams diff --git a/plugins/ngrams/src/index.js b/plugins/ngrams/src/index.js new file mode 100644 index 000000000..020d32d50 --- /dev/null +++ b/plugins/ngrams/src/index.js @@ -0,0 +1,89 @@ +const getGrams = require('./getGrams') +const startGrams = require('./startGrams') +const endGrams = require('./endGrams') +const tokenize = require('./tokenize') +const sort = require('./sort') + +const addMethod = function(Doc) { + /** list all repeating sub-phrases, by word-count */ + Doc.prototype.ngrams = function(obj) { + let list = tokenize(this) + let arr = getGrams(list, obj || {}) + arr = sort(arr) + return arr + } + Doc.prototype.nGrams = Doc.prototype.ngrams + + /** n-grams with one word */ + Doc.prototype.unigrams = function(n) { + let arr = getGrams(tokenize(this), { max: 1, min: 1 }) + arr = sort(arr) + if (typeof n === 'number') { + arr = arr[n] + } + return arr + } + Doc.prototype.uniGrams = Doc.prototype.unigrams + + /** n-grams with two words */ + Doc.prototype.bigrams = function(n) { + let arr = getGrams(tokenize(this), { max: 2, min: 2 }) + arr = sort(arr) + if (typeof n === 'number') { + arr = arr[n] + } + return arr + } + Doc.prototype.biGrams = Doc.prototype.bigrams + + /** n-grams with three words */ + Doc.prototype.trigrams = function(n) { + let arr = getGrams(tokenize(this), { max: 3, min: 3 }) + arr = sort(arr) + if (typeof n === 'number') { + arr = arr[n] + } + return arr + } + Doc.prototype.triGrams = Doc.prototype.trigrams + + /** list all repeating sub-phrases, using the first word */ + Doc.prototype.startgrams = function(obj) { + let list = tokenize(this) + let arr = startGrams(list, obj || {}) + arr = sort(arr) + return arr + } + Doc.prototype.startGrams = Doc.prototype.startgrams + + /** list all repeating sub-phrases, connected to the last word of each phrase */ + Doc.prototype.endgrams = function(obj) { + let list = tokenize(this) + let arr = endGrams(list, obj || {}) + arr = sort(arr) + return arr + } + Doc.prototype.endGrams = Doc.prototype.endgrams + + /** list all repeating sub-phrases, connected to the last word of each phrase */ + Doc.prototype.edgegrams = function(obj) { + let list = tokenize(this) + let start = startGrams(list, obj || {}) + let end = endGrams(list, obj || {}) + // combine them together + let all = start.concat(end) + let combine = all.reduce((h, a) => { + if (h[a.normal]) { + h[a.normal].count += a.count + } else { + h[a.normal] = a + } + return h + }, {}) + let arr = Object.keys(combine).map(k => combine[k]) + arr = sort(arr) + return arr + } + Doc.prototype.edgeGrams = Doc.prototype.edgegrams +} +module.exports = addMethod diff --git a/plugins/ngrams/src/sort.js b/plugins/ngrams/src/sort.js new file mode 100644 index 000000000..534474457 --- /dev/null +++ b/plugins/ngrams/src/sort.js @@ -0,0 +1,21 @@ +const sort = function(arr) { + arr = arr.sort((a, b) => { + //first sort them by count + if (a.count > b.count) { + return -1 + } + if (a.count < b.count) { + return 1 + } + // in a tie, sort them by size + if (a.size > b.size) { + return -1 + } + if (a.size < b.size) { + return 1 + } + return 0 + }) + return arr +} +module.exports = sort diff --git a/plugins/ngrams/src/startGrams.js b/plugins/ngrams/src/startGrams.js new file mode 100644 index 000000000..f2d20faa4 --- /dev/null +++ b/plugins/ngrams/src/startGrams.js @@ -0,0 +1,47 @@ +const defaults = { + max: 4, + min: 1, +} + +const oneSize = function(list, size) { + let grams = {} + // count each instance + list.forEach(terms => { + for (let i = 0; i <= terms.length; i += 1) { + let slice = terms.slice(0, i) + if (slice.length === size) { + let str = slice.join(' ') + if (grams.hasOwnProperty(str)) { + grams[str].count += 1 + } else { + grams[str] = { + size: size, + count: 1, + } + } + } + } + }) + // turn them into an array + let arr = Object.keys(grams).map(k => { + grams[k].normal = k + return grams[k] + }) + return arr +} + +const startGrams = function(list, options) { + // support {size:2} syntax + if (options.size) { + options.min = options.size + options.max = options.size + } + let max = options.max || defaults.max + let min = options.min || defaults.min + let arr = [] + for (let size = min; size <= max; size++) { + arr = arr.concat(oneSize(list, size)) + } + return arr +} +module.exports = startGrams diff --git a/plugins/ngrams/src/tokenize.js b/plugins/ngrams/src/tokenize.js new file mode 100644 index 000000000..8cc134972 --- /dev/null +++ b/plugins/ngrams/src/tokenize.js @@ -0,0 +1,8 @@ +// tokenize by term +const tokenize = function(doc) { + let list = doc.json({ terms: { clean: true }, text: false }).map(o => { + return o.terms.map(t => t.clean) + }) + return list +} +module.exports = tokenize diff --git a/plugins/ngrams/tests/_lib.js b/plugins/ngrams/tests/_lib.js new file mode 100644 index 000000000..254633449 --- /dev/null +++ b/plugins/ngrams/tests/_lib.js @@ -0,0 +1,12 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + } + + module.exports = nlp +} diff --git a/plugins/ngrams/tests/edgegram.test.js b/plugins/ngrams/tests/edgegram.test.js new file mode 100644 index 000000000..84a1abbf4 --- /dev/null +++ b/plugins/ngrams/tests/edgegram.test.js @@ -0,0 +1,49 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('edgegram-sizes:', function(t) { + const r = nlp(`he is cool. john was cool. He is really nice.`) + + let arr = r.startGrams({ size: 5 }) + t.equal(arr.length, 0, 'no-overgrams') + + arr = r.startGrams({ size: 4 }) + t.equal(arr.length, 1, 'one-4-startgram') + arr = r.startGrams({ size: 3 }) + t.equal(arr.length, 3, 'found-3-startgrams') + arr = r.startGrams({ size: 2 }) + t.equal(arr.length, 2, 'found-2-startgrams') + + arr = r.endGrams({ size: 4 }) + t.equal(arr.length, 1, 'one-4-endgram') + arr = r.endGrams({ size: 3 }) + t.equal(arr.length, 3, 'found-3-endgram') + + arr = r.nGrams({ size: 5 }) + t.equal(arr.length, 0, 'zero-5-ngram') + arr = r.nGrams({ size: 4 }) + t.equal(arr.length, 1, 'one-4-ngram') + arr = r.nGrams({ size: 3 }) + t.equal(arr.length, 4, 'four-3-ngrams') + arr = r.nGrams({ size: 2 }) + t.equal(arr.length, 6, 'six-2-ngrams') + + t.end() +}) + +test('edgegram:', function(t) { + let doc = nlp('my birthday is June 5th my birthday') + let arr = doc.edgegrams() + t.equal(arr[0].normal, 'my birthday', 'combine edges') + t.equal(arr[0].count, 2, 'found both edges') + t.end() +}) + +test('start-sizes:', function(t) { + const r = nlp(`he is cool. john was cool. He is really nice.`) + const arr = r.startGrams() + t.equal(arr[0].normal, 'he is', 'sorted-by-freq') + t.equal(arr[0].count, 2, 'normalized-counted') + t.equal(arr[0].size, 2, 'normalized-counted') + t.end() +}) diff --git a/plugins/ngrams/tests/misc.test.js b/plugins/ngrams/tests/misc.test.js new file mode 100644 index 000000000..e1369863a --- /dev/null +++ b/plugins/ngrams/tests/misc.test.js @@ -0,0 +1,24 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('misc ngrams', function(t) { + let doc = nlp(`quickly, suddenly`) + t.equal(doc.ngrams().length, 3, 'found three ngrams') + + doc = nlp(`john, bill, joe`) + t.equal(doc.unigrams().length, 3, 'found three unigrams') + + doc = nlp(`john, bill, joe`) + t.equal(doc.bigrams().length, 2, 'found 2 bigrams') + + doc = nlp(`john, bill, joe`) + t.equal(doc.trigrams().length, 1, 'found 1 trigrams') + + doc = nlp('i am in houston texas. i am a good person. so i think he is a good person.') + let arr = doc.endgrams({ size: 2 }) || [] + t.equal(arr.length, 2, 'found 2 endgrams of size-2') + let first = arr[0] || {} + t.equal(first.normal, 'good person', 'found good person') + t.equal(first.count, 2, 'found 2 good person results') + t.end() +}) diff --git a/plugins/ngrams/tests/ngram.test.js b/plugins/ngrams/tests/ngram.test.js new file mode 100644 index 000000000..6dfe998a0 --- /dev/null +++ b/plugins/ngrams/tests/ngram.test.js @@ -0,0 +1,60 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('ngram-test:', function(t) { + const r = nlp('he is strong. he is cool') + const arr = r.ngrams() + + t.equal(arr[0].normal, 'he is', 'sorted-by-freq') + t.equal(arr[0].count, 2, 'normalized-counted') + t.equal(arr[0].size, 2, 'normalized-counted') + + t.equal(arr.length, 9, 'ngram-length') + t.end() +}) + +test('sort-bigrams:', function(t) { + const r = nlp('he is strong. he is cool') + const arr = r.ngrams({ + size: 2, + }) + t.equal(arr[0].normal, 'he is', '#1-by-freq') + t.equal(arr[1].normal, 'is strong', '#2-by-freq') + t.equal(arr[2].normal, 'is cool', '#3-by-freq') + t.equal(arr.length, 3, 'ngram-length') + t.end() +}) + +test('contractions-support:', function(t) { + const r = nlp("It's free for me and free for you") + const arr = r.ngrams() + const obj = arr.find(o => o.normal === 'free for') + t.equal(obj.count, 2, 'dont include empty contraction') + t.end() +}) + +test('ngrams-options:', function(t) { + let doc = nlp('one two three four five, one two three four five, one two three four five') + let arr = doc.ngrams({ + max: 5, + }) + t.equal(arr[0].size, 5, 'ngram-max-size-5') + arr = doc.ngrams({ + max: 2, + }) + t.equal(arr[0].size, 2, 'ngram-max-size-2') + arr = doc.ngrams({ + max: 9, + }) + t.equal(arr[0].size, 5, 'ngram-max-size-9') + + arr = doc.ngrams({ + size: 2, + }) + t.equal(arr[0].size, 2, 'ngram-size-2') + arr = doc.ngrams({ + size: 4, + }) + t.equal(arr[0].size, 4, 'ngram-size-4') + t.end() +}) diff --git a/plugins/numbers/.gitignore b/plugins/numbers/.gitignore new file mode 100644 index 000000000..8b9247097 --- /dev/null +++ b/plugins/numbers/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +coverage/ +.DS_Store +.env +.nyc_output/ +.vscode \ No newline at end of file diff --git a/plugins/numbers/README.md b/plugins/numbers/README.md new file mode 100644 index 000000000..f5fd7d36b --- /dev/null +++ b/plugins/numbers/README.md @@ -0,0 +1,57 @@ +
+ + +
parse and format numbers in text
+
a plugin for compromise
+ + + + + + + + + + +
+
+ +
+ npm install compromise-numbers +
+ +```js +const nlp = require('compromise') +nlp.extend(require('compromise-numbers')) + +let doc = nlp('I’d like to request seventeen dollars for a push broom rebristling') +doc.numbers().debug() +// 17 +``` + +## [Demo](https://observablehq.com/@spencermountain/compromise-values) + +## API + +- **[.numbers()](https://observablehq.com/@spencermountain/compromise-values)** - grab all written and numeric values + - **[.numbers().json()](https://observablehq.com/@spencermountain/compromise-values)** - overloaded output with number metadata + - **[.money()](https://observablehq.com/@spencermountain/compromise-values)** - things like `'$2.50'` + - **[.fractions()](https://observablehq.com/@spencermountain/compromise-values)** - things like `1/3rd` + - **[.money()](https://observablehq.com/@spencermountain/compromise-values)** - things like `twenty bucks` + - **[.numbers().toText()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `five` or `fifth` + - **[.numbers().toNumber()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `5` or `5th` + - **[.numbers().toOrdinal()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `fifth` or `5th` + - **[.numbers().toCardinal()](https://observablehq.com/@spencermountain/compromise-values)** - convert number to `five` or `5` + - **[.numbers().add(n)](https://observablehq.com/@spencermountain/compromise-values)** - increase number by n + - **[.numbers().subtract(n)](https://observablehq.com/@spencermountain/compromise-values)** - decrease number by n + - **[.numbers().increment()](https://observablehq.com/@spencermountain/compromise-values)** - increase number by 1 + - **[.numbers().decrement()](https://observablehq.com/@spencermountain/compromise-values)** - decrease number by 1 + - **[.numbers().isEqual(n)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers with this value + - **[.numbers().greaterThan(min)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers bigger than n + - **[.numbers().lessThan(max)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers smaller than n + - **[.numbers().between(min, max)](https://observablehq.com/@spencermountain/compromise-values)** - return numbers between min and max + - **[.numbers().isOrdinal()](https://observablehq.com/@spencermountain/compromise-values)** - return only ordinal numbers + - **[.numbers().isCardinal()](https://observablehq.com/@spencermountain/compromise-values)** - return only cardinal numbers + - **[.numbers().toLocaleString()](https://observablehq.com/@spencermountain/compromise-values)** - add commas, or nicer formatting for numbers + +MIT diff --git a/plugins/numbers/builds/compromise-numbers.js b/plugins/numbers/builds/compromise-numbers.js new file mode 100644 index 000000000..df3e560a3 --- /dev/null +++ b/plugins/numbers/builds/compromise-numbers.js @@ -0,0 +1,1237 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseNumbers = factory()); +}(this, (function () { 'use strict'; + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + var tens = 'twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty'; + var teens = 'eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen'; // this is a bit of a mess + + var findNumbers = function findNumbers(doc, n) { + var match = doc.match('#Value+'); //"50 83" + + if (match.has('#NumericValue #NumericValue')) { + //a comma may mean two numbers + if (match.has('#Value @hasComma #Value')) { + match.splitAfter('@hasComma'); + } else { + match = match.splitAfter('#NumericValue'); + } + } //three-length + + + if (match.has('#Value #Value #Value') && !match.has('#Multiple')) { + //twenty-five-twenty + if (match.has('(' + tens + ') #Cardinal #Cardinal')) { + match = match.splitAfter('(' + tens + ') #Cardinal'); + } + } //two-length ones + + + if (match.has('#Value #Value')) { + //june 21st 1992 is two seperate values + if (match.has('#NumericValue #NumericValue')) { + match = match.splitOn('#Year'); + } //sixty fifteen + + + if (match.has('(' + tens + ') (' + teens + ')')) { + match = match.splitAfter('(' + tens + ')'); + } //"72 82" + + + var _double = match.match('#Cardinal #Cardinal'); + + if (_double.found && !match.has('(point|decimal)')) { + //not 'two hundred' + if (!_double.has('#Cardinal (#Multiple|point|decimal)')) { + //one proper way, 'twenty one', or 'hundred one' + if (!_double.has('(' + tens + ') #Cardinal') && !_double.has('#Multiple #Value')) { + // double = double.firstTerm() + _double.terms().forEach(function (d) { + match = match.splitOn(d); + }); + } + } + } //seventh fifth + + + if (match.match('#Ordinal #Ordinal').match('#TextValue').found && !match.has('#Multiple')) { + //the one proper way, 'twenty first' + if (!match.has('(' + tens + ') #Ordinal')) { + match = match.splitAfter('#Ordinal'); + } + } //fifth five + + + if (match.has('#Ordinal #Cardinal')) { + match = match.splitBefore('#Cardinal+'); + } //five 2017 (support '5 hundred', and 'twenty 5' + + + if (match.has('#TextValue #NumericValue') && !match.has('(' + tens + '|#Multiple)')) { + match = match.splitBefore('#NumericValue+'); + } + } //5-8 + + + if (match.has('#NumberRange')) { + match = match.splitAfter('#NumberRange'); + } //grab (n)th result + + + if (typeof n === 'number') { + match = match.get(n); + } + + return match; + }; + + var find = findNumbers; + + //support global multipliers, like 'half-million' by doing 'million' then multiplying by 0.5 + var findModifiers = function findModifiers(str) { + var mults = [{ + reg: /^(minus|negative)[\s\-]/i, + mult: -1 + }, { + reg: /^(a\s)?half[\s\-](of\s)?/i, + mult: 0.5 + } // { + // reg: /^(a\s)?quarter[\s\-]/i, + // mult: 0.25 + // } + ]; + + for (var i = 0; i < mults.length; i++) { + if (mults[i].reg.test(str) === true) { + return { + amount: mults[i].mult, + str: str.replace(mults[i].reg, '') + }; + } + } + + return { + amount: 1, + str: str + }; + }; + + var findModifiers_1 = findModifiers; + + var data = { + ones: { + zeroth: 0, + first: 1, + second: 2, + third: 3, + fourth: 4, + fifth: 5, + sixth: 6, + seventh: 7, + eighth: 8, + ninth: 9, + zero: 0, + one: 1, + two: 2, + three: 3, + four: 4, + five: 5, + six: 6, + seven: 7, + eight: 8, + nine: 9 + }, + teens: { + tenth: 10, + eleventh: 11, + twelfth: 12, + thirteenth: 13, + fourteenth: 14, + fifteenth: 15, + sixteenth: 16, + seventeenth: 17, + eighteenth: 18, + nineteenth: 19, + ten: 10, + eleven: 11, + twelve: 12, + thirteen: 13, + fourteen: 14, + fifteen: 15, + sixteen: 16, + seventeen: 17, + eighteen: 18, + nineteen: 19 + }, + tens: { + twentieth: 20, + thirtieth: 30, + fortieth: 40, + fourtieth: 40, + fiftieth: 50, + sixtieth: 60, + seventieth: 70, + eightieth: 80, + ninetieth: 90, + twenty: 20, + thirty: 30, + forty: 40, + fourty: 40, + fifty: 50, + sixty: 60, + seventy: 70, + eighty: 80, + ninety: 90 + }, + multiples: { + hundredth: 100, + thousandth: 1000, + millionth: 1e6, + billionth: 1e9, + trillionth: 1e12, + quadrillionth: 1e15, + quintillionth: 1e18, + sextillionth: 1e21, + septillionth: 1e24, + hundred: 100, + thousand: 1000, + million: 1e6, + billion: 1e9, + trillion: 1e12, + quadrillion: 1e15, + quintillion: 1e18, + sextillion: 1e21, + septillion: 1e24, + grand: 1000 + } + }; + + var isValid = function isValid(w, has) { + if (data.ones.hasOwnProperty(w)) { + if (has.ones || has.teens) { + return false; + } + } else if (data.teens.hasOwnProperty(w)) { + if (has.ones || has.teens || has.tens) { + return false; + } + } else if (data.tens.hasOwnProperty(w)) { + if (has.ones || has.teens || has.tens) { + return false; + } + } + + return true; + }; + + var validate = isValid; + + var parseDecimals = function parseDecimals(arr) { + var str = '0.'; + + for (var i = 0; i < arr.length; i++) { + var w = arr[i]; + + if (data.ones.hasOwnProperty(w) === true) { + str += data.ones[w]; + } else if (data.teens.hasOwnProperty(w) === true) { + str += data.teens[w]; + } else if (data.tens.hasOwnProperty(w) === true) { + str += data.tens[w]; + } else if (/^[0-9]$/.test(w) === true) { + str += w; + } else { + return 0; + } + } + + return parseFloat(str); + }; + + var parseDecimals_1 = parseDecimals; + + //parse a string like "4,200.1" into Number 4200.1 + var parseNumeric = function parseNumeric(str) { + //remove ordinal - 'th/rd' + str = str.replace(/1st$/, '1'); + str = str.replace(/2nd$/, '2'); + str = str.replace(/3rd$/, '3'); + str = str.replace(/([4567890])r?th$/, '$1'); //remove prefixes + + str = str.replace(/^[$€¥£¢]/, ''); //remove suffixes + + str = str.replace(/[%$€¥£¢]$/, ''); //remove commas + + str = str.replace(/,/g, ''); //split '5kg' from '5' + + str = str.replace(/([0-9])([a-z\u00C0-\u00FF]{1,2})$/, '$1'); + return str; + }; + + var parseNumeric_1 = parseNumeric; + + var improperFraction = /^([0-9,\. ]+)\/([0-9,\. ]+)$/; //some numbers we know + + var casualForms = { + // 'a few': 3, + 'a couple': 2, + 'a dozen': 12, + 'two dozen': 24, + zero: 0 + }; // a 'section' is something like 'fifty-nine thousand' + // turn a section into something we can add to - like 59000 + + var section_sum = function section_sum(obj) { + return Object.keys(obj).reduce(function (sum, k) { + sum += obj[k]; + return sum; + }, 0); + }; //turn a string into a number + + + var parse = function parse(str) { + //convert some known-numbers + if (casualForms.hasOwnProperty(str) === true) { + return casualForms[str]; + } //'a/an' is 1 + + + if (str === 'a' || str === 'an') { + return 1; + } + + var modifier = findModifiers_1(str); + str = modifier.str; + var last_mult = null; + var has = {}; + var sum = 0; + var isNegative = false; + var terms = str.split(/[ -]/); + + for (var i = 0; i < terms.length; i++) { + var w = terms[i]; + w = parseNumeric_1(w); + + if (!w || w === 'and') { + continue; + } + + if (w === '-' || w === 'negative') { + isNegative = true; + continue; + } + + if (w.charAt(0) === '-') { + isNegative = true; + w = w.substr(1); + } //decimal mode + + + if (w === 'point') { + sum += section_sum(has); + sum += parseDecimals_1(terms.slice(i + 1, terms.length)); + sum *= modifier.amount; + return sum; + } //improper fraction + + + var fm = w.match(improperFraction); + + if (fm) { + var num = parseFloat(fm[1].replace(/[, ]/g, '')); + var denom = parseFloat(fm[2].replace(/[, ]/g, '')); + + if (denom) { + sum += num / denom || 0; + } + + continue; + } //prevent mismatched units, like 'seven eleven' + + + if (validate(w, has) === false) { + return null; + } //buildOut section, collect 'has' values + + + if (/^[0-9\.]+$/.test(w)) { + has['ones'] = parseFloat(w); //not technically right + } else if (data.ones.hasOwnProperty(w) === true) { + has['ones'] = data.ones[w]; + } else if (data.teens.hasOwnProperty(w) === true) { + has['teens'] = data.teens[w]; + } else if (data.tens.hasOwnProperty(w) === true) { + has['tens'] = data.tens[w]; + } else if (data.multiples.hasOwnProperty(w) === true) { + var mult = data.multiples[w]; //something has gone wrong : 'two hundred five hundred' + + if (mult === last_mult) { + return null; + } //support 'hundred thousand' + //this one is tricky.. + + + if (mult === 100 && terms[i + 1] !== undefined) { + // has['hundreds']= + var w2 = terms[i + 1]; + + if (data.multiples[w2]) { + mult *= data.multiples[w2]; //hundredThousand/hundredMillion + + i += 1; + } + } //natural order of things + //five thousand, one hundred.. + + + if (last_mult === null || mult < last_mult) { + sum += (section_sum(has) || 1) * mult; + last_mult = mult; + has = {}; + } else { + //maybe hundred .. thousand + sum += section_sum(has); + last_mult = mult; + sum = (sum || 1) * mult; + has = {}; + } + } + } //dump the remaining has values + + + sum += section_sum(has); //post-process add modifier + + sum *= modifier.amount; + sum *= isNegative ? -1 : 1; //dont return 0, if it went straight-through + + if (sum === 0 && Object.keys(has).length === 0) { + return null; + } + + return sum; + }; + + var toNumber = parse; + + var parseNumber = function parseNumber(p) { + var str = p.text('reduced'); // is it in '3,123' format? + + var hasComma = /[0-9],[0-9]/.test(p.text('text')); + str = str.replace(/,/g, ''); //parse a numeric-number (easy) + + var arr = str.split(/^([^0-9]*)([0-9.,]*)([^0-9]*)$/); + + if (arr && arr[2] && p.terms().length < 2) { + var _num = parseFloat(arr[2] || str); //ensure that num is an actual number + + + if (typeof _num !== 'number') { + _num = null; + } // strip an ordinal off the suffix + + + var suffix = arr[3] || ''; + + if (suffix === 'st' || suffix === 'nd' || suffix === 'rd' || suffix === 'th') { + suffix = ''; + } // support M for million, k for thousand + + + if (suffix === 'm' || suffix === 'M') { + _num *= 1000000; + suffix = ''; + } + + if (suffix === 'k' || suffix === 'k') { + _num *= 1000; + suffix = ''; + } + + return { + hasComma: hasComma, + prefix: arr[1] || '', + num: _num, + suffix: suffix + }; + } //parse a text-numer (harder) + + + var num = toNumber(str); + return { + hasComma: hasComma, + prefix: '', + num: num, + suffix: '' + }; + }; + + var parse$1 = parseNumber; + + // handle 'one bottle', 'two bottles' + var agreeUnits = function agreeUnits(agree, val, obj) { + if (agree === false) { + return; + } + + var unit = val.lookAhead('^(#Unit|#Noun)'); // don't do these + + if (unit.has('(#Address|#Money|#Percent)') || val.has('#Ordinal')) { + return; + } + + if (obj.num === 1) { + unit.nouns().toSingular(); + } else if (unit.has('#Singular')) { + unit.nouns().toPlural(); + } + }; + + var _agreeUnits = agreeUnits; + + /** + * turn big numbers, like 2.3e+22, into a string with a ton of trailing 0's + * */ + var numToString = function numToString(n) { + if (n < 1000000) { + return String(n); + } + + var str; + + if (typeof n === 'number') { + str = n.toFixed(0); + } else { + str = n; + } + + if (str.indexOf('e+') === -1) { + return str; + } + + return str.replace('.', '').split('e+').reduce(function (p, b) { + return p + Array(b - p.length + 2).join(0); + }); + }; + + var _toString = numToString; // console.log(numToString(2.5e+22)); + + /** + * turns an integer/float into.ber, like 'fifty-five' + */ + + var tens_mapping = [['ninety', 90], ['eighty', 80], ['seventy', 70], ['sixty', 60], ['fifty', 50], ['forty', 40], ['thirty', 30], ['twenty', 20]]; + var ones_mapping = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']; + var sequence = [[1e24, 'septillion'], [1e20, 'hundred sextillion'], [1e21, 'sextillion'], [1e20, 'hundred quintillion'], [1e18, 'quintillion'], [1e17, 'hundred quadrillion'], [1e15, 'quadrillion'], [1e14, 'hundred trillion'], [1e12, 'trillion'], [1e11, 'hundred billion'], [1e9, 'billion'], [1e8, 'hundred million'], [1e6, 'million'], [100000, 'hundred thousand'], [1000, 'thousand'], [100, 'hundred'], [1, 'one']]; //turn number into an array of magnitudes, like [[5, million], [2, hundred]] + + var breakdown_magnitudes = function breakdown_magnitudes(num) { + var working = num; + var have = []; + sequence.forEach(function (a) { + if (num >= a[0]) { + var howmany = Math.floor(working / a[0]); + working -= howmany * a[0]; + + if (howmany) { + have.push({ + unit: a[1], + count: howmany + }); + } + } + }); + return have; + }; //turn numbers from 100-0 into their text + + + var breakdown_hundred = function breakdown_hundred(num) { + var arr = []; + + if (num > 100) { + return arr; //something bad happened.. + } + + for (var i = 0; i < tens_mapping.length; i++) { + if (num >= tens_mapping[i][1]) { + num -= tens_mapping[i][1]; + arr.push(tens_mapping[i][0]); + } + } //(hopefully) we should only have 20-0 now + + + if (ones_mapping[num]) { + arr.push(ones_mapping[num]); + } + + return arr; + }; + /** print-out 'point eight nine'*/ + + + var handle_decimal = function handle_decimal(num) { + var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']; + var arr = []; //parse it out like a string, because js math is such shit + + var str = _toString(num); + var decimal = str.match(/\.([0-9]+)/); + + if (!decimal || !decimal[0]) { + return arr; + } + + arr.push('point'); + var decimals = decimal[0].split(''); + + for (var i = 0; i < decimals.length; i++) { + arr.push(names[decimals[i]]); + } + + return arr; + }; + /** turns an integer into a textual number */ + + + var to_text = function to_text(num) { + // handle zero, quickly + if (num === 0 || num === '0') { + return 'zero'; // no? + } //big numbers, north of sextillion, aren't gonna work well.. + //keep them small.. + + + if (num > 1e21) { + num = _toString(num); + } + + var arr = []; //handle negative numbers + + if (num < 0) { + arr.push('minus'); + num = Math.abs(num); + } //break-down into units, counts + + + var units = breakdown_magnitudes(num); //build-up the string from its components + + for (var i = 0; i < units.length; i++) { + var unit_name = units[i].unit; + + if (unit_name === 'one') { + unit_name = ''; //put an 'and' in here + + if (arr.length > 1) { + arr.push('and'); + } + } + + arr = arr.concat(breakdown_hundred(units[i].count)); + arr.push(unit_name); + } //also support decimals - 'point eight' + + + arr = arr.concat(handle_decimal(num)); //remove empties + + arr = arr.filter(function (s) { + return s; + }); + + if (arr.length === 0) { + arr[0] = ''; + } + + return arr.join(' '); + }; + + var toText = to_text; // console.log(to_text(-1000.8)); + + /** + * turn a number like 5 into an ordinal like 5th + */ + + var numOrdinal = function numOrdinal(num) { + if (!num && num !== 0) { + return null; + } //the teens are all 'th' + + + var tens = num % 100; + + if (tens > 10 && tens < 20) { + return String(num) + 'th'; + } //the rest of 'em + + + var mapping = { + 0: 'th', + 1: 'st', + 2: 'nd', + 3: 'rd' + }; + var str = _toString(num); + var last = str.slice(str.length - 1, str.length); + + if (mapping[last]) { + str += mapping[last]; + } else { + str += 'th'; + } + + return str; + }; + + var numOrdinal_1 = numOrdinal; + + var irregulars = { + one: 'first', + two: 'second', + three: 'third', + five: 'fifth', + eight: 'eighth', + nine: 'ninth', + twelve: 'twelfth', + twenty: 'twentieth', + thirty: 'thirtieth', + forty: 'fortieth', + fourty: 'fourtieth', + fifty: 'fiftieth', + sixty: 'sixtieth', + seventy: 'seventieth', + eighty: 'eightieth', + ninety: 'ninetieth' + }; + /** + * convert a javascript number to 'twentieth' format + * */ + + var textOrdinal = function textOrdinal(num) { + var words = toText(num).split(' '); //convert the last number to an ordinal + + var last = words[words.length - 1]; + + if (irregulars.hasOwnProperty(last)) { + words[words.length - 1] = irregulars[last]; + } else { + words[words.length - 1] = last.replace(/y$/, 'i') + 'th'; + } + + return words.join(' '); + }; + + var textOrdinal_1 = textOrdinal; + + var prefixes = { + '¢': 'cents', + $: 'dollars', + '£': 'pounds', + '¥': 'yen', + '€': 'euros', + '₡': 'colón', + '฿': 'baht', + '₭': 'kip', + '₩': 'won', + '₹': 'rupees', + '₽': 'ruble', + '₺': 'liras' + }; + var suffixes = { + '%': 'percent', + s: 'seconds', + cm: 'centimetres', + km: 'kilometres' + }; + var _symbols = { + prefixes: prefixes, + suffixes: suffixes + }; + + var prefixes$1 = _symbols.prefixes; + var suffixes$1 = _symbols.suffixes; + var isCurrency = { + usd: true, + eur: true, + jpy: true, + gbp: true, + cad: true, + aud: true, + chf: true, + cny: true, + hkd: true, + nzd: true, + kr: true, + rub: true + }; // convert $ to 'dollars', etc + + var prefixToText = function prefixToText(obj) { + // turn 5% to 'five percent' + if (prefixes$1.hasOwnProperty(obj.prefix)) { + obj.suffix += prefixes$1[obj.prefix]; + obj.prefix = ''; + } //turn 5km to 'five kilometres' + + + if (suffixes$1.hasOwnProperty(obj.suffix)) { + obj.suffix = suffixes$1[obj.suffix]; + } //uppercase lost case for 'USD', etc + + + if (isCurrency.hasOwnProperty(obj.suffix)) { + obj.suffix = obj.suffix.toUpperCase(); + } // add a space, if it exists + + + if (obj.suffix) { + obj.suffix = ' ' + obj.suffix; + } + + return obj; + }; //business-logic for converting a cardinal-number to other forms + + + var makeNumber = function makeNumber(obj, isText, isOrdinal) { + var num = String(obj.num); + + if (isText) { + obj = prefixToText(obj); + + if (isOrdinal) { + //ordinal-text + num = textOrdinal_1(num); + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); + } //cardinal-text + + + num = toText(num); + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); + } //ordinal-number + + + if (isOrdinal) { + num = numOrdinal_1(num); // support '5th percent' + + obj = prefixToText(obj); + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); + } // support comma format + + + if (obj.hasComma === true) { + num = obj.num.toLocaleString(); + } // cardinal-number + + + num = _toString(num); // support very large numbers + + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); + }; + + var makeNumber_1 = makeNumber; + + var methods = { + /** overloaded json method with additional number information */ + json: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var obj = parse$1(doc); + json.prefix = obj.prefix; + json.number = obj.num; + json.suffix = obj.suffix; + json.cardinal = makeNumber_1(obj, false, false); + json.ordinal = makeNumber_1(obj, false, true); + json.textCardinal = makeNumber_1(obj, true, false); + json.textOrdinal = makeNumber_1(obj, true, true); + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + }, + + /** two of what? */ + units: function units() { + return this.lookAhead('^(#Unit|#Noun)'); + }, + + /** return only ordinal numbers */ + isOrdinal: function isOrdinal() { + return this["if"]('#Ordinal'); + }, + + /** return only cardinal numbers*/ + isCardinal: function isCardinal() { + return this["if"]('#Cardinal'); + }, + + /** convert to numeric form like '8' or '8th' */ + toNumber: function toNumber() { + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, false, val.has('#Ordinal')); + val.replaceWith(str, true); + val.tag('NumericValue'); + }); + return this; + }, + + /** add commas, or nicer formatting for numbers */ + toLocaleString: function toLocaleString() { + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + obj.num = obj.num.toLocaleString(); + var str = makeNumber_1(obj, false, val.has('#Ordinal')); + val.replaceWith(str, true); + }); + return this; + }, + + /** convert to text form - like 'eight' or 'eigth'*/ + toText: function toText() { + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, true, val.has('#Ordinal')); + val.replaceWith(str, true); + val.tag('TextValue'); + }); + return this; + }, + + /** convert to cardinal form, like 'eight', or '8' */ + toCardinal: function toCardinal(agree) { + var m = this["if"]('#Ordinal'); + m.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, val.has('#TextValue'), false); + val.replaceWith(str, true, true); + val.tag('Cardinal'); // turn unit into plural -> 'seven beers' + + _agreeUnits(agree, val, obj); + }); + return this; + }, + + /** convert to ordinal form, like 'eighth', or '8th' */ + toOrdinal: function toOrdinal() { + var _this = this; + + var m = this["if"]('#Cardinal'); + m.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, val.has('#TextValue'), true); + val.replaceWith(str, true, true); + val.tag('Ordinal'); // turn unit into singular -> 'seventh beer' + + var unit = _this.lookAhead('^#Plural'); + + if (unit.found) { + unit.nouns().toSingular(); + } + }); + return this; + }, + + /** return only numbers that are == n */ + isEqual: function isEqual(n) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num === n; + }); + }, + + /** return only numbers that are > n*/ + greaterThan: function greaterThan(n) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num > n; + }); + }, + + /** return only numbers that are < n*/ + lessThan: function lessThan(n) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num < n; + }); + }, + + /** return only numbers > min and < max */ + between: function between(min, max) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num > min && num < max; + }); + }, + + /** set these number to n */ + set: function set(n, agree) { + if (n === undefined) { + return this; // don't bother + } + + if (typeof n === 'string') { + n = toNumber(n); + } + + this.forEach(function (val) { + var obj = parse$1(val); + obj.num = n; + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, val.has('#TextValue'), val.has('#Ordinal')); + val.replaceWith(str, true, true); // handle plural/singular unit + + _agreeUnits(agree, val, obj); + }); + return this; + }, + add: function add(n, agree) { + if (!n) { + return this; // don't bother + } + + if (typeof n === 'string') { + n = toNumber(n); + } + + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + obj.num += n; + var str = makeNumber_1(obj, val.has('#TextValue'), val.has('#Ordinal')); + val.replaceWith(str, true, true); // handle plural/singular unit + + _agreeUnits(agree, val, obj); + }); + return this; + }, + + /** decrease each number by n*/ + subtract: function subtract(n, agree) { + return this.add(n * -1, agree); + }, + + /** increase each number by 1 */ + increment: function increment(agree) { + this.add(1, agree); + return this; + }, + + /** decrease each number by 1 */ + decrement: function decrement(agree) { + this.add(-1, agree); + return this; + }, + /// ---- + + /** return things like 1/3rd */ + fractions: function fractions(n) { + var m = this.match('#Fraction'); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; + }, + + /** return things like CCXX*/ + romanNumerals: function romanNumerals(n) { + var m = this.match('#RomanNumeral').numbers(); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; + }, + + /** return things like $4.50*/ + money: function money(n) { + var m = this.splitOn('@hasComma'); + m = m.match('#Money+ #Currency?'); + m = m.numbers(); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; + } + }; // aliases + + methods.toNice = methods.toLocaleString; + methods.isBetween = methods.between; + methods.minus = methods.subtract; + methods.plus = methods.add; + methods.equals = methods.isEqual; + var methods_1 = methods; + + var multiples = '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)'; // improved tagging for numbers + + var tagger = function tagger(doc) { + doc.match(multiples).tag('#Multiple'); // in the 400s + + doc.match('the [/[0-9]+s$/]').tag('#Plural'); //half a million + + doc.match('half a? #Value').tag('Value', 'half-a-value'); //(quarter not ready) + //five and a half + + doc.match('#Value and a (half|quarter)').tag('Value', 'value-and-a-half'); //one hundred and seven dollars + + doc.match('#Money and #Money #Currency?').tag('Money', 'money-and-money'); + }; + + var tagger_1 = tagger; + + var tags = { + Fraction: { + isA: 'Value' + }, + Multiple: { + isA: 'Value' + } + }; + + /** adds .numbers() method */ + + var addMethod = function addMethod(Doc, world) { + // add tags to our tagset + world.addTags(tags); // additional tagging before running the number-parser + + world.postProcess(tagger_1); + /** a list of number values, and their units */ + + var Numbers = + /*#__PURE__*/ + function (_Doc) { + _inherits(Numbers, _Doc); + + function Numbers() { + _classCallCheck(this, Numbers); + + return _possibleConstructorReturn(this, _getPrototypeOf(Numbers).apply(this, arguments)); + } + + return Numbers; + }(Doc); //aliases + + + Object.assign(Numbers.prototype, methods_1); + /** find all numbers and values */ + + Doc.prototype.numbers = function (n) { + var match = find(this, n); + return new Numbers(match.list, this, this.world); + }; // alias for reverse-compatibility + + + Doc.prototype.values = Doc.prototype.numbers; + return Doc; + }; + + var src = addMethod; + + return src; + +}))); +//# sourceMappingURL=compromise-numbers.js.map diff --git a/plugins/numbers/builds/compromise-numbers.js.map b/plugins/numbers/builds/compromise-numbers.js.map new file mode 100644 index 000000000..554998b10 --- /dev/null +++ b/plugins/numbers/builds/compromise-numbers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-numbers.js","sources":["../src/find.js","../src/convert/toNumber/findModifiers.js","../src/convert/toNumber/data.js","../src/convert/toNumber/validate.js","../src/convert/toNumber/parseDecimals.js","../src/convert/toNumber/parseNumeric.js","../src/convert/toNumber/index.js","../src/parse.js","../src/_agreeUnits.js","../src/convert/_toString.js","../src/convert/toText/index.js","../src/convert/toOrdinal/numOrdinal.js","../src/convert/toOrdinal/textOrdinal.js","../src/convert/_symbols.js","../src/convert/makeNumber.js","../src/methods.js","../src/tagger.js","../src/tags.js","../src/index.js"],"sourcesContent":["const tens = 'twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty'\nconst teens = 'eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen'\n\n// this is a bit of a mess\nconst findNumbers = function(doc, n) {\n let match = doc.match('#Value+')\n\n //\"50 83\"\n if (match.has('#NumericValue #NumericValue')) {\n //a comma may mean two numbers\n if (match.has('#Value @hasComma #Value')) {\n match.splitAfter('@hasComma')\n } else {\n match = match.splitAfter('#NumericValue')\n }\n }\n //three-length\n if (match.has('#Value #Value #Value') && !match.has('#Multiple')) {\n //twenty-five-twenty\n if (match.has('(' + tens + ') #Cardinal #Cardinal')) {\n match = match.splitAfter('(' + tens + ') #Cardinal')\n }\n }\n\n //two-length ones\n if (match.has('#Value #Value')) {\n //june 21st 1992 is two seperate values\n if (match.has('#NumericValue #NumericValue')) {\n match = match.splitOn('#Year')\n }\n //sixty fifteen\n if (match.has('(' + tens + ') (' + teens + ')')) {\n match = match.splitAfter('(' + tens + ')')\n }\n //\"72 82\"\n let double = match.match('#Cardinal #Cardinal')\n if (double.found && !match.has('(point|decimal)')) {\n //not 'two hundred'\n if (!double.has('#Cardinal (#Multiple|point|decimal)')) {\n //one proper way, 'twenty one', or 'hundred one'\n if (!double.has('(' + tens + ') #Cardinal') && !double.has('#Multiple #Value')) {\n // double = double.firstTerm()\n double.terms().forEach(d => {\n match = match.splitOn(d)\n })\n }\n }\n }\n //seventh fifth\n if (match.match('#Ordinal #Ordinal').match('#TextValue').found && !match.has('#Multiple')) {\n //the one proper way, 'twenty first'\n if (!match.has('(' + tens + ') #Ordinal')) {\n match = match.splitAfter('#Ordinal')\n }\n }\n //fifth five\n if (match.has('#Ordinal #Cardinal')) {\n match = match.splitBefore('#Cardinal+')\n }\n //five 2017 (support '5 hundred', and 'twenty 5'\n if (match.has('#TextValue #NumericValue') && !match.has('(' + tens + '|#Multiple)')) {\n match = match.splitBefore('#NumericValue+')\n }\n }\n //5-8\n if (match.has('#NumberRange')) {\n match = match.splitAfter('#NumberRange')\n }\n //grab (n)th result\n if (typeof n === 'number') {\n match = match.get(n)\n }\n return match\n}\nmodule.exports = findNumbers\n","//support global multipliers, like 'half-million' by doing 'million' then multiplying by 0.5\nconst findModifiers = str => {\n const mults = [\n {\n reg: /^(minus|negative)[\\s\\-]/i,\n mult: -1,\n },\n {\n reg: /^(a\\s)?half[\\s\\-](of\\s)?/i,\n mult: 0.5,\n },\n // {\n // reg: /^(a\\s)?quarter[\\s\\-]/i,\n // mult: 0.25\n // }\n ]\n for (let i = 0; i < mults.length; i++) {\n if (mults[i].reg.test(str) === true) {\n return {\n amount: mults[i].mult,\n str: str.replace(mults[i].reg, ''),\n }\n }\n }\n return {\n amount: 1,\n str: str,\n }\n}\n\nmodule.exports = findModifiers\n","module.exports = {\n ones: {\n zeroth: 0,\n first: 1,\n second: 2,\n third: 3,\n fourth: 4,\n fifth: 5,\n sixth: 6,\n seventh: 7,\n eighth: 8,\n ninth: 9,\n zero: 0,\n one: 1,\n two: 2,\n three: 3,\n four: 4,\n five: 5,\n six: 6,\n seven: 7,\n eight: 8,\n nine: 9,\n },\n teens: {\n tenth: 10,\n eleventh: 11,\n twelfth: 12,\n thirteenth: 13,\n fourteenth: 14,\n fifteenth: 15,\n sixteenth: 16,\n seventeenth: 17,\n eighteenth: 18,\n nineteenth: 19,\n ten: 10,\n eleven: 11,\n twelve: 12,\n thirteen: 13,\n fourteen: 14,\n fifteen: 15,\n sixteen: 16,\n seventeen: 17,\n eighteen: 18,\n nineteen: 19,\n },\n tens: {\n twentieth: 20,\n thirtieth: 30,\n fortieth: 40,\n fourtieth: 40,\n fiftieth: 50,\n sixtieth: 60,\n seventieth: 70,\n eightieth: 80,\n ninetieth: 90,\n twenty: 20,\n thirty: 30,\n forty: 40,\n fourty: 40,\n fifty: 50,\n sixty: 60,\n seventy: 70,\n eighty: 80,\n ninety: 90,\n },\n multiples: {\n hundredth: 100,\n thousandth: 1000,\n millionth: 1e6,\n billionth: 1e9,\n trillionth: 1e12,\n quadrillionth: 1e15,\n quintillionth: 1e18,\n sextillionth: 1e21,\n septillionth: 1e24,\n hundred: 100,\n thousand: 1000,\n million: 1e6,\n billion: 1e9,\n trillion: 1e12,\n quadrillion: 1e15,\n quintillion: 1e18,\n sextillion: 1e21,\n septillion: 1e24,\n grand: 1000,\n },\n}\n","const words = require('./data')\n\n//prevent things like 'fifteen ten', and 'five sixty'\nconst isValid = (w, has) => {\n if (words.ones.hasOwnProperty(w)) {\n if (has.ones || has.teens) {\n return false\n }\n } else if (words.teens.hasOwnProperty(w)) {\n if (has.ones || has.teens || has.tens) {\n return false\n }\n } else if (words.tens.hasOwnProperty(w)) {\n if (has.ones || has.teens || has.tens) {\n return false\n }\n }\n return true\n}\nmodule.exports = isValid\n","const words = require('./data')\n\n//concatenate into a string with leading '0.'\nconst parseDecimals = function(arr) {\n let str = '0.'\n for (let i = 0; i < arr.length; i++) {\n let w = arr[i]\n if (words.ones.hasOwnProperty(w) === true) {\n str += words.ones[w]\n } else if (words.teens.hasOwnProperty(w) === true) {\n str += words.teens[w]\n } else if (words.tens.hasOwnProperty(w) === true) {\n str += words.tens[w]\n } else if (/^[0-9]$/.test(w) === true) {\n str += w\n } else {\n return 0\n }\n }\n return parseFloat(str)\n}\n\nmodule.exports = parseDecimals\n","//parse a string like \"4,200.1\" into Number 4200.1\nconst parseNumeric = str => {\n //remove ordinal - 'th/rd'\n str = str.replace(/1st$/, '1')\n str = str.replace(/2nd$/, '2')\n str = str.replace(/3rd$/, '3')\n str = str.replace(/([4567890])r?th$/, '$1')\n //remove prefixes\n str = str.replace(/^[$€¥£¢]/, '')\n //remove suffixes\n str = str.replace(/[%$€¥£¢]$/, '')\n //remove commas\n str = str.replace(/,/g, '')\n //split '5kg' from '5'\n str = str.replace(/([0-9])([a-z\\u00C0-\\u00FF]{1,2})$/, '$1')\n return str\n}\n\nmodule.exports = parseNumeric\n","const findModifiers = require('./findModifiers')\nconst words = require('./data')\nconst isValid = require('./validate')\nconst parseDecimals = require('./parseDecimals')\nconst parseNumeric = require('./parseNumeric')\nconst improperFraction = /^([0-9,\\. ]+)\\/([0-9,\\. ]+)$/\n\n//some numbers we know\nconst casualForms = {\n // 'a few': 3,\n 'a couple': 2,\n 'a dozen': 12,\n 'two dozen': 24,\n zero: 0,\n}\n\n// a 'section' is something like 'fifty-nine thousand'\n// turn a section into something we can add to - like 59000\nconst section_sum = obj => {\n return Object.keys(obj).reduce((sum, k) => {\n sum += obj[k]\n return sum\n }, 0)\n}\n\n//turn a string into a number\nconst parse = function(str) {\n //convert some known-numbers\n if (casualForms.hasOwnProperty(str) === true) {\n return casualForms[str]\n }\n //'a/an' is 1\n if (str === 'a' || str === 'an') {\n return 1\n }\n const modifier = findModifiers(str)\n str = modifier.str\n let last_mult = null\n let has = {}\n let sum = 0\n let isNegative = false\n const terms = str.split(/[ -]/)\n for (let i = 0; i < terms.length; i++) {\n let w = terms[i]\n w = parseNumeric(w)\n if (!w || w === 'and') {\n continue\n }\n if (w === '-' || w === 'negative') {\n isNegative = true\n continue\n }\n if (w.charAt(0) === '-') {\n isNegative = true\n w = w.substr(1)\n }\n //decimal mode\n if (w === 'point') {\n sum += section_sum(has)\n sum += parseDecimals(terms.slice(i + 1, terms.length))\n sum *= modifier.amount\n return sum\n }\n //improper fraction\n const fm = w.match(improperFraction)\n if (fm) {\n const num = parseFloat(fm[1].replace(/[, ]/g, ''))\n const denom = parseFloat(fm[2].replace(/[, ]/g, ''))\n if (denom) {\n sum += num / denom || 0\n }\n continue\n }\n //prevent mismatched units, like 'seven eleven'\n if (isValid(w, has) === false) {\n return null\n }\n //buildOut section, collect 'has' values\n if (/^[0-9\\.]+$/.test(w)) {\n has['ones'] = parseFloat(w) //not technically right\n } else if (words.ones.hasOwnProperty(w) === true) {\n has['ones'] = words.ones[w]\n } else if (words.teens.hasOwnProperty(w) === true) {\n has['teens'] = words.teens[w]\n } else if (words.tens.hasOwnProperty(w) === true) {\n has['tens'] = words.tens[w]\n } else if (words.multiples.hasOwnProperty(w) === true) {\n let mult = words.multiples[w]\n\n //something has gone wrong : 'two hundred five hundred'\n if (mult === last_mult) {\n return null\n }\n //support 'hundred thousand'\n //this one is tricky..\n if (mult === 100 && terms[i + 1] !== undefined) {\n // has['hundreds']=\n const w2 = terms[i + 1]\n if (words.multiples[w2]) {\n mult *= words.multiples[w2] //hundredThousand/hundredMillion\n i += 1\n }\n }\n //natural order of things\n //five thousand, one hundred..\n if (last_mult === null || mult < last_mult) {\n sum += (section_sum(has) || 1) * mult\n last_mult = mult\n has = {}\n } else {\n //maybe hundred .. thousand\n sum += section_sum(has)\n last_mult = mult\n sum = (sum || 1) * mult\n has = {}\n }\n }\n }\n //dump the remaining has values\n sum += section_sum(has)\n //post-process add modifier\n sum *= modifier.amount\n sum *= isNegative ? -1 : 1\n //dont return 0, if it went straight-through\n if (sum === 0 && Object.keys(has).length === 0) {\n return null\n }\n return sum\n}\n\nmodule.exports = parse\n","const toNumber = require('./convert/toNumber')\n\n// get a numeric value from this phrase\nconst parseNumber = function(p) {\n let str = p.text('reduced')\n // is it in '3,123' format?\n let hasComma = /[0-9],[0-9]/.test(p.text('text'))\n str = str.replace(/,/g, '')\n\n //parse a numeric-number (easy)\n let arr = str.split(/^([^0-9]*)([0-9.,]*)([^0-9]*)$/)\n if (arr && arr[2] && p.terms().length < 2) {\n let num = parseFloat(arr[2] || str)\n //ensure that num is an actual number\n if (typeof num !== 'number') {\n num = null\n }\n // strip an ordinal off the suffix\n let suffix = arr[3] || ''\n if (suffix === 'st' || suffix === 'nd' || suffix === 'rd' || suffix === 'th') {\n suffix = ''\n }\n // support M for million, k for thousand\n if (suffix === 'm' || suffix === 'M') {\n num *= 1000000\n suffix = ''\n }\n if (suffix === 'k' || suffix === 'k') {\n num *= 1000\n suffix = ''\n }\n return {\n hasComma: hasComma,\n prefix: arr[1] || '',\n num: num,\n suffix: suffix,\n }\n }\n //parse a text-numer (harder)\n let num = toNumber(str)\n return {\n hasComma: hasComma,\n prefix: '',\n num: num,\n suffix: '',\n }\n}\nmodule.exports = parseNumber\n","// handle 'one bottle', 'two bottles'\nconst agreeUnits = function(agree, val, obj) {\n if (agree === false) {\n return\n }\n let unit = val.lookAhead('^(#Unit|#Noun)')\n // don't do these\n if (unit.has('(#Address|#Money|#Percent)') || val.has('#Ordinal')) {\n return\n }\n if (obj.num === 1) {\n unit.nouns().toSingular()\n } else if (unit.has('#Singular')) {\n unit.nouns().toPlural()\n }\n}\nmodule.exports = agreeUnits\n","/**\n * turn big numbers, like 2.3e+22, into a string with a ton of trailing 0's\n * */\nconst numToString = function(n) {\n if (n < 1000000) {\n return String(n)\n }\n let str\n if (typeof n === 'number') {\n str = n.toFixed(0)\n } else {\n str = n\n }\n if (str.indexOf('e+') === -1) {\n return str\n }\n return str\n .replace('.', '')\n .split('e+')\n .reduce(function(p, b) {\n return p + Array(b - p.length + 2).join(0)\n })\n}\nmodule.exports = numToString\n// console.log(numToString(2.5e+22));\n","const toString = require('../_toString')\n/**\n * turns an integer/float into.ber, like 'fifty-five'\n */\n\nconst tens_mapping = [\n ['ninety', 90],\n ['eighty', 80],\n ['seventy', 70],\n ['sixty', 60],\n ['fifty', 50],\n ['forty', 40],\n ['thirty', 30],\n ['twenty', 20],\n]\nconst ones_mapping = [\n '',\n 'one',\n 'two',\n 'three',\n 'four',\n 'five',\n 'six',\n 'seven',\n 'eight',\n 'nine',\n 'ten',\n 'eleven',\n 'twelve',\n 'thirteen',\n 'fourteen',\n 'fifteen',\n 'sixteen',\n 'seventeen',\n 'eighteen',\n 'nineteen',\n]\n\nconst sequence = [\n [1e24, 'septillion'],\n [1e20, 'hundred sextillion'],\n [1e21, 'sextillion'],\n [1e20, 'hundred quintillion'],\n [1e18, 'quintillion'],\n [1e17, 'hundred quadrillion'],\n [1e15, 'quadrillion'],\n [1e14, 'hundred trillion'],\n [1e12, 'trillion'],\n [1e11, 'hundred billion'],\n [1e9, 'billion'],\n [1e8, 'hundred million'],\n [1e6, 'million'],\n [100000, 'hundred thousand'],\n [1000, 'thousand'],\n [100, 'hundred'],\n [1, 'one'],\n]\n\n//turn number into an array of magnitudes, like [[5, million], [2, hundred]]\nconst breakdown_magnitudes = function(num) {\n let working = num\n let have = []\n sequence.forEach(a => {\n if (num >= a[0]) {\n let howmany = Math.floor(working / a[0])\n working -= howmany * a[0]\n if (howmany) {\n have.push({\n unit: a[1],\n count: howmany,\n })\n }\n }\n })\n return have\n}\n\n//turn numbers from 100-0 into their text\nconst breakdown_hundred = function(num) {\n let arr = []\n if (num > 100) {\n return arr //something bad happened..\n }\n for (let i = 0; i < tens_mapping.length; i++) {\n if (num >= tens_mapping[i][1]) {\n num -= tens_mapping[i][1]\n arr.push(tens_mapping[i][0])\n }\n }\n //(hopefully) we should only have 20-0 now\n if (ones_mapping[num]) {\n arr.push(ones_mapping[num])\n }\n return arr\n}\n\n/** print-out 'point eight nine'*/\nconst handle_decimal = num => {\n const names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']\n let arr = []\n //parse it out like a string, because js math is such shit\n let str = toString(num)\n let decimal = str.match(/\\.([0-9]+)/)\n if (!decimal || !decimal[0]) {\n return arr\n }\n arr.push('point')\n let decimals = decimal[0].split('')\n for (let i = 0; i < decimals.length; i++) {\n arr.push(names[decimals[i]])\n }\n return arr\n}\n\n/** turns an integer into a textual number */\nconst to_text = function(num) {\n // handle zero, quickly\n if (num === 0 || num === '0') {\n return 'zero' // no?\n }\n //big numbers, north of sextillion, aren't gonna work well..\n //keep them small..\n if (num > 1e21) {\n num = toString(num)\n }\n let arr = []\n //handle negative numbers\n if (num < 0) {\n arr.push('minus')\n num = Math.abs(num)\n }\n //break-down into units, counts\n let units = breakdown_magnitudes(num)\n //build-up the string from its components\n for (let i = 0; i < units.length; i++) {\n let unit_name = units[i].unit\n if (unit_name === 'one') {\n unit_name = ''\n //put an 'and' in here\n if (arr.length > 1) {\n arr.push('and')\n }\n }\n arr = arr.concat(breakdown_hundred(units[i].count))\n arr.push(unit_name)\n }\n //also support decimals - 'point eight'\n arr = arr.concat(handle_decimal(num))\n //remove empties\n arr = arr.filter(s => s)\n if (arr.length === 0) {\n arr[0] = ''\n }\n return arr.join(' ')\n}\n\nmodule.exports = to_text\n\n// console.log(to_text(-1000.8));\n","const toString = require('../_toString')\n\n/**\n * turn a number like 5 into an ordinal like 5th\n */\nconst numOrdinal = function(num) {\n if (!num && num !== 0) {\n return null\n }\n //the teens are all 'th'\n let tens = num % 100\n if (tens > 10 && tens < 20) {\n return String(num) + 'th'\n }\n //the rest of 'em\n const mapping = {\n 0: 'th',\n 1: 'st',\n 2: 'nd',\n 3: 'rd',\n }\n let str = toString(num)\n let last = str.slice(str.length - 1, str.length)\n if (mapping[last]) {\n str += mapping[last]\n } else {\n str += 'th'\n }\n return str\n}\n\nmodule.exports = numOrdinal\n","const textValue = require('../toText')\n// const toString = require('../_toString')\n\nconst irregulars = {\n one: 'first',\n two: 'second',\n three: 'third',\n five: 'fifth',\n eight: 'eighth',\n nine: 'ninth',\n twelve: 'twelfth',\n twenty: 'twentieth',\n thirty: 'thirtieth',\n forty: 'fortieth',\n fourty: 'fourtieth',\n fifty: 'fiftieth',\n sixty: 'sixtieth',\n seventy: 'seventieth',\n eighty: 'eightieth',\n ninety: 'ninetieth',\n}\n\n/**\n * convert a javascript number to 'twentieth' format\n * */\nconst textOrdinal = num => {\n let words = textValue(num).split(' ')\n //convert the last number to an ordinal\n let last = words[words.length - 1]\n if (irregulars.hasOwnProperty(last)) {\n words[words.length - 1] = irregulars[last]\n } else {\n words[words.length - 1] = last.replace(/y$/, 'i') + 'th'\n }\n return words.join(' ')\n}\n\nmodule.exports = textOrdinal\n","const prefixes = {\n '¢': 'cents',\n $: 'dollars',\n '£': 'pounds',\n '¥': 'yen',\n '€': 'euros',\n '₡': 'colón',\n '฿': 'baht',\n '₭': 'kip',\n '₩': 'won',\n '₹': 'rupees',\n '₽': 'ruble',\n '₺': 'liras',\n}\nconst suffixes = {\n '%': 'percent',\n s: 'seconds',\n cm: 'centimetres',\n km: 'kilometres',\n}\nmodule.exports = {\n prefixes: prefixes,\n suffixes: suffixes,\n}\n","const toString = require('./_toString')\nconst toText = require('./toText')\nconst numOrdinal = require('./toOrdinal/numOrdinal')\nconst textOrdinal = require('./toOrdinal/textOrdinal')\nconst symbols = require('./_symbols')\nconst prefixes = symbols.prefixes\nconst suffixes = symbols.suffixes\n\nconst isCurrency = {\n usd: true,\n eur: true,\n jpy: true,\n gbp: true,\n cad: true,\n aud: true,\n chf: true,\n cny: true,\n hkd: true,\n nzd: true,\n kr: true,\n rub: true,\n}\n// convert $ to 'dollars', etc\nconst prefixToText = function(obj) {\n // turn 5% to 'five percent'\n if (prefixes.hasOwnProperty(obj.prefix)) {\n obj.suffix += prefixes[obj.prefix]\n obj.prefix = ''\n }\n //turn 5km to 'five kilometres'\n if (suffixes.hasOwnProperty(obj.suffix)) {\n obj.suffix = suffixes[obj.suffix]\n }\n //uppercase lost case for 'USD', etc\n if (isCurrency.hasOwnProperty(obj.suffix)) {\n obj.suffix = obj.suffix.toUpperCase()\n }\n // add a space, if it exists\n if (obj.suffix) {\n obj.suffix = ' ' + obj.suffix\n }\n return obj\n}\n\n//business-logic for converting a cardinal-number to other forms\nconst makeNumber = function(obj, isText, isOrdinal) {\n let num = String(obj.num)\n if (isText) {\n obj = prefixToText(obj)\n if (isOrdinal) {\n //ordinal-text\n num = textOrdinal(num)\n return `${obj.prefix || ''}${num}${obj.suffix || ''}`\n }\n //cardinal-text\n num = toText(num)\n return `${obj.prefix || ''}${num}${obj.suffix || ''}`\n }\n //ordinal-number\n if (isOrdinal) {\n num = numOrdinal(num)\n // support '5th percent'\n obj = prefixToText(obj)\n return `${obj.prefix || ''}${num}${obj.suffix || ''}`\n }\n // support comma format\n if (obj.hasComma === true) {\n num = obj.num.toLocaleString()\n }\n // cardinal-number\n num = toString(num) // support very large numbers\n return `${obj.prefix || ''}${num}${obj.suffix || ''}`\n}\nmodule.exports = makeNumber\n","const parseNumber = require('./parse')\nconst agreeUnits = require('./_agreeUnits')\nconst makeNumber = require('./convert/makeNumber')\nconst toNumber = require('./convert/toNumber')\n\nlet methods = {\n /** overloaded json method with additional number information */\n json: function(options) {\n let n = null\n if (typeof options === 'number') {\n n = options\n options = null\n }\n options = options || { text: true, normal: true, trim: true, terms: true }\n let res = []\n this.forEach(doc => {\n let json = doc.json(options)[0]\n let obj = parseNumber(doc)\n json.prefix = obj.prefix\n json.number = obj.num\n json.suffix = obj.suffix\n json.cardinal = makeNumber(obj, false, false)\n json.ordinal = makeNumber(obj, false, true)\n json.textCardinal = makeNumber(obj, true, false)\n json.textOrdinal = makeNumber(obj, true, true)\n res.push(json)\n })\n if (n !== null) {\n return res[n]\n }\n return res\n },\n /** two of what? */\n units: function() {\n return this.lookAhead('^(#Unit|#Noun)')\n },\n /** return only ordinal numbers */\n isOrdinal: function() {\n return this.if('#Ordinal')\n },\n /** return only cardinal numbers*/\n isCardinal: function() {\n return this.if('#Cardinal')\n },\n /** convert to numeric form like '8' or '8th' */\n toNumber: function() {\n this.forEach(val => {\n let obj = parseNumber(val)\n if (obj.num === null) {\n return\n }\n let str = makeNumber(obj, false, val.has('#Ordinal'))\n val.replaceWith(str, true)\n val.tag('NumericValue')\n })\n return this\n },\n /** add commas, or nicer formatting for numbers */\n toLocaleString: function() {\n this.forEach(val => {\n let obj = parseNumber(val)\n if (obj.num === null) {\n return\n }\n obj.num = obj.num.toLocaleString()\n let str = makeNumber(obj, false, val.has('#Ordinal'))\n val.replaceWith(str, true)\n })\n return this\n },\n /** convert to text form - like 'eight' or 'eigth'*/\n toText: function() {\n this.forEach(val => {\n let obj = parseNumber(val)\n if (obj.num === null) {\n return\n }\n let str = makeNumber(obj, true, val.has('#Ordinal'))\n val.replaceWith(str, true)\n val.tag('TextValue')\n })\n return this\n },\n /** convert to cardinal form, like 'eight', or '8' */\n toCardinal: function(agree) {\n let m = this.if('#Ordinal')\n m.forEach(val => {\n let obj = parseNumber(val)\n if (obj.num === null) {\n return\n }\n let str = makeNumber(obj, val.has('#TextValue'), false)\n val.replaceWith(str, true, true)\n val.tag('Cardinal')\n // turn unit into plural -> 'seven beers'\n agreeUnits(agree, val, obj)\n })\n return this\n },\n /** convert to ordinal form, like 'eighth', or '8th' */\n toOrdinal: function() {\n let m = this.if('#Cardinal')\n m.forEach(val => {\n let obj = parseNumber(val)\n if (obj.num === null) {\n return\n }\n let str = makeNumber(obj, val.has('#TextValue'), true)\n val.replaceWith(str, true, true)\n val.tag('Ordinal')\n // turn unit into singular -> 'seventh beer'\n let unit = this.lookAhead('^#Plural')\n if (unit.found) {\n unit.nouns().toSingular()\n }\n })\n return this\n },\n /** return only numbers that are == n */\n isEqual: function(n) {\n return this.filter(val => {\n let num = parseNumber(val).num\n return num === n\n })\n },\n /** return only numbers that are > n*/\n greaterThan: function(n) {\n return this.filter(val => {\n let num = parseNumber(val).num\n return num > n\n })\n },\n /** return only numbers that are < n*/\n lessThan: function(n) {\n return this.filter(val => {\n let num = parseNumber(val).num\n return num < n\n })\n },\n /** return only numbers > min and < max */\n between: function(min, max) {\n return this.filter(val => {\n let num = parseNumber(val).num\n return num > min && num < max\n })\n },\n /** set these number to n */\n set: function(n, agree) {\n if (n === undefined) {\n return this // don't bother\n }\n if (typeof n === 'string') {\n n = toNumber(n)\n }\n this.forEach(val => {\n let obj = parseNumber(val)\n obj.num = n\n if (obj.num === null) {\n return\n }\n let str = makeNumber(obj, val.has('#TextValue'), val.has('#Ordinal'))\n val.replaceWith(str, true, true)\n // handle plural/singular unit\n agreeUnits(agree, val, obj)\n })\n return this\n },\n add: function(n, agree) {\n if (!n) {\n return this // don't bother\n }\n if (typeof n === 'string') {\n n = toNumber(n)\n }\n this.forEach(val => {\n let obj = parseNumber(val)\n\n if (obj.num === null) {\n return\n }\n obj.num += n\n let str = makeNumber(obj, val.has('#TextValue'), val.has('#Ordinal'))\n val.replaceWith(str, true, true)\n // handle plural/singular unit\n agreeUnits(agree, val, obj)\n })\n return this\n },\n /** decrease each number by n*/\n subtract: function(n, agree) {\n return this.add(n * -1, agree)\n },\n /** increase each number by 1 */\n increment: function(agree) {\n this.add(1, agree)\n return this\n },\n /** decrease each number by 1 */\n decrement: function(agree) {\n this.add(-1, agree)\n return this\n },\n\n /// ----\n\n /** return things like 1/3rd */\n fractions: function(n) {\n let m = this.match('#Fraction')\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n },\n\n /** return things like CCXX*/\n romanNumerals: function(n) {\n let m = this.match('#RomanNumeral').numbers()\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n },\n\n /** return things like $4.50*/\n money: function(n) {\n let m = this.splitOn('@hasComma')\n m = m.match('#Money+ #Currency?')\n m = m.numbers()\n if (typeof n === 'number') {\n m = m.get(n)\n }\n return m\n },\n}\n// aliases\nmethods.toNice = methods.toLocaleString\nmethods.isBetween = methods.between\nmethods.minus = methods.subtract\nmethods.plus = methods.add\nmethods.equals = methods.isEqual\n\nmodule.exports = methods\n","const multiples =\n '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)'\n\n// improved tagging for numbers\nconst tagger = function(doc) {\n doc.match(multiples).tag('#Multiple')\n // in the 400s\n doc.match('the [/[0-9]+s$/]').tag('#Plural')\n //half a million\n doc.match('half a? #Value').tag('Value', 'half-a-value') //(quarter not ready)\n //five and a half\n doc.match('#Value and a (half|quarter)').tag('Value', 'value-and-a-half')\n //one hundred and seven dollars\n doc.match('#Money and #Money #Currency?').tag('Money', 'money-and-money')\n}\nmodule.exports = tagger\n","module.exports = {\n Fraction: {\n isA: 'Value',\n },\n Multiple: {\n isA: 'Value',\n },\n}\n","const findNumbers = require('./find')\nconst methods = require('./methods')\nconst tagger = require('./tagger')\nconst tags = require('./tags')\n\n/** adds .numbers() method */\nconst addMethod = function(Doc, world) {\n // add tags to our tagset\n world.addTags(tags)\n\n // additional tagging before running the number-parser\n world.postProcess(tagger)\n\n /** a list of number values, and their units */\n class Numbers extends Doc {}\n //aliases\n Object.assign(Numbers.prototype, methods)\n\n /** find all numbers and values */\n Doc.prototype.numbers = function(n) {\n let match = findNumbers(this, n)\n return new Numbers(match.list, this, this.world)\n }\n // alias for reverse-compatibility\n Doc.prototype.values = Doc.prototype.numbers\n return Doc\n}\nmodule.exports = addMethod\n"],"names":["tens","teens","findNumbers","doc","n","match","has","splitAfter","splitOn","double","found","terms","forEach","d","splitBefore","get","findModifiers","str","mults","reg","mult","i","length","test","amount","replace","ones","zeroth","first","second","third","fourth","fifth","sixth","seventh","eighth","ninth","zero","one","two","three","four","five","six","seven","eight","nine","tenth","eleventh","twelfth","thirteenth","fourteenth","fifteenth","sixteenth","seventeenth","eighteenth","nineteenth","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twentieth","thirtieth","fortieth","fourtieth","fiftieth","sixtieth","seventieth","eightieth","ninetieth","twenty","thirty","forty","fourty","fifty","sixty","seventy","eighty","ninety","multiples","hundredth","thousandth","millionth","billionth","trillionth","quadrillionth","quintillionth","sextillionth","septillionth","hundred","thousand","million","billion","trillion","quadrillion","quintillion","sextillion","septillion","grand","isValid","w","words","hasOwnProperty","parseDecimals","arr","parseFloat","parseNumeric","improperFraction","casualForms","section_sum","obj","Object","keys","reduce","sum","k","parse","modifier","last_mult","isNegative","split","charAt","substr","slice","fm","num","denom","undefined","w2","parseNumber","p","text","hasComma","suffix","prefix","toNumber","agreeUnits","agree","val","unit","lookAhead","nouns","toSingular","toPlural","numToString","String","toFixed","indexOf","b","Array","join","tens_mapping","ones_mapping","sequence","breakdown_magnitudes","working","have","a","howmany","Math","floor","push","count","breakdown_hundred","handle_decimal","names","toString","decimal","decimals","to_text","abs","units","unit_name","concat","filter","s","numOrdinal","mapping","last","irregulars","textOrdinal","textValue","prefixes","$","suffixes","cm","km","symbols","isCurrency","usd","eur","jpy","gbp","cad","aud","chf","cny","hkd","nzd","kr","rub","prefixToText","toUpperCase","makeNumber","isText","isOrdinal","toText","toLocaleString","methods","json","options","normal","trim","res","number","cardinal","ordinal","textCardinal","isCardinal","replaceWith","tag","toCardinal","m","toOrdinal","isEqual","greaterThan","lessThan","between","min","max","set","add","subtract","increment","decrement","fractions","romanNumerals","numbers","money","toNice","isBetween","minus","plus","equals","tagger","Fraction","isA","Multiple","addMethod","Doc","world","addTags","tags","postProcess","Numbers","assign","prototype","list","values"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/numbers/builds/compromise-numbers.min.js b/plugins/numbers/builds/compromise-numbers.min.js new file mode 100644 index 000000000..4802d3c6c --- /dev/null +++ b/plugins/numbers/builds/compromise-numbers.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).compromiseNumbers=t()}(this,(function(){"use strict";function e(t){return(e=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(t)}function t(e,n){return(t=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,n)}function n(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}var r="twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty",i=function(e,t){var n=e.match("#Value+");if(n.has("#NumericValue #NumericValue")&&(n.has("#Value @hasComma #Value")?n.splitAfter("@hasComma"):n=n.splitAfter("#NumericValue")),n.has("#Value #Value #Value")&&!n.has("#Multiple")&&n.has("("+r+") #Cardinal #Cardinal")&&(n=n.splitAfter("("+r+") #Cardinal")),n.has("#Value #Value")){n.has("#NumericValue #NumericValue")&&(n=n.splitOn("#Year")),n.has("("+r+") (eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen)")&&(n=n.splitAfter("("+r+")"));var i=n.match("#Cardinal #Cardinal");i.found&&!n.has("(point|decimal)")&&(i.has("#Cardinal (#Multiple|point|decimal)")||i.has("("+r+") #Cardinal")||i.has("#Multiple #Value")||i.terms().forEach((function(e){n=n.splitOn(e)}))),n.match("#Ordinal #Ordinal").match("#TextValue").found&&!n.has("#Multiple")&&(n.has("("+r+") #Ordinal")||(n=n.splitAfter("#Ordinal"))),n.has("#Ordinal #Cardinal")&&(n=n.splitBefore("#Cardinal+")),n.has("#TextValue #NumericValue")&&!n.has("("+r+"|#Multiple)")&&(n=n.splitBefore("#NumericValue+"))}return n.has("#NumberRange")&&(n=n.splitAfter("#NumberRange")),"number"==typeof t&&(n=n.get(t)),n},u=function(e){for(var t=[{reg:/^(minus|negative)[\s\-]/i,mult:-1},{reg:/^(a\s)?half[\s\-](of\s)?/i,mult:.5}],n=0;n100)return t;for(var n=0;n=v[n][1]&&(e-=v[n][1],t.push(v[n][0]));return g[e]&&t.push(g[e]),t},b=function(e){if(0===e||"0"===e)return"zero";e>1e21&&(e=y(e));var t=[];e<0&&(t.push("minus"),e=Math.abs(e));for(var n=function(e){var t=e,n=[];return x.forEach((function(r){if(e>=r[0]){var i=Math.floor(t/r[0]);t-=i*r[0],i&&n.push({unit:r[1],count:i})}})),n}(e),r=0;r1&&t.push("and")),(t=t.concat(O(n[r].count))).push(i)}return 0===(t=(t=t.concat(function(e){var t=["zero","one","two","three","four","five","six","seven","eight","nine"],n=[],r=y(e).match(/\.([0-9]+)/);if(!r||!r[0])return n;n.push("point");for(var i=r[0].split(""),u=0;u10&&t<20)return String(e)+"th";var n={0:"th",1:"st",2:"nd",3:"rd"},r=y(e),i=r.slice(r.length-1,r.length);return r+=n[i]?n[i]:"th"},V={one:"first",two:"second",three:"third",five:"fifth",eight:"eighth",nine:"ninth",twelve:"twelfth",twenty:"twentieth",thirty:"thirtieth",forty:"fortieth",fourty:"fourtieth",fifty:"fiftieth",sixty:"sixtieth",seventy:"seventieth",eighty:"eightieth",ninety:"ninetieth"},C=function(e){var t=b(e).split(" "),n=t[t.length-1];return V.hasOwnProperty(n)?t[t.length-1]=V[n]:t[t.length-1]=n.replace(/y$/,"i")+"th",t.join(" ")},P={"¢":"cents",$:"dollars","£":"pounds","¥":"yen","€":"euros","₡":"colón","฿":"baht","₭":"kip","₩":"won","₹":"rupees","₽":"ruble","₺":"liras"},N={"%":"percent",s:"seconds",cm:"centimetres",km:"kilometres"},$={usd:!0,eur:!0,jpy:!0,gbp:!0,cad:!0,aud:!0,chf:!0,cny:!0,hkd:!0,nzd:!0,kr:!0,rub:!0},j=function(e){return P.hasOwnProperty(e.prefix)&&(e.suffix+=P[e.prefix],e.prefix=""),N.hasOwnProperty(e.suffix)&&(e.suffix=N[e.suffix]),$.hasOwnProperty(e.suffix)&&(e.suffix=e.suffix.toUpperCase()),e.suffix&&(e.suffix=" "+e.suffix),e},E=function(e,t,n){var r=String(e.num);return t?(e=j(e),n?(r=C(r),"".concat(e.prefix||"").concat(r).concat(e.suffix||"")):(r=b(r),"".concat(e.prefix||"").concat(r).concat(e.suffix||""))):n?(r=w(r),e=j(e),"".concat(e.prefix||"").concat(r).concat(e.suffix||"")):(!0===e.hasComma&&(r=e.num.toLocaleString()),r=y(r),"".concat(e.prefix||"").concat(r).concat(e.suffix||""))},M={json:function(e){var t=null;"number"==typeof e&&(t=e,e=null),e=e||{text:!0,normal:!0,trim:!0,terms:!0};var n=[];return this.forEach((function(t){var r=t.json(e)[0],i=d(t);r.prefix=i.prefix,r.number=i.num,r.suffix=i.suffix,r.cardinal=E(i,!1,!1),r.ordinal=E(i,!1,!0),r.textCardinal=E(i,!0,!1),r.textOrdinal=E(i,!0,!0),n.push(r)})),null!==t?n[t]:n},units:function(){return this.lookAhead("^(#Unit|#Noun)")},isOrdinal:function(){return this.if("#Ordinal")},isCardinal:function(){return this.if("#Cardinal")},toNumber:function(){return this.forEach((function(e){var t=d(e);if(null!==t.num){var n=E(t,!1,e.has("#Ordinal"));e.replaceWith(n,!0),e.tag("NumericValue")}})),this},toLocaleString:function(){return this.forEach((function(e){var t=d(e);if(null!==t.num){t.num=t.num.toLocaleString();var n=E(t,!1,e.has("#Ordinal"));e.replaceWith(n,!0)}})),this},toText:function(){return this.forEach((function(e){var t=d(e);if(null!==t.num){var n=E(t,!0,e.has("#Ordinal"));e.replaceWith(n,!0),e.tag("TextValue")}})),this},toCardinal:function(e){return this.if("#Ordinal").forEach((function(t){var n=d(t);if(null!==n.num){var r=E(n,t.has("#TextValue"),!1);t.replaceWith(r,!0,!0),t.tag("Cardinal"),m(e,t,n)}})),this},toOrdinal:function(){var e=this;return this.if("#Cardinal").forEach((function(t){var n=d(t);if(null!==n.num){var r=E(n,t.has("#TextValue"),!0);t.replaceWith(r,!0,!0),t.tag("Ordinal");var i=e.lookAhead("^#Plural");i.found&&i.nouns().toSingular()}})),this},isEqual:function(e){return this.filter((function(t){return d(t).num===e}))},greaterThan:function(e){return this.filter((function(t){return d(t).num>e}))},lessThan:function(e){return this.filter((function(t){return d(t).nume&&r= a[0]) { + var howmany = Math.floor(working / a[0]); + working -= howmany * a[0]; + + if (howmany) { + have.push({ + unit: a[1], + count: howmany + }); + } + } + }); + return have; +}; //turn numbers from 100-0 into their text + + +var breakdown_hundred = function breakdown_hundred(num) { + var arr = []; + + if (num > 100) { + return arr; //something bad happened.. + } + + for (var i = 0; i < tens_mapping.length; i++) { + if (num >= tens_mapping[i][1]) { + num -= tens_mapping[i][1]; + arr.push(tens_mapping[i][0]); + } + } //(hopefully) we should only have 20-0 now + + + if (ones_mapping[num]) { + arr.push(ones_mapping[num]); + } + + return arr; +}; +/** print-out 'point eight nine'*/ + + +var handle_decimal = function handle_decimal(num) { + var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']; + var arr = []; //parse it out like a string, because js math is such shit + + var str = _toString(num); + var decimal = str.match(/\.([0-9]+)/); + + if (!decimal || !decimal[0]) { + return arr; + } + + arr.push('point'); + var decimals = decimal[0].split(''); + + for (var i = 0; i < decimals.length; i++) { + arr.push(names[decimals[i]]); + } + + return arr; +}; +/** turns an integer into a textual number */ + + +var to_text = function to_text(num) { + // handle zero, quickly + if (num === 0 || num === '0') { + return 'zero'; // no? + } //big numbers, north of sextillion, aren't gonna work well.. + //keep them small.. + + + if (num > 1e21) { + num = _toString(num); + } + + var arr = []; //handle negative numbers + + if (num < 0) { + arr.push('minus'); + num = Math.abs(num); + } //break-down into units, counts + + + var units = breakdown_magnitudes(num); //build-up the string from its components + + for (var i = 0; i < units.length; i++) { + var unit_name = units[i].unit; + + if (unit_name === 'one') { + unit_name = ''; //put an 'and' in here + + if (arr.length > 1) { + arr.push('and'); + } + } + + arr = arr.concat(breakdown_hundred(units[i].count)); + arr.push(unit_name); + } //also support decimals - 'point eight' + + + arr = arr.concat(handle_decimal(num)); //remove empties + + arr = arr.filter(function (s) { + return s; + }); + + if (arr.length === 0) { + arr[0] = ''; + } + + return arr.join(' '); +}; + +var toText = to_text; // console.log(to_text(-1000.8)); + +/** + * turn a number like 5 into an ordinal like 5th + */ + +var numOrdinal = function numOrdinal(num) { + if (!num && num !== 0) { + return null; + } //the teens are all 'th' + + + var tens = num % 100; + + if (tens > 10 && tens < 20) { + return String(num) + 'th'; + } //the rest of 'em + + + var mapping = { + 0: 'th', + 1: 'st', + 2: 'nd', + 3: 'rd' + }; + var str = _toString(num); + var last = str.slice(str.length - 1, str.length); + + if (mapping[last]) { + str += mapping[last]; + } else { + str += 'th'; + } + + return str; +}; + +var numOrdinal_1 = numOrdinal; + +var irregulars = { + one: 'first', + two: 'second', + three: 'third', + five: 'fifth', + eight: 'eighth', + nine: 'ninth', + twelve: 'twelfth', + twenty: 'twentieth', + thirty: 'thirtieth', + forty: 'fortieth', + fourty: 'fourtieth', + fifty: 'fiftieth', + sixty: 'sixtieth', + seventy: 'seventieth', + eighty: 'eightieth', + ninety: 'ninetieth' +}; +/** + * convert a javascript number to 'twentieth' format + * */ + +var textOrdinal = function textOrdinal(num) { + var words = toText(num).split(' '); //convert the last number to an ordinal + + var last = words[words.length - 1]; + + if (irregulars.hasOwnProperty(last)) { + words[words.length - 1] = irregulars[last]; + } else { + words[words.length - 1] = last.replace(/y$/, 'i') + 'th'; + } + + return words.join(' '); +}; + +var textOrdinal_1 = textOrdinal; + +var prefixes = { + '¢': 'cents', + $: 'dollars', + '£': 'pounds', + '¥': 'yen', + '€': 'euros', + '₡': 'colón', + '฿': 'baht', + '₭': 'kip', + '₩': 'won', + '₹': 'rupees', + '₽': 'ruble', + '₺': 'liras' +}; +var suffixes = { + '%': 'percent', + s: 'seconds', + cm: 'centimetres', + km: 'kilometres' +}; +var _symbols = { + prefixes: prefixes, + suffixes: suffixes +}; + +var prefixes$1 = _symbols.prefixes; +var suffixes$1 = _symbols.suffixes; +var isCurrency = { + usd: true, + eur: true, + jpy: true, + gbp: true, + cad: true, + aud: true, + chf: true, + cny: true, + hkd: true, + nzd: true, + kr: true, + rub: true +}; // convert $ to 'dollars', etc + +var prefixToText = function prefixToText(obj) { + // turn 5% to 'five percent' + if (prefixes$1.hasOwnProperty(obj.prefix)) { + obj.suffix += prefixes$1[obj.prefix]; + obj.prefix = ''; + } //turn 5km to 'five kilometres' + + + if (suffixes$1.hasOwnProperty(obj.suffix)) { + obj.suffix = suffixes$1[obj.suffix]; + } //uppercase lost case for 'USD', etc + + + if (isCurrency.hasOwnProperty(obj.suffix)) { + obj.suffix = obj.suffix.toUpperCase(); + } // add a space, if it exists + + + if (obj.suffix) { + obj.suffix = ' ' + obj.suffix; + } + + return obj; +}; //business-logic for converting a cardinal-number to other forms + + +var makeNumber = function makeNumber(obj, isText, isOrdinal) { + var num = String(obj.num); + + if (isText) { + obj = prefixToText(obj); + + if (isOrdinal) { + //ordinal-text + num = textOrdinal_1(num); + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); + } //cardinal-text + + + num = toText(num); + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); + } //ordinal-number + + + if (isOrdinal) { + num = numOrdinal_1(num); // support '5th percent' + + obj = prefixToText(obj); + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); + } // support comma format + + + if (obj.hasComma === true) { + num = obj.num.toLocaleString(); + } // cardinal-number + + + num = _toString(num); // support very large numbers + + return "".concat(obj.prefix || '').concat(num).concat(obj.suffix || ''); +}; + +var makeNumber_1 = makeNumber; + +var methods = { + /** overloaded json method with additional number information */ + json: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var obj = parse$1(doc); + json.prefix = obj.prefix; + json.number = obj.num; + json.suffix = obj.suffix; + json.cardinal = makeNumber_1(obj, false, false); + json.ordinal = makeNumber_1(obj, false, true); + json.textCardinal = makeNumber_1(obj, true, false); + json.textOrdinal = makeNumber_1(obj, true, true); + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + }, + + /** two of what? */ + units: function units() { + return this.lookAhead('^(#Unit|#Noun)'); + }, + + /** return only ordinal numbers */ + isOrdinal: function isOrdinal() { + return this["if"]('#Ordinal'); + }, + + /** return only cardinal numbers*/ + isCardinal: function isCardinal() { + return this["if"]('#Cardinal'); + }, + + /** convert to numeric form like '8' or '8th' */ + toNumber: function toNumber() { + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, false, val.has('#Ordinal')); + val.replaceWith(str, true); + val.tag('NumericValue'); + }); + return this; + }, + + /** add commas, or nicer formatting for numbers */ + toLocaleString: function toLocaleString() { + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + obj.num = obj.num.toLocaleString(); + var str = makeNumber_1(obj, false, val.has('#Ordinal')); + val.replaceWith(str, true); + }); + return this; + }, + + /** convert to text form - like 'eight' or 'eigth'*/ + toText: function toText() { + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, true, val.has('#Ordinal')); + val.replaceWith(str, true); + val.tag('TextValue'); + }); + return this; + }, + + /** convert to cardinal form, like 'eight', or '8' */ + toCardinal: function toCardinal(agree) { + var m = this["if"]('#Ordinal'); + m.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, val.has('#TextValue'), false); + val.replaceWith(str, true, true); + val.tag('Cardinal'); // turn unit into plural -> 'seven beers' + + _agreeUnits(agree, val, obj); + }); + return this; + }, + + /** convert to ordinal form, like 'eighth', or '8th' */ + toOrdinal: function toOrdinal() { + var _this = this; + + var m = this["if"]('#Cardinal'); + m.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, val.has('#TextValue'), true); + val.replaceWith(str, true, true); + val.tag('Ordinal'); // turn unit into singular -> 'seventh beer' + + var unit = _this.lookAhead('^#Plural'); + + if (unit.found) { + unit.nouns().toSingular(); + } + }); + return this; + }, + + /** return only numbers that are == n */ + isEqual: function isEqual(n) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num === n; + }); + }, + + /** return only numbers that are > n*/ + greaterThan: function greaterThan(n) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num > n; + }); + }, + + /** return only numbers that are < n*/ + lessThan: function lessThan(n) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num < n; + }); + }, + + /** return only numbers > min and < max */ + between: function between(min, max) { + return this.filter(function (val) { + var num = parse$1(val).num; + return num > min && num < max; + }); + }, + + /** set these number to n */ + set: function set(n, agree) { + if (n === undefined) { + return this; // don't bother + } + + if (typeof n === 'string') { + n = toNumber(n); + } + + this.forEach(function (val) { + var obj = parse$1(val); + obj.num = n; + + if (obj.num === null) { + return; + } + + var str = makeNumber_1(obj, val.has('#TextValue'), val.has('#Ordinal')); + val.replaceWith(str, true, true); // handle plural/singular unit + + _agreeUnits(agree, val, obj); + }); + return this; + }, + add: function add(n, agree) { + if (!n) { + return this; // don't bother + } + + if (typeof n === 'string') { + n = toNumber(n); + } + + this.forEach(function (val) { + var obj = parse$1(val); + + if (obj.num === null) { + return; + } + + obj.num += n; + var str = makeNumber_1(obj, val.has('#TextValue'), val.has('#Ordinal')); + val.replaceWith(str, true, true); // handle plural/singular unit + + _agreeUnits(agree, val, obj); + }); + return this; + }, + + /** decrease each number by n*/ + subtract: function subtract(n, agree) { + return this.add(n * -1, agree); + }, + + /** increase each number by 1 */ + increment: function increment(agree) { + this.add(1, agree); + return this; + }, + + /** decrease each number by 1 */ + decrement: function decrement(agree) { + this.add(-1, agree); + return this; + }, + /// ---- + + /** return things like 1/3rd */ + fractions: function fractions(n) { + var m = this.match('#Fraction'); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; + }, + + /** return things like CCXX*/ + romanNumerals: function romanNumerals(n) { + var m = this.match('#RomanNumeral').numbers(); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; + }, + + /** return things like $4.50*/ + money: function money(n) { + var m = this.splitOn('@hasComma'); + m = m.match('#Money+ #Currency?'); + m = m.numbers(); + + if (typeof n === 'number') { + m = m.get(n); + } + + return m; + } +}; // aliases + +methods.toNice = methods.toLocaleString; +methods.isBetween = methods.between; +methods.minus = methods.subtract; +methods.plus = methods.add; +methods.equals = methods.isEqual; +var methods_1 = methods; + +var multiples = '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)'; // improved tagging for numbers + +var tagger = function tagger(doc) { + doc.match(multiples).tag('#Multiple'); // in the 400s + + doc.match('the [/[0-9]+s$/]').tag('#Plural'); //half a million + + doc.match('half a? #Value').tag('Value', 'half-a-value'); //(quarter not ready) + //five and a half + + doc.match('#Value and a (half|quarter)').tag('Value', 'value-and-a-half'); //one hundred and seven dollars + + doc.match('#Money and #Money #Currency?').tag('Money', 'money-and-money'); +}; + +var tagger_1 = tagger; + +var tags = { + Fraction: { + isA: 'Value' + }, + Multiple: { + isA: 'Value' + } +}; + +/** adds .numbers() method */ + +var addMethod = function addMethod(Doc, world) { + // add tags to our tagset + world.addTags(tags); // additional tagging before running the number-parser + + world.postProcess(tagger_1); + /** a list of number values, and their units */ + + var Numbers = + /*#__PURE__*/ + function (_Doc) { + _inherits(Numbers, _Doc); + + function Numbers() { + _classCallCheck(this, Numbers); + + return _possibleConstructorReturn(this, _getPrototypeOf(Numbers).apply(this, arguments)); + } + + return Numbers; + }(Doc); //aliases + + + Object.assign(Numbers.prototype, methods_1); + /** find all numbers and values */ + + Doc.prototype.numbers = function (n) { + var match = find(this, n); + return new Numbers(match.list, this, this.world); + }; // alias for reverse-compatibility + + + Doc.prototype.values = Doc.prototype.numbers; + return Doc; +}; + +var src = addMethod; + +export default src; diff --git a/plugins/numbers/package-lock.json b/plugins/numbers/package-lock.json new file mode 100644 index 000000000..b42f749aa --- /dev/null +++ b/plugins/numbers/package-lock.json @@ -0,0 +1,759 @@ +{ + "name": "compromise-numbers", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", + "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz", + "integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz", + "integrity": "sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.1.tgz", + "integrity": "sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/plugins/numbers/package.json b/plugins/numbers/package.json new file mode 100644 index 000000000..1a58f9902 --- /dev/null +++ b/plugins/numbers/package.json @@ -0,0 +1,47 @@ +{ + "name": "compromise-numbers", + "description": "plugin for nlp-compromise", + "version": "0.0.2", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-numbers.js", + "unpkg": "./builds/compromise-numbers.min.js", + "module": "./builds/compromise-numbers.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*" + }, + "dependencies": {}, + "devDependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/plugins/numbers/rollup.config.js b/plugins/numbers/rollup.config.js new file mode 100644 index 000000000..b92577638 --- /dev/null +++ b/plugins/numbers/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-numbers' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseNumbers', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseNumbers', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/numbers/src/_agreeUnits.js b/plugins/numbers/src/_agreeUnits.js new file mode 100644 index 000000000..8fb286920 --- /dev/null +++ b/plugins/numbers/src/_agreeUnits.js @@ -0,0 +1,17 @@ +// handle 'one bottle', 'two bottles' +const agreeUnits = function(agree, val, obj) { + if (agree === false) { + return + } + let unit = val.lookAhead('^(#Unit|#Noun)') + // don't do these + if (unit.has('(#Address|#Money|#Percent)') || val.has('#Ordinal')) { + return + } + if (obj.num === 1) { + unit.nouns().toSingular() + } else if (unit.has('#Singular')) { + unit.nouns().toPlural() + } +} +module.exports = agreeUnits diff --git a/plugins/numbers/src/convert/_symbols.js b/plugins/numbers/src/convert/_symbols.js new file mode 100644 index 000000000..f3d8fa453 --- /dev/null +++ b/plugins/numbers/src/convert/_symbols.js @@ -0,0 +1,24 @@ +const prefixes = { + '¢': 'cents', + $: 'dollars', + '£': 'pounds', + '¥': 'yen', + '€': 'euros', + '₡': 'colón', + '฿': 'baht', + '₭': 'kip', + '₩': 'won', + '₹': 'rupees', + '₽': 'ruble', + '₺': 'liras', +} +const suffixes = { + '%': 'percent', + s: 'seconds', + cm: 'centimetres', + km: 'kilometres', +} +module.exports = { + prefixes: prefixes, + suffixes: suffixes, +} diff --git a/plugins/numbers/src/convert/_toString.js b/plugins/numbers/src/convert/_toString.js new file mode 100644 index 000000000..5408db751 --- /dev/null +++ b/plugins/numbers/src/convert/_toString.js @@ -0,0 +1,25 @@ +/** + * turn big numbers, like 2.3e+22, into a string with a ton of trailing 0's + * */ +const numToString = function(n) { + if (n < 1000000) { + return String(n) + } + let str + if (typeof n === 'number') { + str = n.toFixed(0) + } else { + str = n + } + if (str.indexOf('e+') === -1) { + return str + } + return str + .replace('.', '') + .split('e+') + .reduce(function(p, b) { + return p + Array(b - p.length + 2).join(0) + }) +} +module.exports = numToString +// console.log(numToString(2.5e+22)); diff --git a/plugins/numbers/src/convert/makeNumber.js b/plugins/numbers/src/convert/makeNumber.js new file mode 100644 index 000000000..f6f3672f4 --- /dev/null +++ b/plugins/numbers/src/convert/makeNumber.js @@ -0,0 +1,74 @@ +const toString = require('./_toString') +const toText = require('./toText') +const numOrdinal = require('./toOrdinal/numOrdinal') +const textOrdinal = require('./toOrdinal/textOrdinal') +const symbols = require('./_symbols') +const prefixes = symbols.prefixes +const suffixes = symbols.suffixes + +const isCurrency = { + usd: true, + eur: true, + jpy: true, + gbp: true, + cad: true, + aud: true, + chf: true, + cny: true, + hkd: true, + nzd: true, + kr: true, + rub: true, +} +// convert $ to 'dollars', etc +const prefixToText = function(obj) { + // turn 5% to 'five percent' + if (prefixes.hasOwnProperty(obj.prefix)) { + obj.suffix += prefixes[obj.prefix] + obj.prefix = '' + } + //turn 5km to 'five kilometres' + if (suffixes.hasOwnProperty(obj.suffix)) { + obj.suffix = suffixes[obj.suffix] + } + //uppercase lost case for 'USD', etc + if (isCurrency.hasOwnProperty(obj.suffix)) { + obj.suffix = obj.suffix.toUpperCase() + } + // add a space, if it exists + if (obj.suffix) { + obj.suffix = ' ' + obj.suffix + } + return obj +} + +//business-logic for converting a cardinal-number to other forms +const makeNumber = function(obj, isText, isOrdinal) { + let num = String(obj.num) + if (isText) { + obj = prefixToText(obj) + if (isOrdinal) { + //ordinal-text + num = textOrdinal(num) + return `${obj.prefix || ''}${num}${obj.suffix || ''}` + } + //cardinal-text + num = toText(num) + return `${obj.prefix || ''}${num}${obj.suffix || ''}` + } + //ordinal-number + if (isOrdinal) { + num = numOrdinal(num) + // support '5th percent' + obj = prefixToText(obj) + return `${obj.prefix || ''}${num}${obj.suffix || ''}` + } + // support comma format + if (obj.hasComma === true) { + num = obj.num.toLocaleString() + } + // cardinal-number + num = toString(num) // support very large numbers + return `${obj.prefix || ''}${num}${obj.suffix || ''}` +} +module.exports = makeNumber diff --git a/plugins/numbers/src/convert/toNumber/data.js b/plugins/numbers/src/convert/toNumber/data.js new file mode 100644 index 000000000..ae9faa38b --- /dev/null +++ b/plugins/numbers/src/convert/toNumber/data.js @@ -0,0 +1,87 @@ +module.exports = { + ones: { + zeroth: 0, + first: 1, + second: 2, + third: 3, + fourth: 4, + fifth: 5, + sixth: 6, + seventh: 7, + eighth: 8, + ninth: 9, + zero: 0, + one: 1, + two: 2, + three: 3, + four: 4, + five: 5, + six: 6, + seven: 7, + eight: 8, + nine: 9, + }, + teens: { + tenth: 10, + eleventh: 11, + twelfth: 12, + thirteenth: 13, + fourteenth: 14, + fifteenth: 15, + sixteenth: 16, + seventeenth: 17, + eighteenth: 18, + nineteenth: 19, + ten: 10, + eleven: 11, + twelve: 12, + thirteen: 13, + fourteen: 14, + fifteen: 15, + sixteen: 16, + seventeen: 17, + eighteen: 18, + nineteen: 19, + }, + tens: { + twentieth: 20, + thirtieth: 30, + fortieth: 40, + fourtieth: 40, + fiftieth: 50, + sixtieth: 60, + seventieth: 70, + eightieth: 80, + ninetieth: 90, + twenty: 20, + thirty: 30, + forty: 40, + fourty: 40, + fifty: 50, + sixty: 60, + seventy: 70, + eighty: 80, + ninety: 90, + }, + multiples: { + hundredth: 100, + thousandth: 1000, + millionth: 1e6, + billionth: 1e9, + trillionth: 1e12, + quadrillionth: 1e15, + quintillionth: 1e18, + sextillionth: 1e21, + septillionth: 1e24, + hundred: 100, + thousand: 1000, + million: 1e6, + billion: 1e9, + trillion: 1e12, + quadrillion: 1e15, + quintillion: 1e18, + sextillion: 1e21, + septillion: 1e24, + grand: 1000, + }, +} diff --git a/src/subset/values/parseText/findModifiers.js b/plugins/numbers/src/convert/toNumber/findModifiers.js similarity index 75% rename from src/subset/values/parseText/findModifiers.js rename to plugins/numbers/src/convert/toNumber/findModifiers.js index 1f2363773..c828d695d 100644 --- a/src/subset/values/parseText/findModifiers.js +++ b/plugins/numbers/src/convert/toNumber/findModifiers.js @@ -1,33 +1,31 @@ -'use strict'; - //support global multipliers, like 'half-million' by doing 'million' then multiplying by 0.5 const findModifiers = str => { const mults = [ { reg: /^(minus|negative)[\s\-]/i, - mult: -1 + mult: -1, }, { reg: /^(a\s)?half[\s\-](of\s)?/i, - mult: 0.5 - } + mult: 0.5, + }, // { // reg: /^(a\s)?quarter[\s\-]/i, // mult: 0.25 // } - ]; + ] for (let i = 0; i < mults.length; i++) { if (mults[i].reg.test(str) === true) { return { amount: mults[i].mult, - str: str.replace(mults[i].reg, '') - }; + str: str.replace(mults[i].reg, ''), + } } } return { amount: 1, - str: str - }; -}; + str: str, + } +} -module.exports = findModifiers; +module.exports = findModifiers diff --git a/plugins/numbers/src/convert/toNumber/index.js b/plugins/numbers/src/convert/toNumber/index.js new file mode 100644 index 000000000..44adb0673 --- /dev/null +++ b/plugins/numbers/src/convert/toNumber/index.js @@ -0,0 +1,131 @@ +const findModifiers = require('./findModifiers') +const words = require('./data') +const isValid = require('./validate') +const parseDecimals = require('./parseDecimals') +const parseNumeric = require('./parseNumeric') +const improperFraction = /^([0-9,\. ]+)\/([0-9,\. ]+)$/ + +//some numbers we know +const casualForms = { + // 'a few': 3, + 'a couple': 2, + 'a dozen': 12, + 'two dozen': 24, + zero: 0, +} + +// a 'section' is something like 'fifty-nine thousand' +// turn a section into something we can add to - like 59000 +const section_sum = obj => { + return Object.keys(obj).reduce((sum, k) => { + sum += obj[k] + return sum + }, 0) +} + +//turn a string into a number +const parse = function(str) { + //convert some known-numbers + if (casualForms.hasOwnProperty(str) === true) { + return casualForms[str] + } + //'a/an' is 1 + if (str === 'a' || str === 'an') { + return 1 + } + const modifier = findModifiers(str) + str = modifier.str + let last_mult = null + let has = {} + let sum = 0 + let isNegative = false + const terms = str.split(/[ -]/) + for (let i = 0; i < terms.length; i++) { + let w = terms[i] + w = parseNumeric(w) + if (!w || w === 'and') { + continue + } + if (w === '-' || w === 'negative') { + isNegative = true + continue + } + if (w.charAt(0) === '-') { + isNegative = true + w = w.substr(1) + } + //decimal mode + if (w === 'point') { + sum += section_sum(has) + sum += parseDecimals(terms.slice(i + 1, terms.length)) + sum *= modifier.amount + return sum + } + //improper fraction + const fm = w.match(improperFraction) + if (fm) { + const num = parseFloat(fm[1].replace(/[, ]/g, '')) + const denom = parseFloat(fm[2].replace(/[, ]/g, '')) + if (denom) { + sum += num / denom || 0 + } + continue + } + //prevent mismatched units, like 'seven eleven' + if (isValid(w, has) === false) { + return null + } + //buildOut section, collect 'has' values + if (/^[0-9\.]+$/.test(w)) { + has['ones'] = parseFloat(w) //not technically right + } else if (words.ones.hasOwnProperty(w) === true) { + has['ones'] = words.ones[w] + } else if (words.teens.hasOwnProperty(w) === true) { + has['teens'] = words.teens[w] + } else if (words.tens.hasOwnProperty(w) === true) { + has['tens'] = words.tens[w] + } else if (words.multiples.hasOwnProperty(w) === true) { + let mult = words.multiples[w] + + //something has gone wrong : 'two hundred five hundred' + if (mult === last_mult) { + return null + } + //support 'hundred thousand' + //this one is tricky.. + if (mult === 100 && terms[i + 1] !== undefined) { + // has['hundreds']= + const w2 = terms[i + 1] + if (words.multiples[w2]) { + mult *= words.multiples[w2] //hundredThousand/hundredMillion + i += 1 + } + } + //natural order of things + //five thousand, one hundred.. + if (last_mult === null || mult < last_mult) { + sum += (section_sum(has) || 1) * mult + last_mult = mult + has = {} + } else { + //maybe hundred .. thousand + sum += section_sum(has) + last_mult = mult + sum = (sum || 1) * mult + has = {} + } + } + } + //dump the remaining has values + sum += section_sum(has) + //post-process add modifier + sum *= modifier.amount + sum *= isNegative ? -1 : 1 + //dont return 0, if it went straight-through + if (sum === 0 && Object.keys(has).length === 0) { + return null + } + return sum +} + +module.exports = parse diff --git a/plugins/numbers/src/convert/toNumber/parseDecimals.js b/plugins/numbers/src/convert/toNumber/parseDecimals.js new file mode 100644 index 000000000..cf657798e --- /dev/null +++ b/plugins/numbers/src/convert/toNumber/parseDecimals.js @@ -0,0 +1,23 @@ +const words = require('./data') + +//concatenate into a string with leading '0.' +const parseDecimals = function(arr) { + let str = '0.' + for (let i = 0; i < arr.length; i++) { + let w = arr[i] + if (words.ones.hasOwnProperty(w) === true) { + str += words.ones[w] + } else if (words.teens.hasOwnProperty(w) === true) { + str += words.teens[w] + } else if (words.tens.hasOwnProperty(w) === true) { + str += words.tens[w] + } else if (/^[0-9]$/.test(w) === true) { + str += w + } else { + return 0 + } + } + return parseFloat(str) +} + +module.exports = parseDecimals diff --git a/plugins/numbers/src/convert/toNumber/parseNumeric.js b/plugins/numbers/src/convert/toNumber/parseNumeric.js new file mode 100644 index 000000000..ac2b24d35 --- /dev/null +++ b/plugins/numbers/src/convert/toNumber/parseNumeric.js @@ -0,0 +1,19 @@ +//parse a string like "4,200.1" into Number 4200.1 +const parseNumeric = str => { + //remove ordinal - 'th/rd' + str = str.replace(/1st$/, '1') + str = str.replace(/2nd$/, '2') + str = str.replace(/3rd$/, '3') + str = str.replace(/([4567890])r?th$/, '$1') + //remove prefixes + str = str.replace(/^[$€¥£¢]/, '') + //remove suffixes + str = str.replace(/[%$€¥£¢]$/, '') + //remove commas + str = str.replace(/,/g, '') + //split '5kg' from '5' + str = str.replace(/([0-9])([a-z\u00C0-\u00FF]{1,2})$/, '$1') + return str +} + +module.exports = parseNumeric diff --git a/plugins/numbers/src/convert/toNumber/validate.js b/plugins/numbers/src/convert/toNumber/validate.js new file mode 100644 index 000000000..d3e3c0f7e --- /dev/null +++ b/plugins/numbers/src/convert/toNumber/validate.js @@ -0,0 +1,20 @@ +const words = require('./data') + +//prevent things like 'fifteen ten', and 'five sixty' +const isValid = (w, has) => { + if (words.ones.hasOwnProperty(w)) { + if (has.ones || has.teens) { + return false + } + } else if (words.teens.hasOwnProperty(w)) { + if (has.ones || has.teens || has.tens) { + return false + } + } else if (words.tens.hasOwnProperty(w)) { + if (has.ones || has.teens || has.tens) { + return false + } + } + return true +} +module.exports = isValid diff --git a/plugins/numbers/src/convert/toOrdinal/numOrdinal.js b/plugins/numbers/src/convert/toOrdinal/numOrdinal.js new file mode 100644 index 000000000..3042cc73d --- /dev/null +++ b/plugins/numbers/src/convert/toOrdinal/numOrdinal.js @@ -0,0 +1,32 @@ +const toString = require('../_toString') + +/** + * turn a number like 5 into an ordinal like 5th + */ +const numOrdinal = function(num) { + if (!num && num !== 0) { + return null + } + //the teens are all 'th' + let tens = num % 100 + if (tens > 10 && tens < 20) { + return String(num) + 'th' + } + //the rest of 'em + const mapping = { + 0: 'th', + 1: 'st', + 2: 'nd', + 3: 'rd', + } + let str = toString(num) + let last = str.slice(str.length - 1, str.length) + if (mapping[last]) { + str += mapping[last] + } else { + str += 'th' + } + return str +} + +module.exports = numOrdinal diff --git a/plugins/numbers/src/convert/toOrdinal/textOrdinal.js b/plugins/numbers/src/convert/toOrdinal/textOrdinal.js new file mode 100644 index 000000000..7f4569094 --- /dev/null +++ b/plugins/numbers/src/convert/toOrdinal/textOrdinal.js @@ -0,0 +1,38 @@ +const textValue = require('../toText') +// const toString = require('../_toString') + +const irregulars = { + one: 'first', + two: 'second', + three: 'third', + five: 'fifth', + eight: 'eighth', + nine: 'ninth', + twelve: 'twelfth', + twenty: 'twentieth', + thirty: 'thirtieth', + forty: 'fortieth', + fourty: 'fourtieth', + fifty: 'fiftieth', + sixty: 'sixtieth', + seventy: 'seventieth', + eighty: 'eightieth', + ninety: 'ninetieth', +} + +/** + * convert a javascript number to 'twentieth' format + * */ +const textOrdinal = num => { + let words = textValue(num).split(' ') + //convert the last number to an ordinal + let last = words[words.length - 1] + if (irregulars.hasOwnProperty(last)) { + words[words.length - 1] = irregulars[last] + } else { + words[words.length - 1] = last.replace(/y$/, 'i') + 'th' + } + return words.join(' ') +} + +module.exports = textOrdinal diff --git a/plugins/numbers/src/convert/toText/index.js b/plugins/numbers/src/convert/toText/index.js new file mode 100644 index 000000000..5be5d8c62 --- /dev/null +++ b/plugins/numbers/src/convert/toText/index.js @@ -0,0 +1,159 @@ +const toString = require('../_toString') +/** + * turns an integer/float into.ber, like 'fifty-five' + */ + +const tens_mapping = [ + ['ninety', 90], + ['eighty', 80], + ['seventy', 70], + ['sixty', 60], + ['fifty', 50], + ['forty', 40], + ['thirty', 30], + ['twenty', 20], +] +const ones_mapping = [ + '', + 'one', + 'two', + 'three', + 'four', + 'five', + 'six', + 'seven', + 'eight', + 'nine', + 'ten', + 'eleven', + 'twelve', + 'thirteen', + 'fourteen', + 'fifteen', + 'sixteen', + 'seventeen', + 'eighteen', + 'nineteen', +] + +const sequence = [ + [1e24, 'septillion'], + [1e20, 'hundred sextillion'], + [1e21, 'sextillion'], + [1e20, 'hundred quintillion'], + [1e18, 'quintillion'], + [1e17, 'hundred quadrillion'], + [1e15, 'quadrillion'], + [1e14, 'hundred trillion'], + [1e12, 'trillion'], + [1e11, 'hundred billion'], + [1e9, 'billion'], + [1e8, 'hundred million'], + [1e6, 'million'], + [100000, 'hundred thousand'], + [1000, 'thousand'], + [100, 'hundred'], + [1, 'one'], +] + +//turn number into an array of magnitudes, like [[5, million], [2, hundred]] +const breakdown_magnitudes = function(num) { + let working = num + let have = [] + sequence.forEach(a => { + if (num >= a[0]) { + let howmany = Math.floor(working / a[0]) + working -= howmany * a[0] + if (howmany) { + have.push({ + unit: a[1], + count: howmany, + }) + } + } + }) + return have +} + +//turn numbers from 100-0 into their text +const breakdown_hundred = function(num) { + let arr = [] + if (num > 100) { + return arr //something bad happened.. + } + for (let i = 0; i < tens_mapping.length; i++) { + if (num >= tens_mapping[i][1]) { + num -= tens_mapping[i][1] + arr.push(tens_mapping[i][0]) + } + } + //(hopefully) we should only have 20-0 now + if (ones_mapping[num]) { + arr.push(ones_mapping[num]) + } + return arr +} + +/** print-out 'point eight nine'*/ +const handle_decimal = num => { + const names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] + let arr = [] + //parse it out like a string, because js math is such shit + let str = toString(num) + let decimal = str.match(/\.([0-9]+)/) + if (!decimal || !decimal[0]) { + return arr + } + arr.push('point') + let decimals = decimal[0].split('') + for (let i = 0; i < decimals.length; i++) { + arr.push(names[decimals[i]]) + } + return arr +} + +/** turns an integer into a textual number */ +const to_text = function(num) { + // handle zero, quickly + if (num === 0 || num === '0') { + return 'zero' // no? + } + //big numbers, north of sextillion, aren't gonna work well.. + //keep them small.. + if (num > 1e21) { + num = toString(num) + } + let arr = [] + //handle negative numbers + if (num < 0) { + arr.push('minus') + num = Math.abs(num) + } + //break-down into units, counts + let units = breakdown_magnitudes(num) + //build-up the string from its components + for (let i = 0; i < units.length; i++) { + let unit_name = units[i].unit + if (unit_name === 'one') { + unit_name = '' + //put an 'and' in here + if (arr.length > 1) { + arr.push('and') + } + } + arr = arr.concat(breakdown_hundred(units[i].count)) + arr.push(unit_name) + } + //also support decimals - 'point eight' + arr = arr.concat(handle_decimal(num)) + //remove empties + arr = arr.filter(s => s) + if (arr.length === 0) { + arr[0] = '' + } + return arr.join(' ') +} + +module.exports = to_text + +// console.log(to_text(-1000.8)); diff --git a/plugins/numbers/src/find.js b/plugins/numbers/src/find.js new file mode 100644 index 000000000..30ca2ba61 --- /dev/null +++ b/plugins/numbers/src/find.js @@ -0,0 +1,75 @@ +const tens = 'twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty' +const teens = 'eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen' + +// this is a bit of a mess +const findNumbers = function(doc, n) { + let match = doc.match('#Value+') + + //"50 83" + if (match.has('#NumericValue #NumericValue')) { + //a comma may mean two numbers + if (match.has('#Value @hasComma #Value')) { + match.splitAfter('@hasComma') + } else { + match = match.splitAfter('#NumericValue') + } + } + //three-length + if (match.has('#Value #Value #Value') && !match.has('#Multiple')) { + //twenty-five-twenty + if (match.has('(' + tens + ') #Cardinal #Cardinal')) { + match = match.splitAfter('(' + tens + ') #Cardinal') + } + } + + //two-length ones + if (match.has('#Value #Value')) { + //june 21st 1992 is two seperate values + if (match.has('#NumericValue #NumericValue')) { + match = match.splitOn('#Year') + } + //sixty fifteen + if (match.has('(' + tens + ') (' + teens + ')')) { + match = match.splitAfter('(' + tens + ')') + } + //"72 82" + let double = match.match('#Cardinal #Cardinal') + if (double.found && !match.has('(point|decimal)')) { + //not 'two hundred' + if (!double.has('#Cardinal (#Multiple|point|decimal)')) { + //one proper way, 'twenty one', or 'hundred one' + if (!double.has('(' + tens + ') #Cardinal') && !double.has('#Multiple #Value')) { + // double = double.firstTerm() + double.terms().forEach(d => { + match = match.splitOn(d) + }) + } + } + } + //seventh fifth + if (match.match('#Ordinal #Ordinal').match('#TextValue').found && !match.has('#Multiple')) { + //the one proper way, 'twenty first' + if (!match.has('(' + tens + ') #Ordinal')) { + match = match.splitAfter('#Ordinal') + } + } + //fifth five + if (match.has('#Ordinal #Cardinal')) { + match = match.splitBefore('#Cardinal+') + } + //five 2017 (support '5 hundred', and 'twenty 5' + if (match.has('#TextValue #NumericValue') && !match.has('(' + tens + '|#Multiple)')) { + match = match.splitBefore('#NumericValue+') + } + } + //5-8 + if (match.has('#NumberRange')) { + match = match.splitAfter('#NumberRange') + } + //grab (n)th result + if (typeof n === 'number') { + match = match.get(n) + } + return match +} +module.exports = findNumbers diff --git a/plugins/numbers/src/index.js b/plugins/numbers/src/index.js new file mode 100644 index 000000000..5b2a3ba85 --- /dev/null +++ b/plugins/numbers/src/index.js @@ -0,0 +1,28 @@ +const findNumbers = require('./find') +const methods = require('./methods') +const tagger = require('./tagger') +const tags = require('./tags') + +/** adds .numbers() method */ +const addMethod = function(Doc, world) { + // add tags to our tagset + world.addTags(tags) + + // additional tagging before running the number-parser + world.postProcess(tagger) + + /** a list of number values, and their units */ + class Numbers extends Doc {} + //aliases + Object.assign(Numbers.prototype, methods) + + /** find all numbers and values */ + Doc.prototype.numbers = function(n) { + let match = findNumbers(this, n) + return new Numbers(match.list, this, this.world) + } + // alias for reverse-compatibility + Doc.prototype.values = Doc.prototype.numbers + return Doc +} +module.exports = addMethod diff --git a/plugins/numbers/src/methods.js b/plugins/numbers/src/methods.js new file mode 100644 index 000000000..e8119bba4 --- /dev/null +++ b/plugins/numbers/src/methods.js @@ -0,0 +1,242 @@ +const parseNumber = require('./parse') +const agreeUnits = require('./_agreeUnits') +const makeNumber = require('./convert/makeNumber') +const toNumber = require('./convert/toNumber') + +let methods = { + /** overloaded json method with additional number information */ + json: function(options) { + let n = null + if (typeof options === 'number') { + n = options + options = null + } + options = options || { text: true, normal: true, trim: true, terms: true } + let res = [] + this.forEach(doc => { + let json = doc.json(options)[0] + let obj = parseNumber(doc) + json.prefix = obj.prefix + json.number = obj.num + json.suffix = obj.suffix + json.cardinal = makeNumber(obj, false, false) + json.ordinal = makeNumber(obj, false, true) + json.textCardinal = makeNumber(obj, true, false) + json.textOrdinal = makeNumber(obj, true, true) + res.push(json) + }) + if (n !== null) { + return res[n] + } + return res + }, + /** two of what? */ + units: function() { + return this.lookAhead('^(#Unit|#Noun)') + }, + /** return only ordinal numbers */ + isOrdinal: function() { + return this.if('#Ordinal') + }, + /** return only cardinal numbers*/ + isCardinal: function() { + return this.if('#Cardinal') + }, + /** convert to numeric form like '8' or '8th' */ + toNumber: function() { + this.forEach(val => { + let obj = parseNumber(val) + if (obj.num === null) { + return + } + let str = makeNumber(obj, false, val.has('#Ordinal')) + val.replaceWith(str, true) + val.tag('NumericValue') + }) + return this + }, + /** add commas, or nicer formatting for numbers */ + toLocaleString: function() { + this.forEach(val => { + let obj = parseNumber(val) + if (obj.num === null) { + return + } + obj.num = obj.num.toLocaleString() + let str = makeNumber(obj, false, val.has('#Ordinal')) + val.replaceWith(str, true) + }) + return this + }, + /** convert to text form - like 'eight' or 'eigth'*/ + toText: function() { + this.forEach(val => { + let obj = parseNumber(val) + if (obj.num === null) { + return + } + let str = makeNumber(obj, true, val.has('#Ordinal')) + val.replaceWith(str, true) + val.tag('TextValue') + }) + return this + }, + /** convert to cardinal form, like 'eight', or '8' */ + toCardinal: function(agree) { + let m = this.if('#Ordinal') + m.forEach(val => { + let obj = parseNumber(val) + if (obj.num === null) { + return + } + let str = makeNumber(obj, val.has('#TextValue'), false) + val.replaceWith(str, true, true) + val.tag('Cardinal') + // turn unit into plural -> 'seven beers' + agreeUnits(agree, val, obj) + }) + return this + }, + /** convert to ordinal form, like 'eighth', or '8th' */ + toOrdinal: function() { + let m = this.if('#Cardinal') + m.forEach(val => { + let obj = parseNumber(val) + if (obj.num === null) { + return + } + let str = makeNumber(obj, val.has('#TextValue'), true) + val.replaceWith(str, true, true) + val.tag('Ordinal') + // turn unit into singular -> 'seventh beer' + let unit = this.lookAhead('^#Plural') + if (unit.found) { + unit.nouns().toSingular() + } + }) + return this + }, + /** return only numbers that are == n */ + isEqual: function(n) { + return this.filter(val => { + let num = parseNumber(val).num + return num === n + }) + }, + /** return only numbers that are > n*/ + greaterThan: function(n) { + return this.filter(val => { + let num = parseNumber(val).num + return num > n + }) + }, + /** return only numbers that are < n*/ + lessThan: function(n) { + return this.filter(val => { + let num = parseNumber(val).num + return num < n + }) + }, + /** return only numbers > min and < max */ + between: function(min, max) { + return this.filter(val => { + let num = parseNumber(val).num + return num > min && num < max + }) + }, + /** set these number to n */ + set: function(n, agree) { + if (n === undefined) { + return this // don't bother + } + if (typeof n === 'string') { + n = toNumber(n) + } + this.forEach(val => { + let obj = parseNumber(val) + obj.num = n + if (obj.num === null) { + return + } + let str = makeNumber(obj, val.has('#TextValue'), val.has('#Ordinal')) + val.replaceWith(str, true, true) + // handle plural/singular unit + agreeUnits(agree, val, obj) + }) + return this + }, + add: function(n, agree) { + if (!n) { + return this // don't bother + } + if (typeof n === 'string') { + n = toNumber(n) + } + this.forEach(val => { + let obj = parseNumber(val) + + if (obj.num === null) { + return + } + obj.num += n + let str = makeNumber(obj, val.has('#TextValue'), val.has('#Ordinal')) + val.replaceWith(str, true, true) + // handle plural/singular unit + agreeUnits(agree, val, obj) + }) + return this + }, + /** decrease each number by n*/ + subtract: function(n, agree) { + return this.add(n * -1, agree) + }, + /** increase each number by 1 */ + increment: function(agree) { + this.add(1, agree) + return this + }, + /** decrease each number by 1 */ + decrement: function(agree) { + this.add(-1, agree) + return this + }, + + /// ---- + + /** return things like 1/3rd */ + fractions: function(n) { + let m = this.match('#Fraction') + if (typeof n === 'number') { + m = m.get(n) + } + return m + }, + + /** return things like CCXX*/ + romanNumerals: function(n) { + let m = this.match('#RomanNumeral').numbers() + if (typeof n === 'number') { + m = m.get(n) + } + return m + }, + + /** return things like $4.50*/ + money: function(n) { + let m = this.splitOn('@hasComma') + m = m.match('#Money+ #Currency?') + m = m.numbers() + if (typeof n === 'number') { + m = m.get(n) + } + return m + }, +} +// aliases +methods.toNice = methods.toLocaleString +methods.isBetween = methods.between +methods.minus = methods.subtract +methods.plus = methods.add +methods.equals = methods.isEqual + +module.exports = methods diff --git a/plugins/numbers/src/parse.js b/plugins/numbers/src/parse.js new file mode 100644 index 000000000..b7ead2da6 --- /dev/null +++ b/plugins/numbers/src/parse.js @@ -0,0 +1,48 @@ +const toNumber = require('./convert/toNumber') + +// get a numeric value from this phrase +const parseNumber = function(p) { + let str = p.text('reduced') + // is it in '3,123' format? + let hasComma = /[0-9],[0-9]/.test(p.text('text')) + str = str.replace(/,/g, '') + + //parse a numeric-number (easy) + let arr = str.split(/^([^0-9]*)([0-9.,]*)([^0-9]*)$/) + if (arr && arr[2] && p.terms().length < 2) { + let num = parseFloat(arr[2] || str) + //ensure that num is an actual number + if (typeof num !== 'number') { + num = null + } + // strip an ordinal off the suffix + let suffix = arr[3] || '' + if (suffix === 'st' || suffix === 'nd' || suffix === 'rd' || suffix === 'th') { + suffix = '' + } + // support M for million, k for thousand + if (suffix === 'm' || suffix === 'M') { + num *= 1000000 + suffix = '' + } + if (suffix === 'k' || suffix === 'k') { + num *= 1000 + suffix = '' + } + return { + hasComma: hasComma, + prefix: arr[1] || '', + num: num, + suffix: suffix, + } + } + //parse a text-numer (harder) + let num = toNumber(str) + return { + hasComma: hasComma, + prefix: '', + num: num, + suffix: '', + } +} +module.exports = parseNumber diff --git a/plugins/numbers/src/tagger.js b/plugins/numbers/src/tagger.js new file mode 100644 index 000000000..4c87ab60c --- /dev/null +++ b/plugins/numbers/src/tagger.js @@ -0,0 +1,16 @@ +const multiples = + '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)' + +// improved tagging for numbers +const tagger = function(doc) { + doc.match(multiples).tag('#Multiple') + // in the 400s + doc.match('the [/[0-9]+s$/]').tag('#Plural') + //half a million + doc.match('half a? #Value').tag('Value', 'half-a-value') //(quarter not ready) + //five and a half + doc.match('#Value and a (half|quarter)').tag('Value', 'value-and-a-half') + //one hundred and seven dollars + doc.match('#Money and #Money #Currency?').tag('Money', 'money-and-money') +} +module.exports = tagger diff --git a/plugins/numbers/src/tags.js b/plugins/numbers/src/tags.js new file mode 100644 index 000000000..46bae241c --- /dev/null +++ b/plugins/numbers/src/tags.js @@ -0,0 +1,8 @@ +module.exports = { + Fraction: { + isA: 'Value', + }, + Multiple: { + isA: 'Value', + }, +} diff --git a/plugins/numbers/tests/_lib.js b/plugins/numbers/tests/_lib.js new file mode 100644 index 000000000..254633449 --- /dev/null +++ b/plugins/numbers/tests/_lib.js @@ -0,0 +1,12 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + } + + module.exports = nlp +} diff --git a/plugins/numbers/tests/agreement.test.js b/plugins/numbers/tests/agreement.test.js new file mode 100644 index 000000000..531c11e31 --- /dev/null +++ b/plugins/numbers/tests/agreement.test.js @@ -0,0 +1,26 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('misc agreement', function(t) { + let doc = nlp('i ate 7 kilos of fruit') + .numbers() + .units() + t.equal(doc.text('trim'), 'kilos', 'found unit') + + doc = nlp('i ate 7 of them, kilos are kilograms') + .numbers() + .units() + t.equal(doc.text('trim'), '', 'found no unit') + + t.end() +}) + +test('ordinal agreement', function(t) { + let doc = nlp('seventeen beers') + doc.values().toOrdinal() + t.equal(doc.text(), 'seventeenth beer') + + doc.values().toCardinal() + t.equal(doc.text(), 'seventeen beers') + t.end() +}) diff --git a/plugins/numbers/tests/bigNumber.test.js b/plugins/numbers/tests/bigNumber.test.js new file mode 100644 index 000000000..aaf9a8529 --- /dev/null +++ b/plugins/numbers/tests/bigNumber.test.js @@ -0,0 +1,163 @@ +const test = require('tape') +const nlp = require('./_lib') + +const cardinal = function(str) { + return nlp(str) + .values() + .json(0).number +} + +test('a very large cardinal', function(t) { + t.equal(cardinal('nine trillion two hundred'), 9000000000200, 'trillion') + t.equal(cardinal('nine quadrillion two thousand and six'), 9000000000002006, 'quadrillion') + t.equal(cardinal('ninety quintillion two thousand and six'), 90000000000000002006, 'quintilion') + t.equal( + cardinal('ninety nine quintillion two thousand and six'), + 99000000000000002006, + 'quintilion 2' + ) + t.equal(cardinal('nine sextillion'), 9000000000000000000000, 'sextillion') + // t.equal(cardinal('nine septillion'), 9000000000000000000000000); + // t.equal(cardinal('ninety nine septillion two thousand and six'), 99000000000000000002006); + // t.equal(cardinal('one hundred and twenty-three septillion, four hundred and fifty-six sextillion, seven hundred and eighty-nine quintillion, one hundred and twenty-three quadrillion, four hundred and fifty-six trillion, seven hundred and eighty-nine billion, one hundred and twenty-three million, four hundred and fifty-six thousand and seven hundred and eighty-nine'), 123456789123456789123456789); + // t.equal(cardinal('seven hundred and eighty-nine quintillion, one hundred and twenty-three quadrillion, four hundred and fifty-six trillion, seven hundred and eighty-nine billion, one hundred and twenty-three million, four hundred and fifty-six thousand and seven hundred and eighty-nine'), 789123456789123456789); + t.end() +}) + +test('number ordinal', function(t) { + t.equal( + nlp('two hundred trillion') + .values() + .toOrdinal() + .toNice() + .text(), + '200,000,000,000,000th' + ) + t.equal( + nlp('thirty seven quadrillion and two hundred') + .values() + .toOrdinal() + .toNice() + .text(), + '37,000,000,000,000,200th' + ) + t.equal( + nlp('thirty seven quadrillion, two thousand') + .values() + .toOrdinal() + .toNice() + .text(), + '37,000,000,000,002,000th' + ) + t.equal( + nlp('ninety nine quadrillion, two hundred thousand') + .values() + .toOrdinal() + .toNice() + .text(), + '99,000,000,000,200,000th' + ) + //javascript math can't do this. + // t.equal(nlp('thirty sextillion and two').values().data()[0].niceOrdinal, '30,000,000,000,000,000,000,002nd'); + // t.equal(nlp('ninety nine quadrillion, two hundred and fifty thousand').values().data()[0].niceOrdinal, '99,000,000,000,250,000th'); + t.end() +}) + +test('text ordinal', function(t) { + t.equal( + nlp('thirty quadrillion and two hundred') + .values() + .json()[0].textOrdinal, + 'thirty quadrillion two hundredth' + ) + t.equal( + nlp('nine trillion seven hundred fifty') + .values() + .json()[0].textOrdinal, + 'nine trillion seven hundred and fiftieth' + ) + t.equal( + nlp('a quintillion') + .values() + .json()[0].textOrdinal, + 'one quintillionth' + ) + t.equal( + nlp('seventy-two quintillion') + .values() + .json()[0].textOrdinal, + 'seventy two quintillionth' + ) + t.end() +}) + +test('from number', function(t) { + t.equal( + nlp('9000000000200') + .values() + .toText() + .out(), + 'nine trillion two hundred' + ) + t.equal( + nlp('70000000000200') + .values() + .toText() + .out(), + 'seventy trillion two hundred' + ) + t.equal( + nlp('9000000000002006') + .values() + .toText() + .out(), + 'nine quadrillion two thousand and six' + ) + t.equal( + nlp('900,000,000') + .values() + .toText() + .out(), + 'nine hundred million' + ) + t.equal( + nlp('9,000,000,030') + .values() + .toText() + .out(), + 'nine billion and thirty' + ) + t.equal( + nlp('10,000,000,000') + .values() + .toText() + .out(), + 'ten billion' + ) + // t.equal(nlp('900,000,000,037').values().toText().out(), 'nine hundred billion and thirty seven'); + //javascript can't do this + // t.equal(nlp('90000000000000002006').values().toText().out(), 'ninety quintillion two thousand and six'); + // t.equal(nlp('99000000000000002006').values().toText().out(), 'ninety nine quintillion two thousand and six'); + // t.equal(nlp('9000000000000000000000').values().toText().out(), 'nine sextillion'); + t.end() +}) + +// test('cardinal numbers', function(t) { +// t.equal(cardinal('sixty-one trillion, six hundred and eighty-nine billion, four hundred and seventy-three million, four hundred and fifty-three thousand and five hundred and ninety'), 61689473453590); +// t.end(); +// }); + +// test('cardinal numbers in american form (with ands)', function(t) { +// t.equal(cardinal('six hundred eighty-nine billion, four hundred seventy-three million, four hundred fifty-three thousand, five hundred ninety'), 689473453590); +// t.end(); +// }); + +// test('ordinal numbers', function(t) { +// t.equal(cardinal('six hundred and eighty-nine billion, four hundred and seventy-three million, four hundred and fifty-three thousand and five hundred and ninetieth'), 689473453590); +// t.end(); +// }); + +// test('cardinal numbers in american form (with ands)', function(t) { +// t.equal(cardinal('six hundred eighty-nine billion, four hundred seventy-three million, four hundred fifty-three thousand, five hundred ninetieth'), 689473453590); +// t.end(); +// }); diff --git a/plugins/numbers/tests/misc.test.js b/plugins/numbers/tests/misc.test.js new file mode 100644 index 000000000..d88a77bfe --- /dev/null +++ b/plugins/numbers/tests/misc.test.js @@ -0,0 +1,34 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('misc values', function(t) { + let doc = nlp(`quickly, suddenly`) + t.equal(doc.values().length, 0, 'found no values') + + doc = nlp(`seven is slightly before eleven, but after two.`) + t.equal(doc.values().length, 3, 'found three values') + + doc = nlp('742 Evergreen Terrace') + doc.numbers().set('eleven') + t.equal(doc.text('trim'), '11 Evergreen Terrace', 'address can be value') + t.end() +}) + +test('misc:', function(t) { + let str = '2 million five hundred thousand and fifty nine is bigger than 2882' + let m = nlp(str) + m.values().toNumber() + t.equal(m.out('normal'), '2500059 is bigger than 2882', str) + + str = '2 million five hundred thousand and fifty nine is bigger than 2882' + m = nlp(str) + m.values().toNice() + t.equal(m.out('text'), '2,500,059 is bigger than 2,882', str) + + str = 'doug is 5 years old' + m = nlp(str) + m.values().toText() + t.equal(m.out('normal'), 'doug is five years old', str) + + t.end() +}) diff --git a/plugins/numbers/tests/money.ignore.js b/plugins/numbers/tests/money.ignore.js new file mode 100644 index 000000000..33f3281ba --- /dev/null +++ b/plugins/numbers/tests/money.ignore.js @@ -0,0 +1,53 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('money-basic:', function(t) { + let r = nlp('it is $70.23') + let m = r.match('#Money') + t.equal(m.out('normal'), '$70.23', 'match-$70.23') + + r = nlp('it is $703') + m = r.match('#Money+') + t.equal(m.out('normal'), '$703', 'match-$703') + + r = nlp('it is five euros') + m = r.match('#Money+') + t.equal(m.out('normal'), 'five euros', 'match-five-euros') + + r = nlp('i said five times, you should pay 12 dollars') + m = r.match('#Money+') + t.equal(m.out('normal'), '12 dollars', 'match-12 dollars') + + r = nlp('you should pay sixty five dollars and four cents USD') + m = r.match('#Money+') + t.equal(m.out('normal'), 'sixty five dollars and four cents usd', 'match-long-usd') + + t.end() +}) + +test('money-has:', function(t) { + let tests = [ + ['$7', true], + ['$7.0', true], + ['$7.00', true], + ['$7.003', false], + + ['$7082.03', true], + ['$2,082.03', true], + ['€7.00', true], + ['¥70', true], + ['£0.20', true], + ['@0.20', false], + + ['8 cents', true], + ['60 pence', true], + ['sixty pence', true], + ['sixty USD', true], + ] + tests.forEach(function(a) { + let r = nlp(a[0]) + let m = r.match('#Money') + t.equal(m.found, a[1], "money-has: '" + a[0] + "'") + }) + t.end() +}) diff --git a/plugins/numbers/tests/percent.test.js b/plugins/numbers/tests/percent.test.js new file mode 100644 index 000000000..3c8c4c519 --- /dev/null +++ b/plugins/numbers/tests/percent.test.js @@ -0,0 +1,76 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('percent-basic:', function(t) { + let m = nlp('it is 33%').match('#Percent') + t.equal(m.out('normal'), '33%', 'match-33%') + + //parse number + let arr = nlp('it is 50% of our budget') + .values() + .json() + t.equal(arr[0].number, 50, 'match-50') + + arr = nlp('it is 9,000% of our budget') + .values() + .json() + t.equal(arr[0].number, 9000, 'match-9000') + + //percent-decimal + arr = nlp('it is 0.5% of our budget') + .values() + .json() + t.equal(arr[0].number, 0.5, 'match-0.5') + + t.end() +}) + +test('percent-conversion:', function(t) { + let str = '3% of the budget' + let r = nlp(str) + .values() + .toNumber() + .all() + t.equal(r.out(), str, '3% to number') + + str = "it's 39% of the budget" + r = nlp(str) + .values() + .toNumber() + .all() + t.equal(r.out(), str, '39% to number') + + str = '39% of the budget' + r = nlp(str) + .values() + .toText() + .all() + t.equal(r.out(), 'thirty nine percent of the budget', 'to text') + + str = 'around 100% of the budget' + r = nlp(str) + .values() + .toText() + .all() + t.equal(r.out(), 'around one hundred percent of the budget', 'to text') + + t.end() +}) + +test('percent-tag:', function(t) { + let tests = [ + ['7%', true], + ['7.0%', true], + ['2.22%', true], + ['.2%', true], + ['0.2%', true], + ['2,999%', true], + ['2asdf99%', false], + ['99%3', false], + ] + tests.forEach(function(a) { + let r = nlp(a[0]) + t.equal(r.has('#Percent'), a[1], "Percent-has: '" + a[0] + "'") + }) + t.end() +}) diff --git a/plugins/numbers/tests/prefix.test.js b/plugins/numbers/tests/prefix.test.js new file mode 100644 index 000000000..18153b4b8 --- /dev/null +++ b/plugins/numbers/tests/prefix.test.js @@ -0,0 +1,34 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('prefix:', function(t) { + let doc = nlp('it was almost $400') + doc.values().toText() + t.equals(doc.text(), 'it was almost four hundred dollars', '$400') + + t.end() +}) + +test('suffix:', function(t) { + let doc = nlp('it was 400USD') + doc.values().toText() + t.equals(doc.text(), 'it was four hundred USD', '400usd') + + doc = nlp('it was 4.5m') + doc.values().toText() + t.equals(doc.text(), 'it was four million five hundred thousand', '4.5m') + + doc = nlp('it was $47.5m') + doc.values().toText() + t.equals(doc.text(), 'it was forty seven million five hundred thousand dollars', '$47.5m') + + doc = nlp('i ran 25km uphill') + doc.values().toText() + t.equals(doc.text(), 'i ran twenty five kilometres uphill', '25km') + + doc = nlp('it was 400s!') + doc.values().toText() + t.equals(doc.text(), 'it was four hundred seconds!', '400s!') + + t.end() +}) diff --git a/plugins/numbers/tests/toCardinal.test.js b/plugins/numbers/tests/toCardinal.test.js new file mode 100644 index 000000000..403e45c25 --- /dev/null +++ b/plugins/numbers/tests/toCardinal.test.js @@ -0,0 +1,125 @@ +const test = require('tape') +const nlp = require('./_lib') +//tests 'borrowed' from Travis Savo's lib 💝 https://github.com/TSavo/english2number-js +const cardinal = function(str) { + return nlp(str) + .values() + .json(0).number +} + +test('should give right answers for numbers', function(t) { + t.equal(cardinal('0'), 0) + t.equal(cardinal('1'), 1) + t.equal(cardinal('2'), 2) + t.equal(cardinal('3'), 3) + t.equal(cardinal('4'), 4) + t.equal(cardinal('5'), 5) + t.equal(cardinal('6'), 6) + t.equal(cardinal('7'), 7) + t.equal(cardinal('8'), 8) + t.equal(cardinal('9'), 9) + t.equal(cardinal('10'), 10) + t.equal(cardinal('20'), 20) + t.equal(cardinal('30'), 30) + t.equal(cardinal('50'), 50) + t.equal(cardinal('90'), 90) + t.equal(cardinal('100'), 100) + t.end() +}) +test('should give right answers for numbered ordinals', function(t) { + t.equal(cardinal('0th'), 0) + t.equal(cardinal('1st'), 1) + t.equal(cardinal('2nd'), 2) + t.equal(cardinal('3rd'), 3) + t.equal(cardinal('4th'), 4) + t.equal(cardinal('5th'), 5) + t.equal(cardinal('6th'), 6) + t.equal(cardinal('7th'), 7) + t.equal(cardinal('8th'), 8) + t.equal(cardinal('9th'), 9) + t.equal(cardinal('10th'), 10) + t.equal(cardinal('20th'), 20) + t.equal(cardinal('30th'), 30) + t.equal(cardinal('50th'), 50) + t.equal(cardinal('77th'), 77) + t.equal(cardinal('90th'), 90) + t.equal(cardinal('100th'), 100) + t.end() +}) +test('should give right answers for english names of numbers', function(t) { + t.equal(cardinal('zero'), 0) + t.equal(cardinal('one'), 1) + t.equal(cardinal('two'), 2) + t.equal(cardinal('three'), 3) + t.equal(cardinal('four'), 4) + t.equal(cardinal('five'), 5) + t.equal(cardinal('six'), 6) + t.equal(cardinal('seven'), 7) + t.equal(cardinal('eight'), 8) + t.equal(cardinal('nine'), 9) + t.equal(cardinal('ten'), 10) + t.equal(cardinal('eleven'), 11) + t.equal(cardinal('twelve'), 12) + t.equal(cardinal('thirteen'), 13) + t.equal(cardinal('fourteen'), 14) + t.equal(cardinal('fifteen'), 15) + t.equal(cardinal('sixteen'), 16) + t.equal(cardinal('seventeen'), 17) + t.equal(cardinal('eighteen'), 18) + t.equal(cardinal('nineteen'), 19) + t.equal(cardinal('twenty'), 20) + t.equal(cardinal('twenty-five'), 25) + t.equal(cardinal('twenty five'), 25) + t.equal(cardinal('forty-four'), 44) + t.equal(cardinal('forty four'), 44) + t.equal(cardinal('fourty four'), 44) //typo + t.equal(cardinal('seventy'), 70) + t.equal(cardinal('seventy-seven'), 77) + t.equal(cardinal('eighty eight'), 88) + t.equal(cardinal('ninety nine'), 99) + t.equal(cardinal('one-hundred'), 100) + t.equal(cardinal('one hundred'), 100) + t.end() +}) +test('should give right answers for english names of ordinal positions', function(t) { + t.equal(cardinal('zeroth'), 0) + t.equal(cardinal('first'), 1) + t.equal(cardinal('second'), 2) + t.equal(cardinal('third'), 3) + t.equal(cardinal('fourth'), 4) + t.equal(cardinal('fifth'), 5) + t.equal(cardinal('sixth'), 6) + t.equal(cardinal('seventh'), 7) + t.equal(cardinal('eighth'), 8) + t.equal(cardinal('ninth'), 9) + t.equal(cardinal('tenth'), 10) + t.equal(cardinal('eleventh'), 11) + t.equal(cardinal('twelfth'), 12) + t.equal(cardinal('thirteenth'), 13) + t.equal(cardinal('fourteenth'), 14) + t.equal(cardinal('fifteenth'), 15) + t.equal(cardinal('sixteenth'), 16) + t.equal(cardinal('seventeenth'), 17) + t.equal(cardinal('eighteenth'), 18) + t.equal(cardinal('nineteenth'), 19) + t.equal(cardinal('twentieth'), 20) + t.equal(cardinal('twenty first'), 21) + t.equal(cardinal('twenty second'), 22) + t.equal(cardinal('twenty third'), 23) + t.equal(cardinal('twenty fourth'), 24) + t.equal(cardinal('twenty-fifth'), 25) + t.equal(cardinal('forty-fourth'), 44) + t.equal(cardinal('seventieth'), 70) + t.equal(cardinal('seventy-seventh'), 77) + t.equal(cardinal('ninetieth'), 90) + t.equal(cardinal('ninety ninth'), 99) + t.equal(cardinal('one-hundredth'), 100) + t.end() +}) + +test('should deal with negative numbers', function(t) { + t.equal(cardinal('negative thirty eight thousand two hundred sixty three'), -38263) + t.equal(cardinal('negative thirty eight thousand two hundred sixty three'), -38263) + t.equal(cardinal('negative zero'), -0) + t.end() +}) diff --git a/plugins/numbers/tests/toText.test.js b/plugins/numbers/tests/toText.test.js new file mode 100644 index 000000000..225e080b9 --- /dev/null +++ b/plugins/numbers/tests/toText.test.js @@ -0,0 +1,90 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('to_text:', function(t) { + let arr = [ + // [-5, 'negative five'], + [5, 'five'], + [15, 'fifteen'], + [10, 'ten'], + [20, 'twenty'], + [75, 'seventy five'], + [97, 'ninety seven'], + [111, 'one hundred and eleven'], + [175, 'one hundred and seventy five'], + [900, 'nine hundred'], + [1175, 'one thousand one hundred and seventy five'], + [2000, 'two thousand'], + [2100, 'two thousand one hundred'], + [2102, 'two thousand one hundred and two'], + [70000, 'seventy thousand'], + [72000, 'seventy two thousand'], + [900000, 'nine hundred thousand'], + [900001, 'nine hundred thousand and one'], + [900200, 'nine hundred thousand two hundred'], + [900205, 'nine hundred thousand two hundred and five'], + [7900205, 'seven million nine hundred thousand two hundred and five'], + [90000000, 'ninety million'], + [900000000, 'nine hundred million'], + [900000080, 'nine hundred million and eighty'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .values() + .toText() + .out('text') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('all-to-text:', function(t) { + let arr = [ + 'one', + '1', + '1.0', //not sure.. + '1st', + 'first', + ] + arr.forEach(txt => { + const str = nlp(txt) + .values() + .toText() + .toCardinal() + .text() + t.equal(str, 'one', txt + ' -> one') + }) + + arr = ['500', '500.0', '500th', 'five hundred', 'five hundredth'] + arr.forEach(txt => { + const str = nlp(txt) + .values() + .toText() + .toCardinal() + .text() + t.equal(str, 'five hundred', txt + ' -> five hundred') + }) + + arr = ['2012', '2012.0', '2,012', '2012th', 'two thousand and twelve', 'two thousand and twelfth'] + arr.forEach(txt => { + const str = nlp(txt) + .values() + .toText() + .toCardinal() + .text() + t.equal(str, 'two thousand and twelve', txt) + }) + t.end() +}) + +test('big number:', function(t) { + const str = nlp('twenty-three quadrillion') + .values() + .toText() + .out() + t.equal(str, 'twenty three quadrillion', 'quadrillion') + + // str = nlp('nine quintillion two hundred').values().toText().out(); + // t.equal(str, 'nine quintillion two hundred', 'quantillion'); + t.end() +}) diff --git a/plugins/numbers/tests/value.test.js b/plugins/numbers/tests/value.test.js new file mode 100644 index 000000000..f5d6f9a61 --- /dev/null +++ b/plugins/numbers/tests/value.test.js @@ -0,0 +1,256 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('value-lumper-splitter:', function(t) { + let r = nlp('202 199') + t.equal(r.values().length, 2, 'two-numbers') + + r = nlp('two hundred and fifty times six') + t.equal(r.values().length, 2, 'two-numbers2') + + r = nlp('one two') + t.equal(r.values().length, 2, 'two-numbers3') + + r = nlp('fifth ninth') + t.equal(r.values().length, 2, 'two-numbers4') + t.end() +}) + +test('value-basic:', function(t) { + let r = nlp('third month of 2019') + r.values().toNumber() + t.equal(r.out(), '3rd month of 2019', 'toNumber') + + r.values().toText() + t.equal(r.out(), 'third month of two thousand and nineteen', 'toText') + + r = nlp('third month of two thousand and nineteen') + r.values().toCardinal() + t.equal(r.out(), 'three months of two thousand and nineteen', 'toCardinal') + + r = nlp('three months of two thousand nineteen') + r.values().toOrdinal() + t.equal(r.out(), 'third month of two thousand and nineteenth', 'toOrdinal') + + r.values() + .toNumber() + .all() + t.equal(r.out(), '3rd month of 2019th', 'toNumber2') + + t.end() +}) + +test('value-to_ordinal:', function(t) { + let arr = [ + [11, '11th'], + [5, '5th'], + [22, '22nd'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .values() + .toOrdinal() + .out('normal') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('value-number:', function(t) { + let arr = [ + ['five hundred feet', 500], + ['fifty square feet', 50], + ['90 hertz', 90], + // ['5 six-ounce containers', 5], + ['twelve 2-gram containers', 12], + ['thirty-seven forever-21 stores', 37], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .values() + .toNumber() + .terms(0) + .first() + .out('normal') + a[1] = String(a[1]) + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('add/subtract:', function(t) { + let r = nlp('beginning of 2019') + .values() + .add(2) + .all() + t.equal(r.out(), 'beginning of 2021', 'add-2-cardinal') + + r = nlp('beginning of the 2019th') + .values() + .add(2) + .all() + t.equal(r.out(), 'beginning of the 2021st', 'add-2-ordinal') + + r = nlp('beginning of the 2019th') + .values() + .add(-2) + .all() + t.equal(r.out(), 'beginning of the 2017th', 'add-minus-2-ordinal') + + r = nlp('beginning of 2019') + .values() + .subtract(2) + .all() + t.equal(r.out(), 'beginning of 2017', 'subtract-2-cardinal') + + r = nlp('beginning of the 2019th') + .values() + .subtract(2) + .all() + t.equal(r.out(), 'beginning of the 2017th', 'subtract-2-ordinal') + + r = nlp('seventeen years old') + .values() + .add(2) + .all() + t.equal(r.out(), 'nineteen years old', 'text-add-2-ordinal') + r = nlp('seventeenth birthday') + .values() + .add(2) + .all() + t.equal(r.out(), 'nineteenth birthday', 'text-add-2-ordinal') + + r = nlp('seventeen years old') + .values() + .subtract(2) + .all() + t.equal(r.out(), 'fifteen years old', 'text-subtract-2-cardinal') + + r = nlp('seventeenth birthday') + .values() + .subtract(2) + .all() + t.equal(r.out(), 'fifteenth birthday', 'text-subtract-2-cardinal') + + r = nlp('seven apples and 1,231 peaches') + .values() + .add(50) + .all() + t.equal(r.out(), 'fifty seven apples and 1,281 peaches', 'two-add-50s') + t.end() +}) + +test('increment:', function(t) { + let r = nlp('seven apples and 231 peaches') + r.values().increment() + t.equal(r.out(), 'eight apples and 232 peaches', 'increment-cardinal') + r.values().decrement() + t.equal(r.out(), 'seven apples and 231 peaches', 'decrement-cardinal') + + r = nlp('seventh place and 12th place') + r.values() + .increment() + .increment() + t.equal(r.out(), 'ninth place and 14th place', 'increment-ordinal') + r.values() + .decrement() + .decrement() + t.equal(r.out(), 'seventh place and 12th place', 'decrement-ordinal') + t.end() +}) + +test('number splits', function(t) { + const arr = ['12, 34, 56', '12 34 56', '12, 34, 56', '1 2 4'] + arr.forEach(str => { + const tokens = nlp(str) + .values() + .out('array') + t.equal(tokens.length, 3, str) + }) + t.end() +}) + +// test('nounit:', function(t) { +// let r = nlp('seven apples and 231 peaches') +// let arr = r.values().out('array') +// t.deepEqual(arr, ['seven apples', '231 peaches']) + +// arr = r +// .values() +// .noUnits() +// .out('array') +// t.deepEqual(arr, ['seven', '231']) +// t.end() +// }) + +// test('value-unit:', function(t) { +// let arr = [ +// ['five hundred feet', 'feet'], +// ['fifty hertz', 'hertz'], +// ['100 dollars', 'dollars'], +// // ['$100', 'dollar'], +// // ['¥2.5', 'yen'], +// // ['€3,000,100', 'euro'], +// // ['EUR 9.99', 'eur'], +// // ['5 g', 'g'], +// // ['2 in', 'in'], +// // ['5 g sugar', 'g'], +// ['3 grams', 'grams'], +// ['2 inches', 'inches'], +// ['10 grams of sugar', 'grams'], +// ['fifty inches of snow', 'inches'], +// ['7 years', 'years'], +// ['7.5 days', 'days'], + +// ['7th year', 'year'], +// ['7th years', ''], +// ['1 day', 'day'], +// ['one book', 'book'], +// ['first book', 'book'], +// ['7 day', ''], +// ] +// arr.forEach(function(a) { +// const r = nlp(a[0]) +// .values() +// .units() +// t.equal(r.out('normal'), a[1], a[0]) +// }) +// t.end() +// }) +// test('value-measurement:', function(t) { +// [ +// ['five hundred feet', 'Distance'], +// ['100 kilometers', 'Distance'], +// ['fifty hertz', 'Frequency'], +// ['59 thousand $', 'Money'], +// ['100 mb', 'Data'], +// ['50 руб', 'Money'], +// ['EUR 9.99', 'Money'], +// ['100 dollars', 'Money'], +// ['256 bitcoins', 'Money'], +// ].forEach(function (a) { +// const str = nlp.value(a[0]).measurement; +// str_test(str, a[0], a[1], t); +// }); +// t.end(); +// }); +// +// test('value-of_what:', function(t) { +// [ +// ['nine kg', 'kg'], +// ['5 kg of copper', 'copper'], +// ['many of these stories', 'many of these stories'], +// ['room full of beautiful creatures', 'full of beautiful creatures'], +// ['boxes of bags of food', 'boxes of bags of food'], +// ['5 boxes of water', 'boxes of water'], +// ['6 of kids', 'kids'], +// ['10 kids', 'kids'], +// ['just nothing', 'just nothing'], +// ['EUR 77', 'eur'], +// ['kg', 'kg'] +// ].forEach(function (a) { +// const str = nlp.value(a[0]).of_what; +// str_test(str, a[0], a[1], t); +// }); +// t.end(); +// }); diff --git a/plugins/output/README.md b/plugins/output/README.md new file mode 100644 index 000000000..aa7caa4bb --- /dev/null +++ b/plugins/output/README.md @@ -0,0 +1,113 @@ +
+ + +
a plugin for compromise
+ + + + + + + + + + +
+
+ +
+ npm install compromise-output +
+ +### [Demo](https://observablehq.com/@spencermountain/compromise-output) + +```js +const nlp = require('compromise') +nlp.extend(require('compromise-output')) + +let doc = nlp('The Children are right to laugh at you, Ralph') + +// generate an md5 hash for the document +doc.hash() +// 'KD83KH3L2B39_UI3N1X' + +// create a html rendering of the document +doc.html({ '#Person+': 'red', '#Money+': 'blue' }) +/* +
+  The Children are right to laugh at you, Ralph
+
+*/ +``` + +### .hash() + +this hash function incorporates the term pos-tags, and whitespace, so that tagging or normalizing the document will change the hash. + +Md5 is not considered a very-secure hash, so heads-up if you're doing some top-secret work. + +It can though, be used successfully to compare two documents, without looping through tags: + +```js +let docA = nlp('hello there') +let docB = nlp('hello there') +console.log(docA.hash() === docB.hash()) +// true + +docB.match('hello').tag('Greeting') +console.log(docA.hash() === docB.hash()) +// false +``` + +if you're looking for insensitivity to punctuation, or case, you can normalize or transform your document before making the hash. + +```js +let doc = nlp(`He isn't... working `) +doc.normalize({ + case: true, + punctuation: true, + contractions: true, +}) + +nlp('he is not working').hash() === doc.hash() +// true +``` + +### .html({segments}, {options}) + +this turns the document into easily-to-display html output. + +Special html characters within the document get escaped, in a simple way. Be extra careful when rendering untrusted input, against XSS and other forms of sneaky-html. This library is not considered a battle-tested guard against these security vulnerabilities. + +```js +let doc = nlp('i <3 you') +doc.html() +//
i <3 you
+``` + +you can pass-in a mapping of tags to html classes, so that document metadata can be styled by css. + +```js +let doc = nlp('made by Spencer Kelly') +doc.html({ + '#Person+': 'red', +}) +//
made by Spencer Kelly
+``` + +The library uses `.segment()` method, which is [documented here](https://observablehq.com/@spencermountain/compromise-split). + +by default, whitespace and punctuation are _outside_ the html tag. This is sometimes awkward, and not-ideal. + +the method returns html-strings by default, but the library uses [Jason Miller's htm library](https://github.com/developit/htm) so you can return React Components, or anything: + +```js +doc.html( + {}, + { + bind: React.createElement, + } +) +``` + +MIT diff --git a/plugins/output/builds/compromise-output.js b/plugins/output/builds/compromise-output.js new file mode 100644 index 000000000..2036d685d --- /dev/null +++ b/plugins/output/builds/compromise-output.js @@ -0,0 +1,401 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseOutput = factory()); +}(this, (function () { 'use strict'; + + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _taggedTemplateLiteral(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + + return Object.freeze(Object.defineProperties(strings, { + raw: { + value: Object.freeze(raw) + } + })); + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function unwrapExports (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + function getCjsExportFromNamespace (n) { + return n && n['default'] || n; + } + + var lib = createCommonjsModule(function (module, exports) { + !function (r, n) { + module.exports = n(); + }("undefined" != typeof self ? self : commonjsGlobal, function () { + return function (r) { + var n = {}; + + function e(t) { + if (n[t]) return n[t].exports; + var o = n[t] = { + i: t, + l: !1, + exports: {} + }; + return r[t].call(o.exports, o, o.exports, e), o.l = !0, o.exports; + } + + return e.m = r, e.c = n, e.d = function (r, n, t) { + e.o(r, n) || Object.defineProperty(r, n, { + enumerable: !0, + get: t + }); + }, e.r = function (r) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(r, Symbol.toStringTag, { + value: "Module" + }), Object.defineProperty(r, "__esModule", { + value: !0 + }); + }, e.t = function (r, n) { + if (1 & n && (r = e(r)), 8 & n) return r; + if (4 & n && "object" == _typeof(r) && r && r.__esModule) return r; + var t = Object.create(null); + if (e.r(t), Object.defineProperty(t, "default", { + enumerable: !0, + value: r + }), 2 & n && "string" != typeof r) for (var o in r) { + e.d(t, o, function (n) { + return r[n]; + }.bind(null, o)); + } + return t; + }, e.n = function (r) { + var n = r && r.__esModule ? function () { + return r["default"]; + } : function () { + return r; + }; + return e.d(n, "a", n), n; + }, e.o = function (r, n) { + return Object.prototype.hasOwnProperty.call(r, n); + }, e.p = "", e(e.s = 0); + }([function (r, n, e) { + + e.r(n); + var t = "0123456789abcdef".split(""); + + var o = function o(r) { + for (var n = "", e = 0; e < 4; e++) { + n += t[r >> 8 * e + 4 & 15] + t[r >> 8 * e & 15]; + } + + return n; + }; + + var u = function u(r) { + for (var n = r.length, e = 0; e < n; e++) { + r[e] = o(r[e]); + } + + return r.join(""); + }; + + var f = function f(r, n) { + return r + n & 4294967295; + }; + + var i = function i(r, n, e, t, o, u, _i) { + return function (r, n, e) { + return f(r << n | r >>> 32 - n, e); + }(n = function (r, n, e, t) { + return n = f(f(n, r), f(e, t)); + }(r, n, t, u), o, e); + }; + + var a = function a(r, n, e, t, o, u, f, _a) { + return i(e & t | ~e & o, n, e, u, f, _a); + }; + + var c = function c(r, n, e, t, o, u, f, a) { + return i(e & o | t & ~o, n, e, u, f, a); + }; + + var l = function l(r, n, e, t, o, u, f, a) { + return i(e ^ t ^ o, n, e, u, f, a); + }; + + var d = function d(r, n, e, t, o, u, f, a) { + return i(t ^ (e | ~o), n, e, u, f, a); + }; + + var v = function v(r, n, e) { + void 0 === e && (e = f); + var t = r[0], + o = r[1], + u = r[2], + i = r[3], + v = a.bind(null, e); + t = v(t, o, u, i, n[0], 7, -680876936), i = v(i, t, o, u, n[1], 12, -389564586), u = v(u, i, t, o, n[2], 17, 606105819), o = v(o, u, i, t, n[3], 22, -1044525330), t = v(t, o, u, i, n[4], 7, -176418897), i = v(i, t, o, u, n[5], 12, 1200080426), u = v(u, i, t, o, n[6], 17, -1473231341), o = v(o, u, i, t, n[7], 22, -45705983), t = v(t, o, u, i, n[8], 7, 1770035416), i = v(i, t, o, u, n[9], 12, -1958414417), u = v(u, i, t, o, n[10], 17, -42063), o = v(o, u, i, t, n[11], 22, -1990404162), t = v(t, o, u, i, n[12], 7, 1804603682), i = v(i, t, o, u, n[13], 12, -40341101), u = v(u, i, t, o, n[14], 17, -1502002290), o = v(o, u, i, t, n[15], 22, 1236535329); + var s = c.bind(null, e); + t = s(t, o, u, i, n[1], 5, -165796510), i = s(i, t, o, u, n[6], 9, -1069501632), u = s(u, i, t, o, n[11], 14, 643717713), o = s(o, u, i, t, n[0], 20, -373897302), t = s(t, o, u, i, n[5], 5, -701558691), i = s(i, t, o, u, n[10], 9, 38016083), u = s(u, i, t, o, n[15], 14, -660478335), o = s(o, u, i, t, n[4], 20, -405537848), t = s(t, o, u, i, n[9], 5, 568446438), i = s(i, t, o, u, n[14], 9, -1019803690), u = s(u, i, t, o, n[3], 14, -187363961), o = s(o, u, i, t, n[8], 20, 1163531501), t = s(t, o, u, i, n[13], 5, -1444681467), i = s(i, t, o, u, n[2], 9, -51403784), u = s(u, i, t, o, n[7], 14, 1735328473), o = s(o, u, i, t, n[12], 20, -1926607734); + var b = l.bind(null, e); + t = b(t, o, u, i, n[5], 4, -378558), i = b(i, t, o, u, n[8], 11, -2022574463), u = b(u, i, t, o, n[11], 16, 1839030562), o = b(o, u, i, t, n[14], 23, -35309556), t = b(t, o, u, i, n[1], 4, -1530992060), i = b(i, t, o, u, n[4], 11, 1272893353), u = b(u, i, t, o, n[7], 16, -155497632), o = b(o, u, i, t, n[10], 23, -1094730640), t = b(t, o, u, i, n[13], 4, 681279174), i = b(i, t, o, u, n[0], 11, -358537222), u = b(u, i, t, o, n[3], 16, -722521979), o = b(o, u, i, t, n[6], 23, 76029189), t = b(t, o, u, i, n[9], 4, -640364487), i = b(i, t, o, u, n[12], 11, -421815835), u = b(u, i, t, o, n[15], 16, 530742520), o = b(o, u, i, t, n[2], 23, -995338651); + var p = d.bind(null, e); + t = p(t, o, u, i, n[0], 6, -198630844), i = p(i, t, o, u, n[7], 10, 1126891415), u = p(u, i, t, o, n[14], 15, -1416354905), o = p(o, u, i, t, n[5], 21, -57434055), t = p(t, o, u, i, n[12], 6, 1700485571), i = p(i, t, o, u, n[3], 10, -1894986606), u = p(u, i, t, o, n[10], 15, -1051523), o = p(o, u, i, t, n[1], 21, -2054922799), t = p(t, o, u, i, n[8], 6, 1873313359), i = p(i, t, o, u, n[15], 10, -30611744), u = p(u, i, t, o, n[6], 15, -1560198380), o = p(o, u, i, t, n[13], 21, 1309151649), t = p(t, o, u, i, n[4], 6, -145523070), i = p(i, t, o, u, n[11], 10, -1120210379), u = p(u, i, t, o, n[2], 15, 718787259), o = p(o, u, i, t, n[9], 21, -343485551), r[0] = e(t, r[0]), r[1] = e(o, r[1]), r[2] = e(u, r[2]), r[3] = e(i, r[3]); + }; + + var s = function s(r) { + for (var n = [], e = 0; e < 64; e += 4) { + n[e >> 2] = r.charCodeAt(e) + (r.charCodeAt(e + 1) << 8) + (r.charCodeAt(e + 2) << 16) + (r.charCodeAt(e + 3) << 24); + } + + return n; + }; + + var b = function b(r, n) { + var e, + t = r.length, + o = [1732584193, -271733879, -1732584194, 271733878]; + + for (e = 64; e <= t; e += 64) { + v(o, s(r.substring(e - 64, e)), n); + } + + var u = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + f = (r = r.substring(e - 64)).length; + + for (e = 0; e < f; e++) { + u[e >> 2] |= r.charCodeAt(e) << (e % 4 << 3); + } + + if (u[e >> 2] |= 128 << (e % 4 << 3), e > 55) for (v(o, u, n), e = 16; e--;) { + u[e] = 0; + } + return u[14] = 8 * t, v(o, u, n), o; + }; + + function p(r) { + var n; + return "5d41402abc4b2a76b9719d911017c592" !== u(b("hello")) && (n = function n(r, _n) { + var e = (65535 & r) + (65535 & _n); + return (r >> 16) + (_n >> 16) + (e >> 16) << 16 | 65535 & e; + }), u(b(r, n)); + } + + e.d(n, "md5", function () { + return p; + }); + }]); + }); + }); + unwrapExports(lib); + + var md5 = lib.md5; + + var makeHash = function makeHash(doc) { + var str = doc.text(); + doc.list.forEach(function (p) { + p.terms().forEach(function (t) { + str += t.pre + (t.implicit || t.text) + t.post; + str += Object.keys(t.tags).join(''); + }); + }); + return md5(str); + }; + + var hash = makeHash; + + var n = function n(t, r, u, e) { + for (var p = 1; p < r.length; p++) { + var s = r[p], + h = "number" == typeof s ? u[s] : s, + a = r[++p]; + 1 === a ? e[0] = h : 3 === a ? e[1] = Object.assign(e[1] || {}, h) : 5 === a ? (e[1] = e[1] || {})[r[++p]] = h : 6 === a ? e[1][r[++p]] += h + "" : e.push(a ? t.apply(null, n(t, h, u, ["", null])) : h); + } + + return e; + }, + t = function t(n) { + for (var t, r, u = 1, e = "", p = "", s = [0], h = function h(n) { + 1 === u && (n || (e = e.replace(/^\s*\n\s*|\s*\n\s*$/g, ""))) ? s.push(n || e, 0) : 3 === u && (n || e) ? (s.push(n || e, 1), u = 2) : 2 === u && "..." === e && n ? s.push(n, 3) : 2 === u && e && !n ? s.push(!0, 5, e) : u >= 5 && ((e || !n && 5 === u) && (s.push(e, u, r), u = 6), n && (s.push(n, u, r), u = 6)), e = ""; + }, a = 0; a < n.length; a++) { + a && (1 === u && h(), h(a)); + + for (var f = 0; f < n[a].length; f++) { + t = n[a][f], 1 === u ? "<" === t ? (h(), s = [s], u = 3) : e += t : 4 === u ? "--" === e && ">" === t ? (u = 1, e = "") : e = t + e[0] : p ? t === p ? p = "" : e += t : '"' === t || "'" === t ? p = t : ">" === t ? (h(), u = 1) : u && ("=" === t ? (u = 5, r = e, e = "") : "/" === t && (u < 5 || ">" === n[a][f + 1]) ? (h(), 3 === u && (s = s[0]), u = s, (s = s[0]).push(u, 2), u = 0) : " " === t || "\t" === t || "\n" === t || "\r" === t ? (h(), u = 2) : e += t), 3 === u && "!--" === e && (u = 4, s = s[0]); + } + } + + return h(), s; + }, + r = "function" == typeof Map, + u = r ? new Map() : {}, + e = r ? function (n) { + var r = u.get(n); + return r || u.set(n, r = t(n)), r; + } : function (n) { + for (var r = "", e = 0; e < n.length; e++) { + r += n[e].length + "-" + n[e]; + } + + return u[r] || (u[r] = t(n)); + }; + + function htm_module (t) { + var r = n(this, e(t), arguments, []); + return r.length > 1 ? r : r[0]; + } + + var htm_module$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': htm_module + }); + + var vhtml = createCommonjsModule(function (module, exports) { + (function (global, factory) { + module.exports = factory() ; + })(commonjsGlobal, function () { + + var emptyTags = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']; + + var esc = function esc(str) { + return String(str).replace(/[&<>"']/g, function (s) { + return '&' + map[s] + ';'; + }); + }; + + var map = { + '&': 'amp', + '<': 'lt', + '>': 'gt', + '"': 'quot', + "'": 'apos' + }; + var sanitized = {}; + + function h(name, attrs) { + var stack = []; + + for (var i = arguments.length; i-- > 2;) { + stack.push(arguments[i]); + } + + if (typeof name === 'function') { + (attrs || (attrs = {})).children = stack.reverse(); + return name(attrs); + } + + var s = '<' + name; + if (attrs) for (var _i in attrs) { + if (attrs[_i] !== false && attrs[_i] != null) { + s += ' ' + esc(_i) + '="' + esc(attrs[_i]) + '"'; + } + } + + if (emptyTags.indexOf(name) === -1) { + s += '>'; + + while (stack.length) { + var child = stack.pop(); + + if (child) { + if (child.pop) { + for (var _i2 = child.length; _i2--;) { + stack.push(child[_i2]); + } + } else { + s += sanitized[child] === true ? child : esc(child); + } + } + } + + s += ''; + } else { + s += '>'; + } + + sanitized[s] = true; + return s; + } + + return h; + }); + }); + + var htm = getCjsExportFromNamespace(htm_module$1); + + function _templateObject2() { + var data = _taggedTemplateLiteral(["
", "
"]); + + _templateObject2 = function _templateObject2() { + return data; + }; + + return data; + } + + function _templateObject() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject = function _templateObject() { + return data; + }; + + return data; + } + + var toHtml = function toHtml(doc, segments, options) { + var h = htm.bind(vhtml); + + if (options.bind) { + h = htm.bind(options.bind); + } + + var html = []; + var arr = doc.segment(segments); + arr.forEach(function (o) { + var str = h(_templateObject(), o.segment, o.text); + html.push(str); + }); + return h(_templateObject2(), html); + }; + + var html = toHtml; + + var addMethods = function addMethods(Doc) { + /** generate an md5 hash from the document */ + Doc.prototype.hash = function () { + return hash(this); + }; + /** generate sanitized html from the document */ + + + Doc.prototype.html = function () { + var segments = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return html(this, segments, options); + }; + }; + + var src = addMethods; + + return src; + +}))); +//# sourceMappingURL=compromise-output.js.map diff --git a/plugins/output/builds/compromise-output.js.map b/plugins/output/builds/compromise-output.js.map new file mode 100644 index 000000000..30622b6d3 --- /dev/null +++ b/plugins/output/builds/compromise-output.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-output.js","sources":["../node_modules/pure-md5/lib/index.js","../src/hash.js","../node_modules/htm/dist/htm.module.js","../src/html.js","../src/index.js"],"sourcesContent":["!function(r,n){if(\"object\"==typeof exports&&\"object\"==typeof module)module.exports=n();else if(\"function\"==typeof define&&define.amd)define([],n);else{var e=n();for(var t in e)(\"object\"==typeof exports?exports:r)[t]=e[t]}}(\"undefined\"!=typeof self?self:this,function(){return function(r){var n={};function e(t){if(n[t])return n[t].exports;var o=n[t]={i:t,l:!1,exports:{}};return r[t].call(o.exports,o,o.exports,e),o.l=!0,o.exports}return e.m=r,e.c=n,e.d=function(r,n,t){e.o(r,n)||Object.defineProperty(r,n,{enumerable:!0,get:t})},e.r=function(r){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(r,\"__esModule\",{value:!0})},e.t=function(r,n){if(1&n&&(r=e(r)),8&n)return r;if(4&n&&\"object\"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(e.r(t),Object.defineProperty(t,\"default\",{enumerable:!0,value:r}),2&n&&\"string\"!=typeof r)for(var o in r)e.d(t,o,function(n){return r[n]}.bind(null,o));return t},e.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return e.d(n,\"a\",n),n},e.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},e.p=\"\",e(e.s=0)}([function(r,n,e){\"use strict\";e.r(n);var t=\"0123456789abcdef\".split(\"\");var o=function(r){for(var n=\"\",e=0;e<4;e++)n+=t[r>>8*e+4&15]+t[r>>8*e&15];return n};var u=function(r){for(var n=r.length,e=0;e>>32-n,e)}(n=function(r,n,e,t){return n=f(f(n,r),f(e,t))}(r,n,t,u),o,e)};var a=function(r,n,e,t,o,u,f,a){return i(e&t|~e&o,n,e,u,f,a,r)};var c=function(r,n,e,t,o,u,f,a){return i(e&o|t&~o,n,e,u,f,a,r)};var l=function(r,n,e,t,o,u,f,a){return i(e^t^o,n,e,u,f,a,r)};var d=function(r,n,e,t,o,u,f,a){return i(t^(e|~o),n,e,u,f,a,r)};var v=function(r,n,e){void 0===e&&(e=f);var t=r[0],o=r[1],u=r[2],i=r[3],v=a.bind(null,e);t=v(t,o,u,i,n[0],7,-680876936),i=v(i,t,o,u,n[1],12,-389564586),u=v(u,i,t,o,n[2],17,606105819),o=v(o,u,i,t,n[3],22,-1044525330),t=v(t,o,u,i,n[4],7,-176418897),i=v(i,t,o,u,n[5],12,1200080426),u=v(u,i,t,o,n[6],17,-1473231341),o=v(o,u,i,t,n[7],22,-45705983),t=v(t,o,u,i,n[8],7,1770035416),i=v(i,t,o,u,n[9],12,-1958414417),u=v(u,i,t,o,n[10],17,-42063),o=v(o,u,i,t,n[11],22,-1990404162),t=v(t,o,u,i,n[12],7,1804603682),i=v(i,t,o,u,n[13],12,-40341101),u=v(u,i,t,o,n[14],17,-1502002290),o=v(o,u,i,t,n[15],22,1236535329);var s=c.bind(null,e);t=s(t,o,u,i,n[1],5,-165796510),i=s(i,t,o,u,n[6],9,-1069501632),u=s(u,i,t,o,n[11],14,643717713),o=s(o,u,i,t,n[0],20,-373897302),t=s(t,o,u,i,n[5],5,-701558691),i=s(i,t,o,u,n[10],9,38016083),u=s(u,i,t,o,n[15],14,-660478335),o=s(o,u,i,t,n[4],20,-405537848),t=s(t,o,u,i,n[9],5,568446438),i=s(i,t,o,u,n[14],9,-1019803690),u=s(u,i,t,o,n[3],14,-187363961),o=s(o,u,i,t,n[8],20,1163531501),t=s(t,o,u,i,n[13],5,-1444681467),i=s(i,t,o,u,n[2],9,-51403784),u=s(u,i,t,o,n[7],14,1735328473),o=s(o,u,i,t,n[12],20,-1926607734);var b=l.bind(null,e);t=b(t,o,u,i,n[5],4,-378558),i=b(i,t,o,u,n[8],11,-2022574463),u=b(u,i,t,o,n[11],16,1839030562),o=b(o,u,i,t,n[14],23,-35309556),t=b(t,o,u,i,n[1],4,-1530992060),i=b(i,t,o,u,n[4],11,1272893353),u=b(u,i,t,o,n[7],16,-155497632),o=b(o,u,i,t,n[10],23,-1094730640),t=b(t,o,u,i,n[13],4,681279174),i=b(i,t,o,u,n[0],11,-358537222),u=b(u,i,t,o,n[3],16,-722521979),o=b(o,u,i,t,n[6],23,76029189),t=b(t,o,u,i,n[9],4,-640364487),i=b(i,t,o,u,n[12],11,-421815835),u=b(u,i,t,o,n[15],16,530742520),o=b(o,u,i,t,n[2],23,-995338651);var p=d.bind(null,e);t=p(t,o,u,i,n[0],6,-198630844),i=p(i,t,o,u,n[7],10,1126891415),u=p(u,i,t,o,n[14],15,-1416354905),o=p(o,u,i,t,n[5],21,-57434055),t=p(t,o,u,i,n[12],6,1700485571),i=p(i,t,o,u,n[3],10,-1894986606),u=p(u,i,t,o,n[10],15,-1051523),o=p(o,u,i,t,n[1],21,-2054922799),t=p(t,o,u,i,n[8],6,1873313359),i=p(i,t,o,u,n[15],10,-30611744),u=p(u,i,t,o,n[6],15,-1560198380),o=p(o,u,i,t,n[13],21,1309151649),t=p(t,o,u,i,n[4],6,-145523070),i=p(i,t,o,u,n[11],10,-1120210379),u=p(u,i,t,o,n[2],15,718787259),o=p(o,u,i,t,n[9],21,-343485551),r[0]=e(t,r[0]),r[1]=e(o,r[1]),r[2]=e(u,r[2]),r[3]=e(i,r[3])};var s=function(r){for(var n=[],e=0;e<64;e+=4)n[e>>2]=r.charCodeAt(e)+(r.charCodeAt(e+1)<<8)+(r.charCodeAt(e+2)<<16)+(r.charCodeAt(e+3)<<24);return n};var b=function(r,n){var e,t=r.length,o=[1732584193,-271733879,-1732584194,271733878];for(e=64;e<=t;e+=64)v(o,s(r.substring(e-64,e)),n);var u=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],f=(r=r.substring(e-64)).length;for(e=0;e>2]|=r.charCodeAt(e)<<(e%4<<3);if(u[e>>2]|=128<<(e%4<<3),e>55)for(v(o,u,n),e=16;e--;)u[e]=0;return u[14]=8*t,v(o,u,n),o};function p(r){var n;return\"5d41402abc4b2a76b9719d911017c592\"!==u(b(\"hello\"))&&(n=function(r,n){var e=(65535&r)+(65535&n);return(r>>16)+(n>>16)+(e>>16)<<16|65535&e}),u(b(r,n))}e.d(n,\"md5\",function(){return p})}])});\n//# sourceMappingURL=index.js.map","const md5 = require('pure-md5').md5\n\nconst makeHash = function(doc) {\n let str = doc.text()\n doc.list.forEach(p => {\n p.terms().forEach(t => {\n str += t.pre + (t.implicit || t.text) + t.post\n str += Object.keys(t.tags).join('')\n })\n })\n return md5(str)\n}\nmodule.exports = makeHash\n","var n=function(t,r,u,e){for(var p=1;p=5&&((e||!n&&5===u)&&(s.push(e,u,r),u=6),n&&(s.push(n,u,r),u=6)),e=\"\"},a=0;a\"===t?(u=1,e=\"\"):e=t+e[0]:p?t===p?p=\"\":e+=t:'\"'===t||\"'\"===t?p=t:\">\"===t?(h(),u=1):u&&(\"=\"===t?(u=5,r=e,e=\"\"):\"/\"===t&&(u<5||\">\"===n[a][f+1])?(h(),3===u&&(s=s[0]),u=s,(s=s[0]).push(u,2),u=0):\" \"===t||\"\\t\"===t||\"\\n\"===t||\"\\r\"===t?(h(),u=2):e+=t),3===u&&\"!--\"===e&&(u=4,s=s[0])}return h(),s},r=\"function\"==typeof Map,u=r?new Map:{},e=r?function(n){var r=u.get(n);return r||u.set(n,r=t(n)),r}:function(n){for(var r=\"\",e=0;e1?r:r[0]}\n","const htm = require('htm')\nconst vhtml = require('vhtml')\n\nconst toHtml = function(doc, segments, options) {\n let h = htm.bind(vhtml)\n if (options.bind) {\n h = htm.bind(options.bind)\n }\n let html = []\n let arr = doc.segment(segments)\n arr.forEach(o => {\n let str = h`${o.text}`\n html.push(str)\n })\n return h`
${html}
`\n}\nmodule.exports = toHtml\n","const makeHash = require('./hash')\nconst toHtml = require('./html')\n\nconst addMethods = function(Doc) {\n /** generate an md5 hash from the document */\n Doc.prototype.hash = function() {\n return makeHash(this)\n }\n\n /** generate sanitized html from the document */\n Doc.prototype.html = function(segments = {}, options = {}) {\n return toHtml(this, segments, options)\n }\n}\nmodule.exports = addMethods\n"],"names":["r","n","module","self","this","e","t","exports","o","i","l","call","m","c","d","Object","defineProperty","enumerable","get","Symbol","toStringTag","value","__esModule","create","bind","prototype","hasOwnProperty","p","s","split","u","length","join","f","a","v","b","charCodeAt","substring","md5","require$$0","makeHash","doc","str","text","list","forEach","terms","pre","implicit","post","keys","tags","h","assign","push","apply","replace","Map","set","arguments","toHtml","segments","options","htm","vhtml","html","arr","segment","addMethods","Doc","hash"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/output/builds/compromise-output.min.js b/plugins/output/builds/compromise-output.min.js new file mode 100644 index 000000000..92113892f --- /dev/null +++ b/plugins/output/builds/compromise-output.min.js @@ -0,0 +1 @@ +!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(n=n||self).compromiseOutput=t()}(this,(function(){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n&&"function"==typeof Symbol&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n})(t)}function t(n,t){return t||(t=n.slice(0)),Object.freeze(Object.defineProperties(n,{raw:{value:Object.freeze(t)}}))}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function e(n,t){return n(t={exports:{}},t.exports),t.exports}var r,o=e((function(t,e){"undefined"!=typeof self&&self,t.exports=function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:e})},r.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==n(t)&&t&&t.__esModule)return t;var o=Object.create(null);if(r.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var u in t)r.d(o,u,function(n){return t[n]}.bind(null,u));return o},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="",r(r.s=0)}([function(n,t,e){e.r(t);var r="0123456789abcdef".split(""),o=function(n){for(var t="",e=0;e<4;e++)t+=r[n>>8*e+4&15]+r[n>>8*e&15];return t},u=function(n){for(var t=n.length,e=0;e>>32-t,e)}(t=function(n,t,e,r){return f(f(t,n),f(e,r))}(n,t,r,u),o,e)},c=function(n,t,e,r,o,u,f,c){return i(e&r|~e&o,t,e,u,f,c)},a=function(n,t,e,r,o,u,f,c){return i(e&o|r&~o,t,e,u,f,c)},l=function(n,t,e,r,o,u,f,c){return i(e^r^o,t,e,u,f,c)},p=function(n,t,e,r,o,u,f,c){return i(r^(e|~o),t,e,u,f,c)},s=function(n,t,e){void 0===e&&(e=f);var r=n[0],o=n[1],u=n[2],i=n[3],s=c.bind(null,e);r=s(r,o,u,i,t[0],7,-680876936),i=s(i,r,o,u,t[1],12,-389564586),u=s(u,i,r,o,t[2],17,606105819),o=s(o,u,i,r,t[3],22,-1044525330),r=s(r,o,u,i,t[4],7,-176418897),i=s(i,r,o,u,t[5],12,1200080426),u=s(u,i,r,o,t[6],17,-1473231341),o=s(o,u,i,r,t[7],22,-45705983),r=s(r,o,u,i,t[8],7,1770035416),i=s(i,r,o,u,t[9],12,-1958414417),u=s(u,i,r,o,t[10],17,-42063),o=s(o,u,i,r,t[11],22,-1990404162),r=s(r,o,u,i,t[12],7,1804603682),i=s(i,r,o,u,t[13],12,-40341101),u=s(u,i,r,o,t[14],17,-1502002290),o=s(o,u,i,r,t[15],22,1236535329);var d=a.bind(null,e);r=d(r,o,u,i,t[1],5,-165796510),i=d(i,r,o,u,t[6],9,-1069501632),u=d(u,i,r,o,t[11],14,643717713),o=d(o,u,i,r,t[0],20,-373897302),r=d(r,o,u,i,t[5],5,-701558691),i=d(i,r,o,u,t[10],9,38016083),u=d(u,i,r,o,t[15],14,-660478335),o=d(o,u,i,r,t[4],20,-405537848),r=d(r,o,u,i,t[9],5,568446438),i=d(i,r,o,u,t[14],9,-1019803690),u=d(u,i,r,o,t[3],14,-187363961),o=d(o,u,i,r,t[8],20,1163531501),r=d(r,o,u,i,t[13],5,-1444681467),i=d(i,r,o,u,t[2],9,-51403784),u=d(u,i,r,o,t[7],14,1735328473),o=d(o,u,i,r,t[12],20,-1926607734);var b=l.bind(null,e);r=b(r,o,u,i,t[5],4,-378558),i=b(i,r,o,u,t[8],11,-2022574463),u=b(u,i,r,o,t[11],16,1839030562),o=b(o,u,i,r,t[14],23,-35309556),r=b(r,o,u,i,t[1],4,-1530992060),i=b(i,r,o,u,t[4],11,1272893353),u=b(u,i,r,o,t[7],16,-155497632),o=b(o,u,i,r,t[10],23,-1094730640),r=b(r,o,u,i,t[13],4,681279174),i=b(i,r,o,u,t[0],11,-358537222),u=b(u,i,r,o,t[3],16,-722521979),o=b(o,u,i,r,t[6],23,76029189),r=b(r,o,u,i,t[9],4,-640364487),i=b(i,r,o,u,t[12],11,-421815835),u=b(u,i,r,o,t[15],16,530742520),o=b(o,u,i,r,t[2],23,-995338651);var v=p.bind(null,e);r=v(r,o,u,i,t[0],6,-198630844),i=v(i,r,o,u,t[7],10,1126891415),u=v(u,i,r,o,t[14],15,-1416354905),o=v(o,u,i,r,t[5],21,-57434055),r=v(r,o,u,i,t[12],6,1700485571),i=v(i,r,o,u,t[3],10,-1894986606),u=v(u,i,r,o,t[10],15,-1051523),o=v(o,u,i,r,t[1],21,-2054922799),r=v(r,o,u,i,t[8],6,1873313359),i=v(i,r,o,u,t[15],10,-30611744),u=v(u,i,r,o,t[6],15,-1560198380),o=v(o,u,i,r,t[13],21,1309151649),r=v(r,o,u,i,t[4],6,-145523070),i=v(i,r,o,u,t[11],10,-1120210379),u=v(u,i,r,o,t[2],15,718787259),o=v(o,u,i,r,t[9],21,-343485551),n[0]=e(r,n[0]),n[1]=e(o,n[1]),n[2]=e(u,n[2]),n[3]=e(i,n[3])},d=function(n){for(var t=[],e=0;e<64;e+=4)t[e>>2]=n.charCodeAt(e)+(n.charCodeAt(e+1)<<8)+(n.charCodeAt(e+2)<<16)+(n.charCodeAt(e+3)<<24);return t},b=function(n,t){var e,r=n.length,o=[1732584193,-271733879,-1732584194,271733878];for(e=64;e<=r;e+=64)s(o,d(n.substring(e-64,e)),t);var u=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],f=(n=n.substring(e-64)).length;for(e=0;e>2]|=n.charCodeAt(e)<<(e%4<<3);if(u[e>>2]|=128<<(e%4<<3),e>55)for(s(o,u,t),e=16;e--;)u[e]=0;return u[14]=8*r,s(o,u,t),o};function v(n){var t;return"5d41402abc4b2a76b9719d911017c592"!==u(b("hello"))&&(t=function(n,t){var e=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(e>>16)<<16|65535&e}),u(b(n,t))}e.d(t,"md5",(function(){return v}))}])}));(r=o)&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")&&r.default;var u=o.md5,f=function(n){var t=n.text();return n.list.forEach((function(n){n.terms().forEach((function(n){t+=n.pre+(n.implicit||n.text)+n.post,t+=Object.keys(n.tags).join("")}))})),u(t)},i=function n(t,e,r,o){for(var u=1;u=5&&((o||!n&&5===r)&&(f.push(o,r,e),r=6),n&&(f.push(n,r,e),r=6)),o=""},c=0;c"===t?(r=1,o=""):o=t+o[0]:u?t===u?u="":o+=t:'"'===t||"'"===t?u=t:">"===t?(i(),r=1):r&&("="===t?(r=5,e=o,o=""):"/"===t&&(r<5||">"===n[c][a+1])?(i(),3===r&&(f=f[0]),r=f,(f=f[0]).push(r,2),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(i(),r=2):o+=t),3===r&&"!--"===o&&(r=4,f=f[0])}return i(),f},a="function"==typeof Map,l=a?new Map:{},p=a?function(n){var t=l.get(n);return t||l.set(n,t=c(n)),t}:function(n){for(var t="",e=0;e1?t:t[0]}}),d=e((function(n,t){var e,r,o,u;n.exports=(e=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],r=function(n){return String(n).replace(/[&<>"']/g,(function(n){return"&"+o[n]+";"}))},o={"&":"amp","<":"lt",">":"gt",'"':"quot","'":"apos"},u={},function(n,t){for(var o=[],f=arguments.length;f-- >2;)o.push(arguments[f]);if("function"==typeof n)return(t||(t={})).children=o.reverse(),n(t);var i="<"+n;if(t)for(var c in t)!1!==t[c]&&null!=t[c]&&(i+=" "+r(c)+'="'+r(t[c])+'"');if(-1===e.indexOf(n)){for(i+=">";o.length;){var a=o.pop();if(a)if(a.pop)for(var l=a.length;l--;)o.push(a[l]);else i+=!0===u[a]?a:r(a)}i+=""}else i+=">";return u[i]=!0,i})})),b=function(n){return n&&n.default||n}(s);function v(){var n=t(["
","
"]);return v=function(){return n},n}function h(){var n=t(["",""]);return h=function(){return n},n}var y=function(n,t,e){var r=b.bind(d);e.bind&&(r=b.bind(e.bind));var o=[];return n.segment(t).forEach((function(n){var t=r(h(),n.segment,n.text);o.push(t)})),r(v(),o)};return function(n){n.prototype.hash=function(){return f(this)},n.prototype.html=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return y(this,n,t)}}})); diff --git a/plugins/output/builds/compromise-output.mjs b/plugins/output/builds/compromise-output.mjs new file mode 100644 index 000000000..70de05b62 --- /dev/null +++ b/plugins/output/builds/compromise-output.mjs @@ -0,0 +1,381 @@ +function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +function _taggedTemplateLiteral(strings, raw) { + if (!raw) { + raw = strings.slice(0); + } + + return Object.freeze(Object.defineProperties(strings, { + raw: { + value: Object.freeze(raw) + } + })); +} + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function unwrapExports (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +var lib = createCommonjsModule(function (module, exports) { + !function (r, n) { + module.exports = n(); + }("undefined" != typeof self ? self : commonjsGlobal, function () { + return function (r) { + var n = {}; + + function e(t) { + if (n[t]) return n[t].exports; + var o = n[t] = { + i: t, + l: !1, + exports: {} + }; + return r[t].call(o.exports, o, o.exports, e), o.l = !0, o.exports; + } + + return e.m = r, e.c = n, e.d = function (r, n, t) { + e.o(r, n) || Object.defineProperty(r, n, { + enumerable: !0, + get: t + }); + }, e.r = function (r) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(r, Symbol.toStringTag, { + value: "Module" + }), Object.defineProperty(r, "__esModule", { + value: !0 + }); + }, e.t = function (r, n) { + if (1 & n && (r = e(r)), 8 & n) return r; + if (4 & n && "object" == _typeof(r) && r && r.__esModule) return r; + var t = Object.create(null); + if (e.r(t), Object.defineProperty(t, "default", { + enumerable: !0, + value: r + }), 2 & n && "string" != typeof r) for (var o in r) { + e.d(t, o, function (n) { + return r[n]; + }.bind(null, o)); + } + return t; + }, e.n = function (r) { + var n = r && r.__esModule ? function () { + return r["default"]; + } : function () { + return r; + }; + return e.d(n, "a", n), n; + }, e.o = function (r, n) { + return Object.prototype.hasOwnProperty.call(r, n); + }, e.p = "", e(e.s = 0); + }([function (r, n, e) { + + e.r(n); + var t = "0123456789abcdef".split(""); + + var o = function o(r) { + for (var n = "", e = 0; e < 4; e++) { + n += t[r >> 8 * e + 4 & 15] + t[r >> 8 * e & 15]; + } + + return n; + }; + + var u = function u(r) { + for (var n = r.length, e = 0; e < n; e++) { + r[e] = o(r[e]); + } + + return r.join(""); + }; + + var f = function f(r, n) { + return r + n & 4294967295; + }; + + var i = function i(r, n, e, t, o, u, _i) { + return function (r, n, e) { + return f(r << n | r >>> 32 - n, e); + }(n = function (r, n, e, t) { + return n = f(f(n, r), f(e, t)); + }(r, n, t, u), o, e); + }; + + var a = function a(r, n, e, t, o, u, f, _a) { + return i(e & t | ~e & o, n, e, u, f, _a); + }; + + var c = function c(r, n, e, t, o, u, f, a) { + return i(e & o | t & ~o, n, e, u, f, a); + }; + + var l = function l(r, n, e, t, o, u, f, a) { + return i(e ^ t ^ o, n, e, u, f, a); + }; + + var d = function d(r, n, e, t, o, u, f, a) { + return i(t ^ (e | ~o), n, e, u, f, a); + }; + + var v = function v(r, n, e) { + void 0 === e && (e = f); + var t = r[0], + o = r[1], + u = r[2], + i = r[3], + v = a.bind(null, e); + t = v(t, o, u, i, n[0], 7, -680876936), i = v(i, t, o, u, n[1], 12, -389564586), u = v(u, i, t, o, n[2], 17, 606105819), o = v(o, u, i, t, n[3], 22, -1044525330), t = v(t, o, u, i, n[4], 7, -176418897), i = v(i, t, o, u, n[5], 12, 1200080426), u = v(u, i, t, o, n[6], 17, -1473231341), o = v(o, u, i, t, n[7], 22, -45705983), t = v(t, o, u, i, n[8], 7, 1770035416), i = v(i, t, o, u, n[9], 12, -1958414417), u = v(u, i, t, o, n[10], 17, -42063), o = v(o, u, i, t, n[11], 22, -1990404162), t = v(t, o, u, i, n[12], 7, 1804603682), i = v(i, t, o, u, n[13], 12, -40341101), u = v(u, i, t, o, n[14], 17, -1502002290), o = v(o, u, i, t, n[15], 22, 1236535329); + var s = c.bind(null, e); + t = s(t, o, u, i, n[1], 5, -165796510), i = s(i, t, o, u, n[6], 9, -1069501632), u = s(u, i, t, o, n[11], 14, 643717713), o = s(o, u, i, t, n[0], 20, -373897302), t = s(t, o, u, i, n[5], 5, -701558691), i = s(i, t, o, u, n[10], 9, 38016083), u = s(u, i, t, o, n[15], 14, -660478335), o = s(o, u, i, t, n[4], 20, -405537848), t = s(t, o, u, i, n[9], 5, 568446438), i = s(i, t, o, u, n[14], 9, -1019803690), u = s(u, i, t, o, n[3], 14, -187363961), o = s(o, u, i, t, n[8], 20, 1163531501), t = s(t, o, u, i, n[13], 5, -1444681467), i = s(i, t, o, u, n[2], 9, -51403784), u = s(u, i, t, o, n[7], 14, 1735328473), o = s(o, u, i, t, n[12], 20, -1926607734); + var b = l.bind(null, e); + t = b(t, o, u, i, n[5], 4, -378558), i = b(i, t, o, u, n[8], 11, -2022574463), u = b(u, i, t, o, n[11], 16, 1839030562), o = b(o, u, i, t, n[14], 23, -35309556), t = b(t, o, u, i, n[1], 4, -1530992060), i = b(i, t, o, u, n[4], 11, 1272893353), u = b(u, i, t, o, n[7], 16, -155497632), o = b(o, u, i, t, n[10], 23, -1094730640), t = b(t, o, u, i, n[13], 4, 681279174), i = b(i, t, o, u, n[0], 11, -358537222), u = b(u, i, t, o, n[3], 16, -722521979), o = b(o, u, i, t, n[6], 23, 76029189), t = b(t, o, u, i, n[9], 4, -640364487), i = b(i, t, o, u, n[12], 11, -421815835), u = b(u, i, t, o, n[15], 16, 530742520), o = b(o, u, i, t, n[2], 23, -995338651); + var p = d.bind(null, e); + t = p(t, o, u, i, n[0], 6, -198630844), i = p(i, t, o, u, n[7], 10, 1126891415), u = p(u, i, t, o, n[14], 15, -1416354905), o = p(o, u, i, t, n[5], 21, -57434055), t = p(t, o, u, i, n[12], 6, 1700485571), i = p(i, t, o, u, n[3], 10, -1894986606), u = p(u, i, t, o, n[10], 15, -1051523), o = p(o, u, i, t, n[1], 21, -2054922799), t = p(t, o, u, i, n[8], 6, 1873313359), i = p(i, t, o, u, n[15], 10, -30611744), u = p(u, i, t, o, n[6], 15, -1560198380), o = p(o, u, i, t, n[13], 21, 1309151649), t = p(t, o, u, i, n[4], 6, -145523070), i = p(i, t, o, u, n[11], 10, -1120210379), u = p(u, i, t, o, n[2], 15, 718787259), o = p(o, u, i, t, n[9], 21, -343485551), r[0] = e(t, r[0]), r[1] = e(o, r[1]), r[2] = e(u, r[2]), r[3] = e(i, r[3]); + }; + + var s = function s(r) { + for (var n = [], e = 0; e < 64; e += 4) { + n[e >> 2] = r.charCodeAt(e) + (r.charCodeAt(e + 1) << 8) + (r.charCodeAt(e + 2) << 16) + (r.charCodeAt(e + 3) << 24); + } + + return n; + }; + + var b = function b(r, n) { + var e, + t = r.length, + o = [1732584193, -271733879, -1732584194, 271733878]; + + for (e = 64; e <= t; e += 64) { + v(o, s(r.substring(e - 64, e)), n); + } + + var u = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + f = (r = r.substring(e - 64)).length; + + for (e = 0; e < f; e++) { + u[e >> 2] |= r.charCodeAt(e) << (e % 4 << 3); + } + + if (u[e >> 2] |= 128 << (e % 4 << 3), e > 55) for (v(o, u, n), e = 16; e--;) { + u[e] = 0; + } + return u[14] = 8 * t, v(o, u, n), o; + }; + + function p(r) { + var n; + return "5d41402abc4b2a76b9719d911017c592" !== u(b("hello")) && (n = function n(r, _n) { + var e = (65535 & r) + (65535 & _n); + return (r >> 16) + (_n >> 16) + (e >> 16) << 16 | 65535 & e; + }), u(b(r, n)); + } + + e.d(n, "md5", function () { + return p; + }); + }]); + }); +}); +unwrapExports(lib); + +var md5 = lib.md5; + +var makeHash = function makeHash(doc) { + var str = doc.text(); + doc.list.forEach(function (p) { + p.terms().forEach(function (t) { + str += t.pre + (t.implicit || t.text) + t.post; + str += Object.keys(t.tags).join(''); + }); + }); + return md5(str); +}; + +var hash = makeHash; + +var n = function n(t, r, u, e) { + for (var p = 1; p < r.length; p++) { + var s = r[p], + h = "number" == typeof s ? u[s] : s, + a = r[++p]; + 1 === a ? e[0] = h : 3 === a ? e[1] = Object.assign(e[1] || {}, h) : 5 === a ? (e[1] = e[1] || {})[r[++p]] = h : 6 === a ? e[1][r[++p]] += h + "" : e.push(a ? t.apply(null, n(t, h, u, ["", null])) : h); + } + + return e; +}, + t = function t(n) { + for (var t, r, u = 1, e = "", p = "", s = [0], h = function h(n) { + 1 === u && (n || (e = e.replace(/^\s*\n\s*|\s*\n\s*$/g, ""))) ? s.push(n || e, 0) : 3 === u && (n || e) ? (s.push(n || e, 1), u = 2) : 2 === u && "..." === e && n ? s.push(n, 3) : 2 === u && e && !n ? s.push(!0, 5, e) : u >= 5 && ((e || !n && 5 === u) && (s.push(e, u, r), u = 6), n && (s.push(n, u, r), u = 6)), e = ""; + }, a = 0; a < n.length; a++) { + a && (1 === u && h(), h(a)); + + for (var f = 0; f < n[a].length; f++) { + t = n[a][f], 1 === u ? "<" === t ? (h(), s = [s], u = 3) : e += t : 4 === u ? "--" === e && ">" === t ? (u = 1, e = "") : e = t + e[0] : p ? t === p ? p = "" : e += t : '"' === t || "'" === t ? p = t : ">" === t ? (h(), u = 1) : u && ("=" === t ? (u = 5, r = e, e = "") : "/" === t && (u < 5 || ">" === n[a][f + 1]) ? (h(), 3 === u && (s = s[0]), u = s, (s = s[0]).push(u, 2), u = 0) : " " === t || "\t" === t || "\n" === t || "\r" === t ? (h(), u = 2) : e += t), 3 === u && "!--" === e && (u = 4, s = s[0]); + } + } + + return h(), s; +}, + r = "function" == typeof Map, + u = r ? new Map() : {}, + e = r ? function (n) { + var r = u.get(n); + return r || u.set(n, r = t(n)), r; +} : function (n) { + for (var r = "", e = 0; e < n.length; e++) { + r += n[e].length + "-" + n[e]; + } + + return u[r] || (u[r] = t(n)); +}; + +function htm (t) { + var r = n(this, e(t), arguments, []); + return r.length > 1 ? r : r[0]; +} + +var vhtml = createCommonjsModule(function (module, exports) { + (function (global, factory) { + module.exports = factory() ; + })(commonjsGlobal, function () { + + var emptyTags = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']; + + var esc = function esc(str) { + return String(str).replace(/[&<>"']/g, function (s) { + return '&' + map[s] + ';'; + }); + }; + + var map = { + '&': 'amp', + '<': 'lt', + '>': 'gt', + '"': 'quot', + "'": 'apos' + }; + var sanitized = {}; + + function h(name, attrs) { + var stack = []; + + for (var i = arguments.length; i-- > 2;) { + stack.push(arguments[i]); + } + + if (typeof name === 'function') { + (attrs || (attrs = {})).children = stack.reverse(); + return name(attrs); + } + + var s = '<' + name; + if (attrs) for (var _i in attrs) { + if (attrs[_i] !== false && attrs[_i] != null) { + s += ' ' + esc(_i) + '="' + esc(attrs[_i]) + '"'; + } + } + + if (emptyTags.indexOf(name) === -1) { + s += '>'; + + while (stack.length) { + var child = stack.pop(); + + if (child) { + if (child.pop) { + for (var _i2 = child.length; _i2--;) { + stack.push(child[_i2]); + } + } else { + s += sanitized[child] === true ? child : esc(child); + } + } + } + + s += ''; + } else { + s += '>'; + } + + sanitized[s] = true; + return s; + } + + return h; + }); +}); + +function _templateObject2() { + var data = _taggedTemplateLiteral(["
", "
"]); + + _templateObject2 = function _templateObject2() { + return data; + }; + + return data; +} + +function _templateObject() { + var data = _taggedTemplateLiteral(["", ""]); + + _templateObject = function _templateObject() { + return data; + }; + + return data; +} + +var toHtml = function toHtml(doc, segments, options) { + var h = htm.bind(vhtml); + + if (options.bind) { + h = htm.bind(options.bind); + } + + var html = []; + var arr = doc.segment(segments); + arr.forEach(function (o) { + var str = h(_templateObject(), o.segment, o.text); + html.push(str); + }); + return h(_templateObject2(), html); +}; + +var html = toHtml; + +var addMethods = function addMethods(Doc) { + /** generate an md5 hash from the document */ + Doc.prototype.hash = function () { + return hash(this); + }; + /** generate sanitized html from the document */ + + + Doc.prototype.html = function () { + var segments = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return html(this, segments, options); + }; +}; + +var src = addMethods; + +export default src; diff --git a/plugins/output/package-lock.json b/plugins/output/package-lock.json new file mode 100644 index 000000000..f0f1fd10d --- /dev/null +++ b/plugins/output/package-lock.json @@ -0,0 +1,774 @@ +{ + "name": "compromise-output", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz", + "integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", + "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz", + "integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "htm": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/htm/-/htm-2.2.1.tgz", + "integrity": "sha512-nPWqBlSbdSHaT2d/cpFRpZLqH5BcdaRcXaicyAtXbkIsIiXLnstPPg0fEX3I8SrlY16FSzb1FLK44uk25xhMvw==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", + "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "magic-string": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz", + "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "pure-md5": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/pure-md5/-/pure-md5-0.1.9.tgz", + "integrity": "sha512-SA/xeqGm/WSx9sup7801Xl8cs2mi5IB6UTCOapWcHc7IeAlMn4k3JBO9aLH+88+JrqqUANhVwX1+Tz3dlvRI+A==" + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.8.tgz", + "integrity": "sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vhtml": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vhtml/-/vhtml-2.1.0.tgz", + "integrity": "sha1-qFjtLjKMWVOZphroig4A+3Vr4Bw=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/plugins/output/package.json b/plugins/output/package.json new file mode 100644 index 000000000..7014a6d82 --- /dev/null +++ b/plugins/output/package.json @@ -0,0 +1,51 @@ +{ + "name": "compromise-output", + "description": "plugin for nlp-compromise", + "version": "0.0.2", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-output.js", + "unpkg": "./builds/compromise-output.min.js", + "module": "./builds/compromise-output.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*" + }, + "dependencies": { + "htm": "^2.2.1", + "pure-md5": "^0.1.9", + "vhtml": "^2.1.0" + }, + "devDependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/plugins/output/rollup.config.js b/plugins/output/rollup.config.js new file mode 100644 index 000000000..0b75449b1 --- /dev/null +++ b/plugins/output/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-output' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseOutput', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseOutput', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/output/src/hash.js b/plugins/output/src/hash.js new file mode 100644 index 000000000..9f850e303 --- /dev/null +++ b/plugins/output/src/hash.js @@ -0,0 +1,13 @@ +const md5 = require('pure-md5').md5 + +const makeHash = function(doc) { + let str = doc.text() + doc.list.forEach(p => { + p.terms().forEach(t => { + str += t.pre + (t.implicit || t.text) + t.post + str += Object.keys(t.tags).join('') + }) + }) + return md5(str) +} +module.exports = makeHash diff --git a/plugins/output/src/html.js b/plugins/output/src/html.js new file mode 100644 index 000000000..1cffdda5b --- /dev/null +++ b/plugins/output/src/html.js @@ -0,0 +1,17 @@ +const htm = require('htm') +const vhtml = require('vhtml') + +const toHtml = function(doc, segments, options) { + let h = htm.bind(vhtml) + if (options.bind) { + h = htm.bind(options.bind) + } + let html = [] + let arr = doc.segment(segments) + arr.forEach(o => { + let str = h`${o.text}` + html.push(str) + }) + return h`
${html}
` +} +module.exports = toHtml diff --git a/plugins/output/src/index.js b/plugins/output/src/index.js new file mode 100644 index 000000000..cb02ae270 --- /dev/null +++ b/plugins/output/src/index.js @@ -0,0 +1,15 @@ +const makeHash = require('./hash') +const toHtml = require('./html') + +const addMethods = function(Doc) { + /** generate an md5 hash from the document */ + Doc.prototype.hash = function() { + return makeHash(this) + } + + /** generate sanitized html from the document */ + Doc.prototype.html = function(segments = {}, options = {}) { + return toHtml(this, segments, options) + } +} +module.exports = addMethods diff --git a/plugins/output/tests/_lib.js b/plugins/output/tests/_lib.js new file mode 100644 index 000000000..254633449 --- /dev/null +++ b/plugins/output/tests/_lib.js @@ -0,0 +1,12 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + } + + module.exports = nlp +} diff --git a/plugins/output/tests/misc.test.js b/plugins/output/tests/misc.test.js new file mode 100644 index 000000000..b198df6a3 --- /dev/null +++ b/plugins/output/tests/misc.test.js @@ -0,0 +1,30 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('hash has whitespace', function(t) { + let doc = nlp(`He isn't... working `) + doc.normalize({ + case: false, + punctuation: true, + contractions: false, + }) + t.equal(nlp('he is not working').hash() === doc.hash(), false, 'whitespace changes hash') + t.end() +}) + +test('hash output', function(t) { + let docA = nlp('hello there') + let docB = nlp('hello there') + t.equal(docA.hash() === docB.hash(), true, 'both are equal') + + docB.match('hello').tag('Greeting') + t.equal(docA.hash() === docB.hash(), false, 'hashes not equal after tag') + t.end() +}) + +test('html output', function(t) { + let doc = nlp('i <3 you') + t.equal(doc.html(), '
i <3 you
', 'html escaped') + doc = nlp() + t.end() +}) diff --git a/plugins/paragraphs/README.md b/plugins/paragraphs/README.md new file mode 100644 index 000000000..8dfd0b05b --- /dev/null +++ b/plugins/paragraphs/README.md @@ -0,0 +1,105 @@ +
+ + +
a plugin for compromise
+ + + + + + v + + + + +
+
+ +
+ npm install compromise-paragraphs +
+ +```js +let str = `What's with these homies dissin' my girl? Why do they gotta front? + +What did we ever do to these guys that made them so violent? + +Woo-hoo, but you know I'm yours. +Woo-hoo, and I know you're mine. +Woo-hoo, and that's for all time +` + +let doc = nlp(str).paragraphs() + +doc.length +// 3 + +doc.json(options) +/*[ + {text:'What's with these ...', sentences:[{},{}]} + {text:'What did we ever ...', sentences:[{}]} +]*/ + +// get the second paragraph +doc.eq(1).text() +// 'What did we ever ...' + +// get the first two sentences of the first paragraph +doc + .first() + .sentences() + .slice(0, 2) +``` + +This is a tentative implementation of `.paragraphs()` and associated methods, for compromise. + +This is tricky because a sentence is a top-level structure to compromise, (and english grammar!), and combining sentences together would have some consequences about grammatical tags. + +Instead, this plugin is a (partially-complete) wrapper for sentence objects, so that you can call things like `.text()` and `.json()` on a paragraph, but then drop back down to `.sentences()` after, and work as normal. + +The term objects passed into `.paragraphs()` are mutable, so they will actually change when you transform them: + +```js +let doc = nlp(str).paragraphs() + +doc = doc.filter(p => { + return p.has('#Determiner guys') +}) +// What did we ever do to these guys that made them so violent? +``` + +### [Demo](https://observablehq.com/@spencermountain/compromise-paragraphs) + +## API: + +outputs: + +- .text() +- .json() + +matches: + +- .match() +- .not() +- .if() +- .ifNo() +- .has() + +selectors: + +- .sentences() +- .terms() + +accessors: + +- .eq() +- .first() +- .last() + +loops: + +- .forEach() +- .map() +- .filter() + +MIT diff --git a/plugins/paragraphs/builds/compromise-paragraphs.js b/plugins/paragraphs/builds/compromise-paragraphs.js new file mode 100644 index 000000000..4e4b678bb --- /dev/null +++ b/plugins/paragraphs/builds/compromise-paragraphs.js @@ -0,0 +1,262 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseParagraphs = factory()); +}(this, (function () { 'use strict'; + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + var addMethods = function addMethods(Paragraphs, Doc) { + var methods = { + // return back to a regular Doc object + sentences: function sentences(n) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + list = list.concat(doc.list); + }); + }); + var doc = new Doc(list, this.parent, this.world); + + if (typeof n === 'number') { + return doc.eq(n); + } + + return doc; + }, + // grab every term in the paragraph + terms: function terms(n) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + list = list.concat(doc.terms().list); + }); + }); + var doc = new Doc(list, this.parent, this.world); + + if (typeof n === 'number') { + return doc.eq(n); + } + + return doc; + }, + + /** return metadata for each paragraph */ + json: function json() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return this.paragraphs.map(function (docs) { + var text = docs.map(function (d) { + return d.text(); + }).join(''); + var obj = { + text: text, + sentences: docs.map(function (d) { + return d.json(options); + }) + }; + + if (options.normal) { + obj.normal = docs.map(function (d) { + return d.text('normal'); + }).join(''); + } + + return obj; + }); + }, + + /** print out the text of each paragraph */ + text: function text(options) { + var text = ''; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + text += doc.text(options); + }); + }); + return text; + }, + // accessor method wrappers + eq: function eq(n) { + var list = [this.paragraphs[n]]; + list = list.filter(function (l) { + return l; + }); + return new Paragraphs(list, this, this.world); + }, + first: function first() { + return this.eq(0); + }, + last: function last() { + var len = this.length; + return this.eq(len - 1); + }, + debug: function debug() { + this.paragraphs.forEach(function (docs) { + console.log('\n=-=-=-=-'); + docs.forEach(function (doc) { + doc.debug(); + }); + }); + }, + // match methods + // returns doc objects, not paragraph objects + match: function match(str) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + var m = doc.match(str); + + if (m.found) { + list = list.concat(m.list); + } + }); + }); + return new Doc(list, this.parent, this.world); + }, + // returns doc objects + not: function not(str) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + var m = doc.not(str); + + if (m.found) { + list = list.concat(m.list); + } + }); + }); + return new Doc(list, this.parent, this.world); + }, + // returns paragraph objects + "if": function _if(str) { + var list = this.paragraphs.filter(function (docs) { + return docs.some(function (doc) { + return doc.has(str); + }); + }); + return new Paragraphs(list, this, this.world); + }, + ifNo: function ifNo(str) { + var list = this.paragraphs.filter(function (docs) { + return docs.some(function (doc) { + return doc.has(str) === false; + }); + }); + return new Paragraphs(list, this, this.world); + }, + // returns boolean + has: function has(str) { + return this.paragraphs.some(function (docs) { + for (var i = 0; i < docs.length; i++) { + return docs[i].has(str); + } + }); + }, + //loops + forEach: function forEach(fn) { + var _this = this; + + this.paragraphs.forEach(function (docs) { + var p = new Paragraphs([docs], _this, _this.world); + fn(p); + }); + return this; + }, + map: function map(fn) { + var _this2 = this; + + var paragraphs = this.paragraphs.map(function (docs) { + var p = new Paragraphs([docs], _this2, _this2.world); + return fn(p); + }); + new Paragraphs(paragraphs, this, this.world); + }, + //each paragraph must have atleast one sentence that matches + filter: function filter(fn) { + this.paragraphs = this.paragraphs.filter(function (docs) { + return docs.some(fn); + }); + return this; + } + }; // aliases + + methods.get = methods.eq; + Object.keys(methods).forEach(function (k) { + Paragraphs.prototype[k] = methods[k]; + }); + }; + + var methods = addMethods; + + var hasTwoNewline = /\n\n/; + + var addMethods$1 = function addMethods(Doc) { + /** an abstraction on top of Doc */ + var Paragraphs = function Paragraphs(paragraphs, parent, world) { + var _this = this; + + _classCallCheck(this, Paragraphs); + + Object.defineProperty(this, 'paragraphs', { + enumerable: false, + writable: true, + value: paragraphs + }); + this.parent = parent; + this.world = world; //'found' getter + + Object.defineProperty(this, 'found', { + get: function get() { + return _this.paragraphs.length > 0; + } + }); //'length' getter + + Object.defineProperty(this, 'length', { + get: function get() { + return _this.paragraphs.length; + } + }); + }; // add our wrapper methods for Doc + + + methods(Paragraphs, Doc); // finder method creates the sentence groups + + Doc.prototype.paragraphs = function (n) { + var match = this.all(); + var results = []; + var carry = []; + match.forEach(function (s) { + carry.push(s); + + if (hasTwoNewline.test(s.post()[0])) { + results.push(carry); + carry = []; + } + }); + + if (carry.length > 0) { + results.push(carry); + } + + if (typeof n === 'number') { + if (results[n]) { + results = [results[n]]; + } else { + results = []; + } + } + + return new Paragraphs(results, this, this.world); + }; + }; + + var src = addMethods$1; + + return src; + +}))); +//# sourceMappingURL=compromise-paragraphs.js.map diff --git a/plugins/paragraphs/builds/compromise-paragraphs.js.map b/plugins/paragraphs/builds/compromise-paragraphs.js.map new file mode 100644 index 000000000..40cafc3ba --- /dev/null +++ b/plugins/paragraphs/builds/compromise-paragraphs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-paragraphs.js","sources":["../src/methods.js","../src/index.js"],"sourcesContent":["const addMethods = function(Paragraphs, Doc) {\n const methods = {\n // return back to a regular Doc object\n sentences: function(n) {\n let list = []\n this.paragraphs.forEach(docs => {\n docs.forEach(doc => {\n list = list.concat(doc.list)\n })\n })\n let doc = new Doc(list, this.parent, this.world)\n if (typeof n === 'number') {\n return doc.eq(n)\n }\n return doc\n },\n\n // grab every term in the paragraph\n terms: function(n) {\n let list = []\n this.paragraphs.forEach(docs => {\n docs.forEach(doc => {\n list = list.concat(doc.terms().list)\n })\n })\n let doc = new Doc(list, this.parent, this.world)\n if (typeof n === 'number') {\n return doc.eq(n)\n }\n return doc\n },\n\n /** return metadata for each paragraph */\n json: function(options = {}) {\n return this.paragraphs.map(docs => {\n let text = docs.map(d => d.text()).join('')\n let obj = {\n text: text,\n sentences: docs.map(d => d.json(options)),\n }\n if (options.normal) {\n obj.normal = docs.map(d => d.text('normal')).join('')\n }\n return obj\n })\n },\n\n /** print out the text of each paragraph */\n text: function(options) {\n let text = ''\n this.paragraphs.forEach(docs => {\n docs.forEach(doc => {\n text += doc.text(options)\n })\n })\n return text\n },\n\n // accessor method wrappers\n eq: function(n) {\n let list = [this.paragraphs[n]]\n list = list.filter(l => l)\n return new Paragraphs(list, this, this.world)\n },\n first: function() {\n return this.eq(0)\n },\n last: function() {\n let len = this.length\n return this.eq(len - 1)\n },\n debug: function() {\n this.paragraphs.forEach(docs => {\n console.log('\\n=-=-=-=-')\n docs.forEach(doc => {\n doc.debug()\n })\n })\n },\n\n // match methods\n\n // returns doc objects, not paragraph objects\n match: function(str) {\n let list = []\n this.paragraphs.forEach(docs => {\n docs.forEach(doc => {\n let m = doc.match(str)\n if (m.found) {\n list = list.concat(m.list)\n }\n })\n })\n return new Doc(list, this.parent, this.world)\n },\n // returns doc objects\n not: function(str) {\n let list = []\n this.paragraphs.forEach(docs => {\n docs.forEach(doc => {\n let m = doc.not(str)\n if (m.found) {\n list = list.concat(m.list)\n }\n })\n })\n return new Doc(list, this.parent, this.world)\n },\n // returns paragraph objects\n if: function(str) {\n let list = this.paragraphs.filter(docs => {\n return docs.some(doc => doc.has(str))\n })\n return new Paragraphs(list, this, this.world)\n },\n ifNo: function(str) {\n let list = this.paragraphs.filter(docs => {\n return docs.some(doc => doc.has(str) === false)\n })\n return new Paragraphs(list, this, this.world)\n },\n // returns boolean\n has: function(str) {\n return this.paragraphs.some(docs => {\n for (let i = 0; i < docs.length; i++) {\n return docs[i].has(str)\n }\n })\n },\n\n //loops\n forEach: function(fn) {\n this.paragraphs.forEach(docs => {\n let p = new Paragraphs([docs], this, this.world)\n fn(p)\n })\n return this\n },\n map: function(fn) {\n let paragraphs = this.paragraphs.map(docs => {\n let p = new Paragraphs([docs], this, this.world)\n return fn(p)\n })\n new Paragraphs(paragraphs, this, this.world)\n },\n\n //each paragraph must have atleast one sentence that matches\n filter: function(fn) {\n this.paragraphs = this.paragraphs.filter(docs => {\n return docs.some(fn)\n })\n return this\n },\n }\n // aliases\n methods.get = methods.eq\n\n Object.keys(methods).forEach(k => {\n Paragraphs.prototype[k] = methods[k]\n })\n}\nmodule.exports = addMethods\n","const hasTwoNewline = /\\n\\n/\nconst wrapperMethods = require('./methods')\n\nconst addMethods = function(Doc) {\n /** an abstraction on top of Doc */\n class Paragraphs {\n constructor(paragraphs, parent, world) {\n Object.defineProperty(this, 'paragraphs', {\n enumerable: false,\n writable: true,\n value: paragraphs,\n })\n this.parent = parent\n this.world = world\n //'found' getter\n Object.defineProperty(this, 'found', {\n get: () => this.paragraphs.length > 0,\n })\n //'length' getter\n Object.defineProperty(this, 'length', {\n get: () => this.paragraphs.length,\n })\n }\n }\n // add our wrapper methods for Doc\n wrapperMethods(Paragraphs, Doc)\n\n // finder method creates the sentence groups\n Doc.prototype.paragraphs = function(n) {\n let match = this.all()\n let results = []\n let carry = []\n match.forEach(s => {\n carry.push(s)\n if (hasTwoNewline.test(s.post()[0])) {\n results.push(carry)\n carry = []\n }\n })\n if (carry.length > 0) {\n results.push(carry)\n }\n if (typeof n === 'number') {\n if (results[n]) {\n results = [results[n]]\n } else {\n results = []\n }\n }\n return new Paragraphs(results, this, this.world)\n }\n}\n\nmodule.exports = addMethods\n"],"names":["addMethods","Paragraphs","Doc","methods","sentences","n","list","paragraphs","forEach","docs","doc","concat","parent","world","eq","terms","json","options","map","text","d","join","obj","normal","filter","l","first","last","len","length","debug","console","log","match","str","m","found","not","some","has","ifNo","i","fn","p","get","Object","keys","k","prototype","hasTwoNewline","defineProperty","enumerable","writable","value","wrapperMethods","all","results","carry","s","push","test","post"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/paragraphs/builds/compromise-paragraphs.min.js b/plugins/paragraphs/builds/compromise-paragraphs.min.js new file mode 100644 index 000000000..ac011eb9d --- /dev/null +++ b/plugins/paragraphs/builds/compromise-paragraphs.min.js @@ -0,0 +1 @@ +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t=t||self).compromiseParagraphs=n()}(this,(function(){"use strict";var t=function(t,n){var r={sentences:function(t){var r=[];this.paragraphs.forEach((function(t){t.forEach((function(t){r=r.concat(t.list)}))}));var a=new n(r,this.parent,this.world);return"number"==typeof t?a.eq(t):a},terms:function(t){var r=[];this.paragraphs.forEach((function(t){t.forEach((function(t){r=r.concat(t.terms().list)}))}));var a=new n(r,this.parent,this.world);return"number"==typeof t?a.eq(t):a},json:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return this.paragraphs.map((function(n){var r={text:n.map((function(t){return t.text()})).join(""),sentences:n.map((function(n){return n.json(t)}))};return t.normal&&(r.normal=n.map((function(t){return t.text("normal")})).join("")),r}))},text:function(t){var n="";return this.paragraphs.forEach((function(r){r.forEach((function(r){n+=r.text(t)}))})),n},eq:function(n){var r=[this.paragraphs[n]];return r=r.filter((function(t){return t})),new t(r,this,this.world)},first:function(){return this.eq(0)},last:function(){var t=this.length;return this.eq(t-1)},debug:function(){this.paragraphs.forEach((function(t){console.log("\n=-=-=-=-"),t.forEach((function(t){t.debug()}))}))},match:function(t){var r=[];return this.paragraphs.forEach((function(n){n.forEach((function(n){var a=n.match(t);a.found&&(r=r.concat(a.list))}))})),new n(r,this.parent,this.world)},not:function(t){var r=[];return this.paragraphs.forEach((function(n){n.forEach((function(n){var a=n.not(t);a.found&&(r=r.concat(a.list))}))})),new n(r,this.parent,this.world)},if:function(n){var r=this.paragraphs.filter((function(t){return t.some((function(t){return t.has(n)}))}));return new t(r,this,this.world)},ifNo:function(n){var r=this.paragraphs.filter((function(t){return t.some((function(t){return!1===t.has(n)}))}));return new t(r,this,this.world)},has:function(t){return this.paragraphs.some((function(n){for(var r=0;r0}}),Object.defineProperty(this,"length",{get:function(){return e.paragraphs.length}})};t(a,r),r.prototype.paragraphs=function(t){var r=this.all(),e=[],o=[];return r.forEach((function(t){o.push(t),n.test(t.post()[0])&&(e.push(o),o=[])})),o.length>0&&e.push(o),"number"==typeof t&&(e=e[t]?[e[t]]:[]),new a(e,this,this.world)}}})); diff --git a/plugins/paragraphs/builds/compromise-paragraphs.mjs b/plugins/paragraphs/builds/compromise-paragraphs.mjs new file mode 100644 index 000000000..57b8f8617 --- /dev/null +++ b/plugins/paragraphs/builds/compromise-paragraphs.mjs @@ -0,0 +1,253 @@ +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +var addMethods = function addMethods(Paragraphs, Doc) { + var methods = { + // return back to a regular Doc object + sentences: function sentences(n) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + list = list.concat(doc.list); + }); + }); + var doc = new Doc(list, this.parent, this.world); + + if (typeof n === 'number') { + return doc.eq(n); + } + + return doc; + }, + // grab every term in the paragraph + terms: function terms(n) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + list = list.concat(doc.terms().list); + }); + }); + var doc = new Doc(list, this.parent, this.world); + + if (typeof n === 'number') { + return doc.eq(n); + } + + return doc; + }, + + /** return metadata for each paragraph */ + json: function json() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return this.paragraphs.map(function (docs) { + var text = docs.map(function (d) { + return d.text(); + }).join(''); + var obj = { + text: text, + sentences: docs.map(function (d) { + return d.json(options); + }) + }; + + if (options.normal) { + obj.normal = docs.map(function (d) { + return d.text('normal'); + }).join(''); + } + + return obj; + }); + }, + + /** print out the text of each paragraph */ + text: function text(options) { + var text = ''; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + text += doc.text(options); + }); + }); + return text; + }, + // accessor method wrappers + eq: function eq(n) { + var list = [this.paragraphs[n]]; + list = list.filter(function (l) { + return l; + }); + return new Paragraphs(list, this, this.world); + }, + first: function first() { + return this.eq(0); + }, + last: function last() { + var len = this.length; + return this.eq(len - 1); + }, + debug: function debug() { + this.paragraphs.forEach(function (docs) { + console.log('\n=-=-=-=-'); + docs.forEach(function (doc) { + doc.debug(); + }); + }); + }, + // match methods + // returns doc objects, not paragraph objects + match: function match(str) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + var m = doc.match(str); + + if (m.found) { + list = list.concat(m.list); + } + }); + }); + return new Doc(list, this.parent, this.world); + }, + // returns doc objects + not: function not(str) { + var list = []; + this.paragraphs.forEach(function (docs) { + docs.forEach(function (doc) { + var m = doc.not(str); + + if (m.found) { + list = list.concat(m.list); + } + }); + }); + return new Doc(list, this.parent, this.world); + }, + // returns paragraph objects + "if": function _if(str) { + var list = this.paragraphs.filter(function (docs) { + return docs.some(function (doc) { + return doc.has(str); + }); + }); + return new Paragraphs(list, this, this.world); + }, + ifNo: function ifNo(str) { + var list = this.paragraphs.filter(function (docs) { + return docs.some(function (doc) { + return doc.has(str) === false; + }); + }); + return new Paragraphs(list, this, this.world); + }, + // returns boolean + has: function has(str) { + return this.paragraphs.some(function (docs) { + for (var i = 0; i < docs.length; i++) { + return docs[i].has(str); + } + }); + }, + //loops + forEach: function forEach(fn) { + var _this = this; + + this.paragraphs.forEach(function (docs) { + var p = new Paragraphs([docs], _this, _this.world); + fn(p); + }); + return this; + }, + map: function map(fn) { + var _this2 = this; + + var paragraphs = this.paragraphs.map(function (docs) { + var p = new Paragraphs([docs], _this2, _this2.world); + return fn(p); + }); + new Paragraphs(paragraphs, this, this.world); + }, + //each paragraph must have atleast one sentence that matches + filter: function filter(fn) { + this.paragraphs = this.paragraphs.filter(function (docs) { + return docs.some(fn); + }); + return this; + } + }; // aliases + + methods.get = methods.eq; + Object.keys(methods).forEach(function (k) { + Paragraphs.prototype[k] = methods[k]; + }); +}; + +var methods = addMethods; + +var hasTwoNewline = /\n\n/; + +var addMethods$1 = function addMethods(Doc) { + /** an abstraction on top of Doc */ + var Paragraphs = function Paragraphs(paragraphs, parent, world) { + var _this = this; + + _classCallCheck(this, Paragraphs); + + Object.defineProperty(this, 'paragraphs', { + enumerable: false, + writable: true, + value: paragraphs + }); + this.parent = parent; + this.world = world; //'found' getter + + Object.defineProperty(this, 'found', { + get: function get() { + return _this.paragraphs.length > 0; + } + }); //'length' getter + + Object.defineProperty(this, 'length', { + get: function get() { + return _this.paragraphs.length; + } + }); + }; // add our wrapper methods for Doc + + + methods(Paragraphs, Doc); // finder method creates the sentence groups + + Doc.prototype.paragraphs = function (n) { + var match = this.all(); + var results = []; + var carry = []; + match.forEach(function (s) { + carry.push(s); + + if (hasTwoNewline.test(s.post()[0])) { + results.push(carry); + carry = []; + } + }); + + if (carry.length > 0) { + results.push(carry); + } + + if (typeof n === 'number') { + if (results[n]) { + results = [results[n]]; + } else { + results = []; + } + } + + return new Paragraphs(results, this, this.world); + }; +}; + +var src = addMethods$1; + +export default src; diff --git a/plugins/paragraphs/package-lock.json b/plugins/paragraphs/package-lock.json new file mode 100644 index 000000000..9fb0a8000 --- /dev/null +++ b/plugins/paragraphs/package-lock.json @@ -0,0 +1,759 @@ +{ + "name": "compromise-paragraphs", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.8.tgz", + "integrity": "sha512-FMdVn84tJJdV+xe+53sYiZS4R5yn1mAIxfj+DVoNiQjTYz1+OYmjwEZr1ev9nU0axXwda0QDbYl06QHanRVH3A==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz", + "integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", + "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "magic-string": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz", + "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.4.tgz", + "integrity": "sha512-Kcrn3RiW8NtHBP0ssOAzwa2MsIRQ8lJWiBG/K7JgqPlomA3mtb2DEmp4/hrUA+Jujx+WZ02zqd7GYD+QRBB/2Q==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/plugins/paragraphs/package.json b/plugins/paragraphs/package.json new file mode 100644 index 000000000..518cf810f --- /dev/null +++ b/plugins/paragraphs/package.json @@ -0,0 +1,47 @@ +{ + "name": "compromise-paragraphs", + "description": "plugin for nlp-compromise", + "version": "0.0.2", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-paragraphs.js", + "unpkg": "./builds/compromise-paragraphs.min.js", + "module": "./builds/compromise-paragraphs.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*" + }, + "dependencies": {}, + "devDependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/plugins/paragraphs/rollup.config.js b/plugins/paragraphs/rollup.config.js new file mode 100644 index 000000000..e1c85e7d6 --- /dev/null +++ b/plugins/paragraphs/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-paragraphs' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseParagraphs', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseParagraphs', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/paragraphs/src/index.js b/plugins/paragraphs/src/index.js new file mode 100644 index 000000000..b593049ef --- /dev/null +++ b/plugins/paragraphs/src/index.js @@ -0,0 +1,54 @@ +const hasTwoNewline = /\n\n/ +const wrapperMethods = require('./methods') + +const addMethods = function(Doc) { + /** an abstraction on top of Doc */ + class Paragraphs { + constructor(paragraphs, parent, world) { + Object.defineProperty(this, 'paragraphs', { + enumerable: false, + writable: true, + value: paragraphs, + }) + this.parent = parent + this.world = world + //'found' getter + Object.defineProperty(this, 'found', { + get: () => this.paragraphs.length > 0, + }) + //'length' getter + Object.defineProperty(this, 'length', { + get: () => this.paragraphs.length, + }) + } + } + // add our wrapper methods for Doc + wrapperMethods(Paragraphs, Doc) + + // finder method creates the sentence groups + Doc.prototype.paragraphs = function(n) { + let match = this.all() + let results = [] + let carry = [] + match.forEach(s => { + carry.push(s) + if (hasTwoNewline.test(s.post()[0])) { + results.push(carry) + carry = [] + } + }) + if (carry.length > 0) { + results.push(carry) + } + if (typeof n === 'number') { + if (results[n]) { + results = [results[n]] + } else { + results = [] + } + } + return new Paragraphs(results, this, this.world) + } +} + +module.exports = addMethods diff --git a/plugins/paragraphs/src/methods.js b/plugins/paragraphs/src/methods.js new file mode 100644 index 000000000..0960ccbd2 --- /dev/null +++ b/plugins/paragraphs/src/methods.js @@ -0,0 +1,162 @@ +const addMethods = function(Paragraphs, Doc) { + const methods = { + // return back to a regular Doc object + sentences: function(n) { + let list = [] + this.paragraphs.forEach(docs => { + docs.forEach(doc => { + list = list.concat(doc.list) + }) + }) + let doc = new Doc(list, this.parent, this.world) + if (typeof n === 'number') { + return doc.eq(n) + } + return doc + }, + + // grab every term in the paragraph + terms: function(n) { + let list = [] + this.paragraphs.forEach(docs => { + docs.forEach(doc => { + list = list.concat(doc.terms().list) + }) + }) + let doc = new Doc(list, this.parent, this.world) + if (typeof n === 'number') { + return doc.eq(n) + } + return doc + }, + + /** return metadata for each paragraph */ + json: function(options = {}) { + return this.paragraphs.map(docs => { + let text = docs.map(d => d.text()).join('') + let obj = { + text: text, + sentences: docs.map(d => d.json(options)), + } + if (options.normal) { + obj.normal = docs.map(d => d.text('normal')).join('') + } + return obj + }) + }, + + /** print out the text of each paragraph */ + text: function(options) { + let text = '' + this.paragraphs.forEach(docs => { + docs.forEach(doc => { + text += doc.text(options) + }) + }) + return text + }, + + // accessor method wrappers + eq: function(n) { + let list = [this.paragraphs[n]] + list = list.filter(l => l) + return new Paragraphs(list, this, this.world) + }, + first: function() { + return this.eq(0) + }, + last: function() { + let len = this.length + return this.eq(len - 1) + }, + debug: function() { + this.paragraphs.forEach(docs => { + console.log('\n=-=-=-=-') + docs.forEach(doc => { + doc.debug() + }) + }) + }, + + // match methods + + // returns doc objects, not paragraph objects + match: function(str) { + let list = [] + this.paragraphs.forEach(docs => { + docs.forEach(doc => { + let m = doc.match(str) + if (m.found) { + list = list.concat(m.list) + } + }) + }) + return new Doc(list, this.parent, this.world) + }, + // returns doc objects + not: function(str) { + let list = [] + this.paragraphs.forEach(docs => { + docs.forEach(doc => { + let m = doc.not(str) + if (m.found) { + list = list.concat(m.list) + } + }) + }) + return new Doc(list, this.parent, this.world) + }, + // returns paragraph objects + if: function(str) { + let list = this.paragraphs.filter(docs => { + return docs.some(doc => doc.has(str)) + }) + return new Paragraphs(list, this, this.world) + }, + ifNo: function(str) { + let list = this.paragraphs.filter(docs => { + return docs.some(doc => doc.has(str) === false) + }) + return new Paragraphs(list, this, this.world) + }, + // returns boolean + has: function(str) { + return this.paragraphs.some(docs => { + for (let i = 0; i < docs.length; i++) { + return docs[i].has(str) + } + }) + }, + + //loops + forEach: function(fn) { + this.paragraphs.forEach(docs => { + let p = new Paragraphs([docs], this, this.world) + fn(p) + }) + return this + }, + map: function(fn) { + let paragraphs = this.paragraphs.map(docs => { + let p = new Paragraphs([docs], this, this.world) + return fn(p) + }) + new Paragraphs(paragraphs, this, this.world) + }, + + //each paragraph must have atleast one sentence that matches + filter: function(fn) { + this.paragraphs = this.paragraphs.filter(docs => { + return docs.some(fn) + }) + return this + }, + } + // aliases + methods.get = methods.eq + + Object.keys(methods).forEach(k => { + Paragraphs.prototype[k] = methods[k] + }) +} +module.exports = addMethods diff --git a/plugins/paragraphs/tests/_lib.js b/plugins/paragraphs/tests/_lib.js new file mode 100644 index 000000000..254633449 --- /dev/null +++ b/plugins/paragraphs/tests/_lib.js @@ -0,0 +1,12 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + } + + module.exports = nlp +} diff --git a/plugins/paragraphs/tests/misc.test.js b/plugins/paragraphs/tests/misc.test.js new file mode 100644 index 000000000..eeb38d8ce --- /dev/null +++ b/plugins/paragraphs/tests/misc.test.js @@ -0,0 +1,30 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('paragraph-basic', function(t) { + let str = `What's with these homies dissin' my girl? Why do they gotta front? + +What did we ever do to these guys that made them so violent? + +Woo-hoo, but you know I'm yours. +Woo-hoo, and I know you're mine. +Woo-hoo, and that's for all time + ` + + let doc = nlp(str).paragraphs() + + t.equal(doc.length, 3, 'three-paragraphs') + + let m = doc.eq(0) + t.equal(m.sentences().length, 2, 'two sentences in first paragraph') + + t.equal(doc.json().length, 3, 'three-json objects') + + let one = doc.filter(p => { + return p.has('#Determiner guys') + }) + t.equal(one.length, 1, 'filter-one') + t.equal(/^What did we ever do /.test(one.text()), true, 'filter-text') + + t.end() +}) diff --git a/plugins/sentences/.gitignore b/plugins/sentences/.gitignore new file mode 100644 index 000000000..8b9247097 --- /dev/null +++ b/plugins/sentences/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +coverage/ +.DS_Store +.env +.nyc_output/ +.vscode \ No newline at end of file diff --git a/plugins/sentences/README.md b/plugins/sentences/README.md new file mode 100644 index 000000000..0095db260 --- /dev/null +++ b/plugins/sentences/README.md @@ -0,0 +1,54 @@ +
+ + +
a plugin for compromise
+ + + + + + + + + + +
+
+ +
+ npm install compromise-sentences +
+ +```js +const nlp = require('compromise') +nlp.extend(require('compromise-sentences')) + +let doc = nlp('Are you shouting boo, or boo-urns? Booo! I was saying boo-urns.') +doc.sentences().length +// 3 +``` + +### [Demo](https://observablehq.com/@spencermountain/compromise-sentences) + +### API + +- **[.sentences()](#)** - return a sentence class with additional methods + - **[.sentences().json()](#)** - overloaded output with sentence metadata + - **[.sentences().subjects()](#)** - return the main noun of each sentence + - **[.sentences().toPastTense()](#)** - `he walks` -> `he walked` + - **[.sentences().toPresentTense()](#)** - `he walked` -> `he walks` + - **[.sentences().toFutureTense()](#)** -- `he walks` -> `he will walk` + - **[.sentences().toNegative()](#)** - - `he walks` -> `he didn't walk` + - **[.sentences().toPositive()](#)** - `he doesn't walk` -> `he walks` + - **[.sentences().isPassive()](#)** - return only sentences with a passive-voice + - **[.sentences().isQuestion()](#)** - return questions with a `?` + - **[.sentences().isExclamation()](#)** - return sentences with a `!` + - **[.sentences().isStatement()](#)** - return sentences without `?` or `!` + - **[.sentences().prepend()](#)** - smarter prepend that repairs whitespace + titlecasing + - **[.sentences().append()](#)** - smarter append that repairs sentence punctuation + - **[.sentences().toExclamation()](#)** - end sentence with a `!` + - **[.sentences().toQuestion()](#)** - end sentence with a `?` + - **[.sentences().toStatement()](#)** - end sentence with a `.` + + +MIT diff --git a/plugins/sentences/builds/compromise-sentences.js b/plugins/sentences/builds/compromise-sentences.js new file mode 100644 index 000000000..5842192c4 --- /dev/null +++ b/plugins/sentences/builds/compromise-sentences.js @@ -0,0 +1,435 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseSentences = factory()); +}(this, (function () { 'use strict'; + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + // if a clause starts with these, it's not a main clause + var subordinate = "(after|although|as|because|before|if|since|than|that|though|when|whenever|where|whereas|wherever|whether|while|why|unless|until|once)"; + var relative = "(that|which|whichever|who|whoever|whom|whose|whomever)"; //try to remove secondary clauses + + var mainClause = function mainClause(og) { + var m = og.clone(true); + + if (m.length === 1) { + return m; + } // if there's no verb? + + + m = m["if"]('#Verb'); + + if (m.length === 1) { + return m; + } // this is a signal for subordinate-clauses + + + m = m.ifNo(subordinate); + m = m.ifNo('^even (if|though)'); + m = m.ifNo('^so that'); + m = m.ifNo('^rather than'); + m = m.ifNo('^provided that'); + + if (m.length === 1) { + return m; + } // relative clauses + + + m = m.ifNo(relative); + + if (m.length === 1) { + return m; + } + + m = m.ifNo('(despite|during|before|through|throughout)'); + + if (m.length === 1) { + return m; + } // did we go too far? + + + if (m.length === 0) { + m = og; + } // choose the first one? + + + return m.eq(0); + }; + + var mainClause_1 = mainClause; + + var parse = function parse(doc) { + var clauses = doc.clauses(); + var main = mainClause_1(clauses); + var nouns = main.match('#Determiner? (#Noun|#Adjective)+')["if"]('#Noun'); + var verb = main.verbs().eq(0); // match('(do|will)? not? #Verb+ not?').eq(0) + + return { + subject: nouns.eq(0), + verb: verb, + object: verb.lookAhead('.*') + }; + }; + + var parse_1 = parse; + + /** he walks -> he did not walk */ + + var toNegative = function toNegative() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toNegative(); + obj.verb.replaceWith(vb, false, true); + }); + return this; + }; + /** he doesn't walk -> he walks */ + + + var toPositive = function toPositive() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toPositive(); + obj.verb.replaceWith(vb, false, true); + }); + return this; + }; + + var negate = { + toNegative: toNegative, + toPositive: toPositive + }; + + /** return sentences ending with '?' */ + var isQuestion = function isQuestion() { + return this.filter(function (doc) { + var term = doc.lastTerm().termList(0); + return term.hasPost('?'); + }); + }; + /** return sentences ending with '!' */ + + + var isExclamation = function isExclamation() { + return this.filter(function (doc) { + var term = doc.lastTerm().termList(0); + return term.hasPost('!'); + }); + }; + /** return sentences with neither a question or an exclamation */ + + + var isStatement = function isStatement() { + return this.filter(function (doc) { + var term = doc.lastTerm().termList(0); + return !term.hasPost('?') && !term.hasPost('!'); + }); + }; + /** 'he is.' -> 'he is!' */ + + + var toExclamation = function toExclamation() { + return this; + }; + /** 'he is.' -> 'he is?' */ + + + var toQuestion = function toQuestion() { + return this; + }; + /** 'he is?' -> 'he is.' */ + + + var toStatement = function toStatement() { + return this; + }; + + var punct = { + isQuestion: isQuestion, + isExclamation: isExclamation, + isStatement: isStatement, + toExclamation: toExclamation, + toQuestion: toQuestion, + toStatement: toStatement + }; + + /** he walks -> he walked */ + + var toPastTense = function toPastTense() { + this.forEach(function (doc) { + if (doc.has('#PastTense')) { + return; + } + + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toPastTense(); + obj.verb.replaceWith(vb, false, true); // trailing gerund/future/present are okay, but 'walked and eats' is not + + if (obj.object && obj.object.found && obj.object.has('#PresentTense')) { + var verbs = obj.object.verbs(); + verbs["if"]('#PresentTense').verbs().toPastTense(); + } + }); + return this; + }; + /** he walked -> he walks */ + + + var toPresentTense = function toPresentTense() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var isPlural = obj.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found; + var vb = obj.verb.clone(); // 'i look', not 'i looks' + + if (isPlural) { + //quick hack for copula verb - be/am + if (vb.has('(is|was|am|be)')) { + vb = vb.replace('will? (is|was|am|be)', 'am'); + } else { + vb = vb.verbs().toInfinitive(); + } + } else { + //'he looks' + vb = vb.verbs().toPresentTense(); + } + + obj.verb.replaceWith(vb, false, true); // future is okay, but 'walks and ate' -> 'walks and eats' + + if (obj.object && obj.object.found && obj.object.has('#PastTense')) { + var verbs = obj.object.verbs(); + verbs["if"]('#PastTense').verbs().toPresentTense(); + } + }); + return this; + }; + /**he walked -> he will walk */ + + + var toFutureTense = function toFutureTense() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toFutureTense(); + obj.verb.replaceWith(vb, false, true); //Present is okay, but 'will walk and ate' -> 'will walk and eat' + + if (obj.object && obj.object.found && obj.object.has('(#PastTense|#PresentTense)')) { + var verbs = obj.object.verbs(); + verbs["if"]('(#PastTense|#PresentTense)').verbs().toInfinitive(); + } + }); + return this; + }; // toContinuous() { + // return this + // } + + + var tense = { + toPastTense: toPastTense, + toPresentTense: toPresentTense, + toFutureTense: toFutureTense + }; + + var methods = Object.assign({}, negate, punct, tense); + + var addMethod = function addMethod(Doc) { + /** */ + var Sentences = + /*#__PURE__*/ + function (_Doc) { + _inherits(Sentences, _Doc); + + function Sentences(list, from, world) { + _classCallCheck(this, Sentences); + + list = list.map(function (p) { + return p.clone(true); + }); + return _possibleConstructorReturn(this, _getPrototypeOf(Sentences).call(this, list, from, world)); + } + /** overload the original json with noun information */ + + + _createClass(Sentences, [{ + key: "json", + value: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var obj = parse_1(doc); + json.subject = obj.subject.json(options)[0]; + json.verb = obj.verb.json(options)[0]; + json.object = obj.object.json(options)[0]; + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + } + /** the main noun of the sentence */ + + }, { + key: "subjects", + value: function subjects() { + return this.map(function (doc) { + var res = parse_1(doc); + return res.subject; + }); + } + /** return sentences that are in passive-voice */ + + }, { + key: "isPassive", + value: function isPassive() { + return this["if"]('was #Adverb? #PastTense #Adverb? by'); //haha + } + /** add a word to the start of this sentence */ + + }, { + key: "prepend", + value: function prepend(str) { + this.forEach(function (doc) { + // repair the titlecase + var firstTerms = doc.match('^.'); + firstTerms.not('#ProperNoun').toLowerCase(); // actually add the word + + firstTerms.prepend(str); // add a titlecase + + firstTerms.terms(0).toTitleCase(); + }); + return this; + } + /** add a word to the end of this sentence */ + + }, { + key: "append", + value: function append(str) { + var hasEnd = /[.?!]\s*$/.test(str); + this.forEach(function (doc) { + var end = doc.match('.$'); + var lastTerm = end.termList(0); + var punct = lastTerm.post; + + if (hasEnd === true) { + punct = ''; + } // add punctuation to the end + + + end.append(str + punct); // remove punctuation from the former last-term + + lastTerm.post = ' '; + }); + return this; + } + }]); + + return Sentences; + }(Doc); + + Object.assign(Sentences.prototype, methods); + + Doc.prototype.sentences = function (n) { + var match = this.all(); //grab (n)th result + + if (typeof n === 'number') { + match = match.get(n); + } + + return new Sentences(match.list, this, this.world); + }; + + return Doc; + }; + + var src = addMethod; + + return src; + +}))); +//# sourceMappingURL=compromise-sentences.js.map diff --git a/plugins/sentences/builds/compromise-sentences.js.map b/plugins/sentences/builds/compromise-sentences.js.map new file mode 100644 index 000000000..54772c365 --- /dev/null +++ b/plugins/sentences/builds/compromise-sentences.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-sentences.js","sources":["../src/mainClause.js","../src/parse.js","../src/methods/negate.js","../src/methods/punct.js","../src/methods/tense.js","../src/methods/index.js","../src/index.js"],"sourcesContent":["// if a clause starts with these, it's not a main clause\nconst subordinate = `(after|although|as|because|before|if|since|than|that|though|when|whenever|where|whereas|wherever|whether|while|why|unless|until|once)`\nconst relative = `(that|which|whichever|who|whoever|whom|whose|whomever)`\n\n//try to remove secondary clauses\nconst mainClause = function(og) {\n let m = og.clone(true)\n if (m.length === 1) {\n return m\n }\n // if there's no verb?\n m = m.if('#Verb')\n if (m.length === 1) {\n return m\n }\n // this is a signal for subordinate-clauses\n m = m.ifNo(subordinate)\n m = m.ifNo('^even (if|though)')\n m = m.ifNo('^so that')\n m = m.ifNo('^rather than')\n m = m.ifNo('^provided that')\n if (m.length === 1) {\n return m\n }\n // relative clauses\n m = m.ifNo(relative)\n if (m.length === 1) {\n return m\n }\n\n m = m.ifNo('(despite|during|before|through|throughout)')\n if (m.length === 1) {\n return m\n }\n // did we go too far?\n if (m.length === 0) {\n m = og\n }\n // choose the first one?\n return m.eq(0)\n}\nmodule.exports = mainClause\n","const mainClause = require('./mainClause')\n\nconst parse = function(doc) {\n let clauses = doc.clauses()\n let main = mainClause(clauses)\n let nouns = main.match('#Determiner? (#Noun|#Adjective)+').if('#Noun')\n let verb = main.verbs().eq(0)\n // match('(do|will)? not? #Verb+ not?').eq(0)\n return {\n subject: nouns.eq(0),\n verb: verb,\n object: verb.lookAhead('.*'),\n }\n}\nmodule.exports = parse\n","const parse = require('../parse')\n\n/** he walks -> he did not walk */\nexports.toNegative = function() {\n this.forEach(doc => {\n let obj = parse(doc)\n let vb = obj.verb.clone()\n vb = vb.verbs().toNegative()\n obj.verb.replaceWith(vb, false, true)\n })\n return this\n}\n/** he doesn't walk -> he walks */\nexports.toPositive = function() {\n this.forEach(doc => {\n let obj = parse(doc)\n let vb = obj.verb.clone()\n vb = vb.verbs().toPositive()\n obj.verb.replaceWith(vb, false, true)\n })\n return this\n}\n","/** return sentences ending with '?' */\nexports.isQuestion = function() {\n return this.filter(doc => {\n let term = doc.lastTerm().termList(0)\n return term.hasPost('?')\n })\n}\n/** return sentences ending with '!' */\nexports.isExclamation = function() {\n return this.filter(doc => {\n let term = doc.lastTerm().termList(0)\n return term.hasPost('!')\n })\n}\n/** return sentences with neither a question or an exclamation */\nexports.isStatement = function() {\n return this.filter(doc => {\n let term = doc.lastTerm().termList(0)\n return !term.hasPost('?') && !term.hasPost('!')\n })\n}\n\n/** 'he is.' -> 'he is!' */\nexports.toExclamation = function() {\n return this\n}\n/** 'he is.' -> 'he is?' */\nexports.toQuestion = function() {\n return this\n}\n/** 'he is?' -> 'he is.' */\nexports.toStatement = function() {\n return this\n}\n","const parse = require('../parse')\n\n/** he walks -> he walked */\nexports.toPastTense = function() {\n this.forEach(doc => {\n if (doc.has('#PastTense')) {\n return\n }\n let obj = parse(doc)\n let vb = obj.verb.clone()\n vb = vb.verbs().toPastTense()\n obj.verb.replaceWith(vb, false, true)\n // trailing gerund/future/present are okay, but 'walked and eats' is not\n if (obj.object && obj.object.found && obj.object.has('#PresentTense')) {\n let verbs = obj.object.verbs()\n verbs\n .if('#PresentTense')\n .verbs()\n .toPastTense()\n }\n })\n return this\n}\n\n/** he walked -> he walks */\nexports.toPresentTense = function() {\n this.forEach(doc => {\n let obj = parse(doc)\n let isPlural = obj.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found\n let vb = obj.verb.clone()\n // 'i look', not 'i looks'\n if (isPlural) {\n //quick hack for copula verb - be/am\n if (vb.has('(is|was|am|be)')) {\n vb = vb.replace('will? (is|was|am|be)', 'am')\n } else {\n vb = vb.verbs().toInfinitive()\n }\n } else {\n //'he looks'\n vb = vb.verbs().toPresentTense()\n }\n obj.verb.replaceWith(vb, false, true)\n\n // future is okay, but 'walks and ate' -> 'walks and eats'\n if (obj.object && obj.object.found && obj.object.has('#PastTense')) {\n let verbs = obj.object.verbs()\n verbs\n .if('#PastTense')\n .verbs()\n .toPresentTense()\n }\n })\n return this\n}\n\n/**he walked -> he will walk */\nexports.toFutureTense = function() {\n this.forEach(doc => {\n let obj = parse(doc)\n let vb = obj.verb.clone()\n vb = vb.verbs().toFutureTense()\n obj.verb.replaceWith(vb, false, true)\n //Present is okay, but 'will walk and ate' -> 'will walk and eat'\n if (obj.object && obj.object.found && obj.object.has('(#PastTense|#PresentTense)')) {\n let verbs = obj.object.verbs()\n verbs\n .if('(#PastTense|#PresentTense)')\n .verbs()\n .toInfinitive()\n }\n })\n return this\n}\n\n// toContinuous() {\n// return this\n// }\n","module.exports = Object.assign({}, require('./negate'), require('./punct'), require('./tense'))\n","const parse = require('./parse')\nconst methods = require('./methods')\n\nconst addMethod = function(Doc) {\n /** */\n class Sentences extends Doc {\n constructor(list, from, world) {\n list = list.map(p => p.clone(true))\n super(list, from, world)\n }\n\n /** overload the original json with noun information */\n json(options) {\n let n = null\n if (typeof options === 'number') {\n n = options\n options = null\n }\n options = options || { text: true, normal: true, trim: true, terms: true }\n let res = []\n this.forEach(doc => {\n let json = doc.json(options)[0]\n let obj = parse(doc)\n json.subject = obj.subject.json(options)[0]\n json.verb = obj.verb.json(options)[0]\n json.object = obj.object.json(options)[0]\n res.push(json)\n })\n if (n !== null) {\n return res[n]\n }\n return res\n }\n\n /** the main noun of the sentence */\n subjects() {\n return this.map(doc => {\n let res = parse(doc)\n return res.subject\n })\n }\n\n /** return sentences that are in passive-voice */\n isPassive() {\n return this.if('was #Adverb? #PastTense #Adverb? by') //haha\n }\n\n /** add a word to the start of this sentence */\n prepend(str) {\n this.forEach(doc => {\n // repair the titlecase\n let firstTerms = doc.match('^.')\n firstTerms.not('#ProperNoun').toLowerCase()\n // actually add the word\n firstTerms.prepend(str)\n // add a titlecase\n firstTerms.terms(0).toTitleCase()\n })\n return this\n }\n\n /** add a word to the end of this sentence */\n append(str) {\n let hasEnd = /[.?!]\\s*$/.test(str)\n this.forEach(doc => {\n let end = doc.match('.$')\n let lastTerm = end.termList(0)\n let punct = lastTerm.post\n if (hasEnd === true) {\n punct = ''\n }\n // add punctuation to the end\n end.append(str + punct)\n // remove punctuation from the former last-term\n lastTerm.post = ' '\n })\n return this\n }\n }\n Object.assign(Sentences.prototype, methods)\n\n Doc.prototype.sentences = function(n) {\n let match = this.all()\n\n //grab (n)th result\n if (typeof n === 'number') {\n match = match.get(n)\n }\n return new Sentences(match.list, this, this.world)\n }\n return Doc\n}\nmodule.exports = addMethod\n"],"names":["subordinate","relative","mainClause","og","m","clone","length","ifNo","eq","parse","doc","clauses","main","nouns","match","verb","verbs","subject","object","lookAhead","forEach","obj","vb","toNegative","replaceWith","toPositive","filter","term","lastTerm","termList","hasPost","has","toPastTense","found","isPlural","lookBehind","replace","toInfinitive","toPresentTense","toFutureTense","Object","assign","require$$0","require$$1","require$$2","addMethod","Doc","Sentences","list","from","world","map","p","options","n","text","normal","trim","terms","res","json","push","str","firstTerms","not","toLowerCase","prepend","toTitleCase","hasEnd","test","end","punct","post","append","prototype","methods","sentences","all","get"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/sentences/builds/compromise-sentences.min.js b/plugins/sentences/builds/compromise-sentences.min.js new file mode 100644 index 000000000..40a77162a --- /dev/null +++ b/plugins/sentences/builds/compromise-sentences.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).compromiseSentences=t()}(this,(function(){"use strict";function e(e,t){for(var n=0;n he did not walk */ + +var toNegative = function toNegative() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toNegative(); + obj.verb.replaceWith(vb, false, true); + }); + return this; +}; +/** he doesn't walk -> he walks */ + + +var toPositive = function toPositive() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toPositive(); + obj.verb.replaceWith(vb, false, true); + }); + return this; +}; + +var negate = { + toNegative: toNegative, + toPositive: toPositive +}; + +/** return sentences ending with '?' */ +var isQuestion = function isQuestion() { + return this.filter(function (doc) { + var term = doc.lastTerm().termList(0); + return term.hasPost('?'); + }); +}; +/** return sentences ending with '!' */ + + +var isExclamation = function isExclamation() { + return this.filter(function (doc) { + var term = doc.lastTerm().termList(0); + return term.hasPost('!'); + }); +}; +/** return sentences with neither a question or an exclamation */ + + +var isStatement = function isStatement() { + return this.filter(function (doc) { + var term = doc.lastTerm().termList(0); + return !term.hasPost('?') && !term.hasPost('!'); + }); +}; +/** 'he is.' -> 'he is!' */ + + +var toExclamation = function toExclamation() { + return this; +}; +/** 'he is.' -> 'he is?' */ + + +var toQuestion = function toQuestion() { + return this; +}; +/** 'he is?' -> 'he is.' */ + + +var toStatement = function toStatement() { + return this; +}; + +var punct = { + isQuestion: isQuestion, + isExclamation: isExclamation, + isStatement: isStatement, + toExclamation: toExclamation, + toQuestion: toQuestion, + toStatement: toStatement +}; + +/** he walks -> he walked */ + +var toPastTense = function toPastTense() { + this.forEach(function (doc) { + if (doc.has('#PastTense')) { + return; + } + + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toPastTense(); + obj.verb.replaceWith(vb, false, true); // trailing gerund/future/present are okay, but 'walked and eats' is not + + if (obj.object && obj.object.found && obj.object.has('#PresentTense')) { + var verbs = obj.object.verbs(); + verbs["if"]('#PresentTense').verbs().toPastTense(); + } + }); + return this; +}; +/** he walked -> he walks */ + + +var toPresentTense = function toPresentTense() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var isPlural = obj.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found; + var vb = obj.verb.clone(); // 'i look', not 'i looks' + + if (isPlural) { + //quick hack for copula verb - be/am + if (vb.has('(is|was|am|be)')) { + vb = vb.replace('will? (is|was|am|be)', 'am'); + } else { + vb = vb.verbs().toInfinitive(); + } + } else { + //'he looks' + vb = vb.verbs().toPresentTense(); + } + + obj.verb.replaceWith(vb, false, true); // future is okay, but 'walks and ate' -> 'walks and eats' + + if (obj.object && obj.object.found && obj.object.has('#PastTense')) { + var verbs = obj.object.verbs(); + verbs["if"]('#PastTense').verbs().toPresentTense(); + } + }); + return this; +}; +/**he walked -> he will walk */ + + +var toFutureTense = function toFutureTense() { + this.forEach(function (doc) { + var obj = parse_1(doc); + var vb = obj.verb.clone(); + vb = vb.verbs().toFutureTense(); + obj.verb.replaceWith(vb, false, true); //Present is okay, but 'will walk and ate' -> 'will walk and eat' + + if (obj.object && obj.object.found && obj.object.has('(#PastTense|#PresentTense)')) { + var verbs = obj.object.verbs(); + verbs["if"]('(#PastTense|#PresentTense)').verbs().toInfinitive(); + } + }); + return this; +}; // toContinuous() { +// return this +// } + + +var tense = { + toPastTense: toPastTense, + toPresentTense: toPresentTense, + toFutureTense: toFutureTense +}; + +var methods = Object.assign({}, negate, punct, tense); + +var addMethod = function addMethod(Doc) { + /** */ + var Sentences = + /*#__PURE__*/ + function (_Doc) { + _inherits(Sentences, _Doc); + + function Sentences(list, from, world) { + _classCallCheck(this, Sentences); + + list = list.map(function (p) { + return p.clone(true); + }); + return _possibleConstructorReturn(this, _getPrototypeOf(Sentences).call(this, list, from, world)); + } + /** overload the original json with noun information */ + + + _createClass(Sentences, [{ + key: "json", + value: function json(options) { + var n = null; + + if (typeof options === 'number') { + n = options; + options = null; + } + + options = options || { + text: true, + normal: true, + trim: true, + terms: true + }; + var res = []; + this.forEach(function (doc) { + var json = doc.json(options)[0]; + var obj = parse_1(doc); + json.subject = obj.subject.json(options)[0]; + json.verb = obj.verb.json(options)[0]; + json.object = obj.object.json(options)[0]; + res.push(json); + }); + + if (n !== null) { + return res[n]; + } + + return res; + } + /** the main noun of the sentence */ + + }, { + key: "subjects", + value: function subjects() { + return this.map(function (doc) { + var res = parse_1(doc); + return res.subject; + }); + } + /** return sentences that are in passive-voice */ + + }, { + key: "isPassive", + value: function isPassive() { + return this["if"]('was #Adverb? #PastTense #Adverb? by'); //haha + } + /** add a word to the start of this sentence */ + + }, { + key: "prepend", + value: function prepend(str) { + this.forEach(function (doc) { + // repair the titlecase + var firstTerms = doc.match('^.'); + firstTerms.not('#ProperNoun').toLowerCase(); // actually add the word + + firstTerms.prepend(str); // add a titlecase + + firstTerms.terms(0).toTitleCase(); + }); + return this; + } + /** add a word to the end of this sentence */ + + }, { + key: "append", + value: function append(str) { + var hasEnd = /[.?!]\s*$/.test(str); + this.forEach(function (doc) { + var end = doc.match('.$'); + var lastTerm = end.termList(0); + var punct = lastTerm.post; + + if (hasEnd === true) { + punct = ''; + } // add punctuation to the end + + + end.append(str + punct); // remove punctuation from the former last-term + + lastTerm.post = ' '; + }); + return this; + } + }]); + + return Sentences; + }(Doc); + + Object.assign(Sentences.prototype, methods); + + Doc.prototype.sentences = function (n) { + var match = this.all(); //grab (n)th result + + if (typeof n === 'number') { + match = match.get(n); + } + + return new Sentences(match.list, this, this.world); + }; + + return Doc; +}; + +var src = addMethod; + +export default src; diff --git a/plugins/sentences/package-lock.json b/plugins/sentences/package-lock.json new file mode 100644 index 000000000..5faf6b2a3 --- /dev/null +++ b/plugins/sentences/package-lock.json @@ -0,0 +1,759 @@ +{ + "name": "compromise-sentences", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", + "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz", + "integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.1.tgz", + "integrity": "sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/plugins/sentences/package.json b/plugins/sentences/package.json new file mode 100644 index 000000000..c49feae9b --- /dev/null +++ b/plugins/sentences/package.json @@ -0,0 +1,47 @@ +{ + "name": "compromise-sentences", + "description": "plugin for nlp-compromise", + "version": "0.0.2", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-sentences.js", + "unpkg": "./builds/compromise-sentences.min.js", + "module": "./builds/compromise-sentences.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*" + }, + "dependencies": {}, + "devDependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/plugins/sentences/rollup.config.js b/plugins/sentences/rollup.config.js new file mode 100644 index 000000000..3bc59b8f9 --- /dev/null +++ b/plugins/sentences/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-sentences' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseSentences', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseSentences', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/sentences/src/index.js b/plugins/sentences/src/index.js new file mode 100644 index 000000000..4af34cdf7 --- /dev/null +++ b/plugins/sentences/src/index.js @@ -0,0 +1,93 @@ +const parse = require('./parse') +const methods = require('./methods') + +const addMethod = function(Doc) { + /** */ + class Sentences extends Doc { + constructor(list, from, world) { + list = list.map(p => p.clone(true)) + super(list, from, world) + } + + /** overload the original json with noun information */ + json(options) { + let n = null + if (typeof options === 'number') { + n = options + options = null + } + options = options || { text: true, normal: true, trim: true, terms: true } + let res = [] + this.forEach(doc => { + let json = doc.json(options)[0] + let obj = parse(doc) + json.subject = obj.subject.json(options)[0] + json.verb = obj.verb.json(options)[0] + json.object = obj.object.json(options)[0] + res.push(json) + }) + if (n !== null) { + return res[n] + } + return res + } + + /** the main noun of the sentence */ + subjects() { + return this.map(doc => { + let res = parse(doc) + return res.subject + }) + } + + /** return sentences that are in passive-voice */ + isPassive() { + return this.if('was #Adverb? #PastTense #Adverb? by') //haha + } + + /** add a word to the start of this sentence */ + prepend(str) { + this.forEach(doc => { + // repair the titlecase + let firstTerms = doc.match('^.') + firstTerms.not('#ProperNoun').toLowerCase() + // actually add the word + firstTerms.prepend(str) + // add a titlecase + firstTerms.terms(0).toTitleCase() + }) + return this + } + + /** add a word to the end of this sentence */ + append(str) { + let hasEnd = /[.?!]\s*$/.test(str) + this.forEach(doc => { + let end = doc.match('.$') + let lastTerm = end.termList(0) + let punct = lastTerm.post + if (hasEnd === true) { + punct = '' + } + // add punctuation to the end + end.append(str + punct) + // remove punctuation from the former last-term + lastTerm.post = ' ' + }) + return this + } + } + Object.assign(Sentences.prototype, methods) + + Doc.prototype.sentences = function(n) { + let match = this.all() + + //grab (n)th result + if (typeof n === 'number') { + match = match.get(n) + } + return new Sentences(match.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/plugins/sentences/src/mainClause.js b/plugins/sentences/src/mainClause.js new file mode 100644 index 000000000..54bd8f1da --- /dev/null +++ b/plugins/sentences/src/mainClause.js @@ -0,0 +1,42 @@ +// if a clause starts with these, it's not a main clause +const subordinate = `(after|although|as|because|before|if|since|than|that|though|when|whenever|where|whereas|wherever|whether|while|why|unless|until|once)` +const relative = `(that|which|whichever|who|whoever|whom|whose|whomever)` + +//try to remove secondary clauses +const mainClause = function(og) { + let m = og.clone(true) + if (m.length === 1) { + return m + } + // if there's no verb? + m = m.if('#Verb') + if (m.length === 1) { + return m + } + // this is a signal for subordinate-clauses + m = m.ifNo(subordinate) + m = m.ifNo('^even (if|though)') + m = m.ifNo('^so that') + m = m.ifNo('^rather than') + m = m.ifNo('^provided that') + if (m.length === 1) { + return m + } + // relative clauses + m = m.ifNo(relative) + if (m.length === 1) { + return m + } + + m = m.ifNo('(despite|during|before|through|throughout)') + if (m.length === 1) { + return m + } + // did we go too far? + if (m.length === 0) { + m = og + } + // choose the first one? + return m.eq(0) +} +module.exports = mainClause diff --git a/plugins/sentences/src/methods/index.js b/plugins/sentences/src/methods/index.js new file mode 100644 index 000000000..801cebefd --- /dev/null +++ b/plugins/sentences/src/methods/index.js @@ -0,0 +1 @@ +module.exports = Object.assign({}, require('./negate'), require('./punct'), require('./tense')) diff --git a/plugins/sentences/src/methods/negate.js b/plugins/sentences/src/methods/negate.js new file mode 100644 index 000000000..b0e9946ff --- /dev/null +++ b/plugins/sentences/src/methods/negate.js @@ -0,0 +1,22 @@ +const parse = require('../parse') + +/** he walks -> he did not walk */ +exports.toNegative = function() { + this.forEach(doc => { + let obj = parse(doc) + let vb = obj.verb.clone() + vb = vb.verbs().toNegative() + obj.verb.replaceWith(vb, false, true) + }) + return this +} +/** he doesn't walk -> he walks */ +exports.toPositive = function() { + this.forEach(doc => { + let obj = parse(doc) + let vb = obj.verb.clone() + vb = vb.verbs().toPositive() + obj.verb.replaceWith(vb, false, true) + }) + return this +} diff --git a/plugins/sentences/src/methods/punct.js b/plugins/sentences/src/methods/punct.js new file mode 100644 index 000000000..824453f9d --- /dev/null +++ b/plugins/sentences/src/methods/punct.js @@ -0,0 +1,34 @@ +/** return sentences ending with '?' */ +exports.isQuestion = function() { + return this.filter(doc => { + let term = doc.lastTerm().termList(0) + return term.hasPost('?') + }) +} +/** return sentences ending with '!' */ +exports.isExclamation = function() { + return this.filter(doc => { + let term = doc.lastTerm().termList(0) + return term.hasPost('!') + }) +} +/** return sentences with neither a question or an exclamation */ +exports.isStatement = function() { + return this.filter(doc => { + let term = doc.lastTerm().termList(0) + return !term.hasPost('?') && !term.hasPost('!') + }) +} + +/** 'he is.' -> 'he is!' */ +exports.toExclamation = function() { + return this +} +/** 'he is.' -> 'he is?' */ +exports.toQuestion = function() { + return this +} +/** 'he is?' -> 'he is.' */ +exports.toStatement = function() { + return this +} diff --git a/plugins/sentences/src/methods/tense.js b/plugins/sentences/src/methods/tense.js new file mode 100644 index 000000000..d9b7d1852 --- /dev/null +++ b/plugins/sentences/src/methods/tense.js @@ -0,0 +1,78 @@ +const parse = require('../parse') + +/** he walks -> he walked */ +exports.toPastTense = function() { + this.forEach(doc => { + if (doc.has('#PastTense')) { + return + } + let obj = parse(doc) + let vb = obj.verb.clone() + vb = vb.verbs().toPastTense() + obj.verb.replaceWith(vb, false, true) + // trailing gerund/future/present are okay, but 'walked and eats' is not + if (obj.object && obj.object.found && obj.object.has('#PresentTense')) { + let verbs = obj.object.verbs() + verbs + .if('#PresentTense') + .verbs() + .toPastTense() + } + }) + return this +} + +/** he walked -> he walks */ +exports.toPresentTense = function() { + this.forEach(doc => { + let obj = parse(doc) + let isPlural = obj.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found + let vb = obj.verb.clone() + // 'i look', not 'i looks' + if (isPlural) { + //quick hack for copula verb - be/am + if (vb.has('(is|was|am|be)')) { + vb = vb.replace('will? (is|was|am|be)', 'am') + } else { + vb = vb.verbs().toInfinitive() + } + } else { + //'he looks' + vb = vb.verbs().toPresentTense() + } + obj.verb.replaceWith(vb, false, true) + + // future is okay, but 'walks and ate' -> 'walks and eats' + if (obj.object && obj.object.found && obj.object.has('#PastTense')) { + let verbs = obj.object.verbs() + verbs + .if('#PastTense') + .verbs() + .toPresentTense() + } + }) + return this +} + +/**he walked -> he will walk */ +exports.toFutureTense = function() { + this.forEach(doc => { + let obj = parse(doc) + let vb = obj.verb.clone() + vb = vb.verbs().toFutureTense() + obj.verb.replaceWith(vb, false, true) + //Present is okay, but 'will walk and ate' -> 'will walk and eat' + if (obj.object && obj.object.found && obj.object.has('(#PastTense|#PresentTense)')) { + let verbs = obj.object.verbs() + verbs + .if('(#PastTense|#PresentTense)') + .verbs() + .toInfinitive() + } + }) + return this +} + +// toContinuous() { +// return this +// } diff --git a/plugins/sentences/src/parse.js b/plugins/sentences/src/parse.js new file mode 100644 index 000000000..c6278460d --- /dev/null +++ b/plugins/sentences/src/parse.js @@ -0,0 +1,15 @@ +const mainClause = require('./mainClause') + +const parse = function(doc) { + let clauses = doc.clauses() + let main = mainClause(clauses) + let nouns = main.match('#Determiner? (#Noun|#Adjective)+').if('#Noun') + let verb = main.verbs().eq(0) + // match('(do|will)? not? #Verb+ not?').eq(0) + return { + subject: nouns.eq(0), + verb: verb, + object: verb.lookAhead('.*'), + } +} +module.exports = parse diff --git a/plugins/sentences/tests/_lib.js b/plugins/sentences/tests/_lib.js new file mode 100644 index 000000000..254633449 --- /dev/null +++ b/plugins/sentences/tests/_lib.js @@ -0,0 +1,12 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + } + + module.exports = nlp +} diff --git a/plugins/sentences/tests/misc.test.js b/plugins/sentences/tests/misc.test.js new file mode 100644 index 000000000..bb248c508 --- /dev/null +++ b/plugins/sentences/tests/misc.test.js @@ -0,0 +1,64 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('misc sentences', function(t) { + let doc = nlp(`quickly, suddenly`) + t.equal(doc.sentences().length, 1, 'found one sentence') + + doc = nlp(`john, bill, and joe. Here we go. Must be three now.`) + t.equal(doc.sentences().length, 3, 'found three sentences') + + let d = nlp(`i am good`) + let s = d.sentences() + s.replace('am', 'was') + t.equal(d.text(), 'i was good', 'tricky map replace bug') + + t.end() +}) + +test('sentence prepend', function(t) { + let doc = nlp('He is cool.') + doc.sentences().prepend('so i think') + t.equal(doc.text(), 'So i think he is cool.', 'reset titlecase') + + doc = nlp('Spencer is cool.') + doc.sentences().prepend('yeah') + t.equal(doc.text(), 'Yeah Spencer is cool.', 'leave propernoun titlecase') + t.end() +}) + +test('sentence filters', function(t) { + let doc = nlp('He is cool? I think not. Yipeee!').sentences() + + t.equal(doc.isExclamation().length, 1, 'has-exclamation') + t.equal(doc.isQuestion().length, 1, 'has-question') + t.equal(doc.isStatement().length, 1, 'has-statement') + + t.end() +}) + +test('sentence append', function(t) { + let doc = nlp('Spencer is cool.') + doc.sentences().append('i think') + t.equal(doc.text(), 'Spencer is cool i think.', 'move period') + + doc = nlp('Spencer is cool?') + doc.sentences().append('i think') + t.equal(doc.text(), 'Spencer is cool i think?', 'move question-mark') + + doc = nlp('Spencer is cool!') + doc.sentences().append('i think') + t.equal(doc.text(), 'Spencer is cool i think!', 'move exclamation-mark') + t.end() +}) + +test('sentence append - change', function(t) { + let doc = nlp('i am cool. it is raining!') + doc.sentences().append('right?') + t.equal(doc.text(), 'i am cool right? it is raining right?', 'change ending') + + doc = nlp('it is cool? it is raining?') + doc.sentences(0).append('for sure. ') + t.equal(doc.text(), 'it is cool for sure. it is raining?', 'change ending 2') + t.end() +}) diff --git a/plugins/sentences/tests/negative.test.js b/plugins/sentences/tests/negative.test.js new file mode 100644 index 000000000..f3949a400 --- /dev/null +++ b/plugins/sentences/tests/negative.test.js @@ -0,0 +1,18 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('sentences.toPositive', function(t) { + let doc = nlp(`okay, do not use reverse psychology.`) + doc + .sentences() + .toPositive() + .toPositive() + .toPositive() + .toPositive() + t.equal(doc.text(), 'okay, do use reverse psychology.') + + // doc.sentences().toNegative() + // t.equal(doc.text(), 'okay, do not use reverse psychology.') + + t.end() +}) diff --git a/plugins/sentences/tests/svo.test.js b/plugins/sentences/tests/svo.test.js new file mode 100644 index 000000000..cebc2bafe --- /dev/null +++ b/plugins/sentences/tests/svo.test.js @@ -0,0 +1,43 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('svo parser', function(t) { + let arr = [ + ['My dog loves pizza crusts.', 'my dog', 'loves'], + ['My grey dog loves pizza crusts.', 'my grey dog', 'loves'], + ['if i can recall, my grey dog loves pizza crusts.', 'my grey dog', 'loves'], + + ['I remember what you said yesterday.', 'i', 'remember'], + ['I eat bananas in the kitchen.', 'i', 'eat'], + ['I thought what she wore was so chic.', 'i', 'thought'], + + ['In the kitchen, I eat', 'i', 'eat'], + // ['every day the kitten tries to eat the mouse', 'the kitten', 'tries to eat'], + ['smoked poutine is delicious', 'smoked poutine', 'is'], + // ["please tell me you'll address the issue", 'you', 'will address'], + + ['Every night before I go to bed, I eat bananas.', 'i', 'eat'], + + ['The store that the boy robbed is on the corner.', 'the store', 'is'], + [ + 'Diane decided to plant tomatoes in the back of the yard, where the sun blazed the longest during the day.', + 'diane', + 'decided', + ], + ['Once Adam smashed the spider, he ran into the bathroom', 'he', 'ran into'], + + // ['The boy who you saw at the store committed a robbery.', 'the boy', 'committed'], + // [ + // 'After dripping mustard all over his chest, the man who was wearing a red shirt wished that he had instead chosen ketchup for his hotdog.', + // 'the man', + // 'wished', + // ], + ] + arr.forEach(a => { + let doc = nlp(a[0]) + let obj = doc.sentences().json(0) + t.equal(obj.subject.normal, a[1], 'subject: ' + a[1]) + t.equal(obj.verb.normal, a[2], 'verb: ' + a[2]) + }) + t.end() +}) diff --git a/plugins/sentences/tests/tense.test.js b/plugins/sentences/tests/tense.test.js new file mode 100644 index 000000000..55694c293 --- /dev/null +++ b/plugins/sentences/tests/tense.test.js @@ -0,0 +1,292 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('sentence-change-tense:', function(t) { + let arr = [ + ['john walks quickly', 'john walked quickly', 'john will walk quickly'], + ['he is quick', 'he was quick', 'he will be quick'], + ['the stool falls over', 'the stool fell over', 'the stool will fall over'], + ['i usually take the stairs', 'i usually took the stairs', 'i usually will take the stairs'], + ['i usually use the stairs', 'i usually used the stairs', 'i usually will use the stairs'], + ['he finishes first', 'he finished first', 'he will finish first'], + ['our house looks great', 'our house looked great', 'our house will look great'], + //infinitives + // ['he does what he can to stop', 'he did what he could to stop', 'he will do what he can to stop'], + ['goes to sleep', 'went to sleep', 'will go to sleep'], + + //passive + // ['cardboard is made of tree fibre', 'cardboard was made of tree fibre', 'cardboard will be made of tree fibre'], + + //grammatical-number + // ['we do what we can to stop', 'we did what we could to stop', 'we will do what we can to stop'], + + //multi-sentence + [ + 'this is one sentence. This makes two now.', + 'this was one sentence. This made two now.', + 'this will be one sentence. This will make two now.', + ], + + //support negative + // ['this isn\'t one sentence. This doesn\'t make two now.', 'this was not one sentence. This didn\'t make two now.', 'this won\'t be one sentence. This won\'t make two now.'] + ] + arr.forEach(function(a) { + let r = nlp(a[0]).sentences() + + r.toPastTense() + let str = r.out('text') + t.equal(str, a[1], 'pastTense-' + str) + + r.toFutureTense() + str = r.out('text') + t.equal(str, a[2], 'futureTense-' + str) + + r.toPresentTense() + str = r.out('text') + t.equal(str, a[0], 'presentTense-' + str) + }) + t.end() +}) + +test('copula-form', function(t) { + let m = nlp('john is nice').sentences() + + m.toPastTense() + t.equal(m.out(), 'john was nice', 'toPast-1') + + m.toPresentTense() + t.equal(m.out(), 'john is nice', 'toPres-1') + + m.toFutureTense() + t.equal(m.out(), 'john will be nice', 'toFuture-1') + + m.toNegative() + t.equal(m.out(), 'john will not be nice', 'toNeg-future') + + //negative forms + m.toPastTense() + t.equal(m.out(), 'john was not nice', 'toPast-neg') + + m.toPresentTense() + t.equal(m.out(), 'john is not nice', 'toPres-neg') + + m.toFutureTense() + t.equal(m.out(), 'john will not be nice', 'toFuture-neg') + + t.end() +}) + +// +test('conjugate-form', function(t) { + let m = nlp('john walks quickly').sentences() + + m.toPastTense() + t.equal(m.out(), 'john walked quickly', 'toPast-1') + + m.toPresentTense() + t.equal(m.out(), 'john walks quickly', 'toPres-1') + + m.toFutureTense() + t.equal(m.out(), 'john will walk quickly', 'toFuture-1') + + m.toNegative() + t.equal(m.out(), 'john will not walk quickly', 'toNeg') + + //negative forms + m.toPastTense() + t.equal(m.out(), 'john did not walk quickly', 'toPast-neg') + + m.toPresentTense() + t.equal(m.out(), 'john does not walk quickly', 'toPres-neg') + + m.toFutureTense() + t.equal(m.out(), 'john will not walk quickly', 'toFuture-neg') + + t.end() +}) + +test('particle-form', function(t) { + let m = nlp('the stool falls over').sentences() + + m.toPastTense() + t.equal(m.out(), 'the stool fell over', 'toPast-1') + + m.toPresentTense() + t.equal(m.out(), 'the stool falls over', 'toPres-1') + + m.toFutureTense() + t.equal(m.out(), 'the stool will fall over', 'toFuture-1') + + m.toNegative() + t.equal(m.out(), 'the stool will not fall over', 'toNeg') + + //negative forms + m.toPastTense() + t.equal(m.out(), 'the stool did not fall over', 'toPast-neg') + + m.toPresentTense() + t.equal(m.out(), 'the stool does not fall over', 'toPres-neg') + + m.toFutureTense() + t.equal(m.out(), 'the stool will not fall over', 'toFuture-neg') + + t.end() +}) + +test('contraction-cases', function(t) { + let arr = [ + [`I'm going to the shops`, `I went to the shops`], + [`I'll go to the shops`, `I went to the shops`], + ] + arr.forEach(a => { + let str = nlp(a[0]) + .sentences() + .toPastTense() + .out() + t.equal(str, a[1], 'past-tense ' + a.join(' - ')) + }) + arr = [ + [`We're looking`, `We looked`], + [`We'll look`, `We looked`], + [`We are looking`, `We looked`], + ] + arr.forEach(a => { + let str = nlp(a[0]) + .sentences() + .toPastTense() + .out() + t.equal(str, a[1], 'past-tense ' + a.join(' - ')) + }) + arr = [ + [`I'm going to the shops`, `I will go to the shops`], + [`I'll go to the shops`, `I will go to the shops`], + ] + arr.forEach(a => { + let str = nlp(a[0]) + .sentences() + .toFutureTense() + .out() + t.equal(str, a[1], 'future-tense ' + a.join(' - ')) + }) + arr = [ + [`I'm going to the shops`, `I go to the shops`], + [`I'll go to the shops`, `I go to the shops`], + ] + arr.forEach(a => { + let str = nlp(a[0]) + .sentences() + .toPresentTense() + .out() + t.equal(str, a[1], 'present-tense ' + a.join(' - ')) + }) + arr = [ + [`I'm looking for a bug`, `I look for a bug`], + [`I'll look for a bug`, `I look for a bug`], + ] + arr.forEach(a => { + let str = nlp(a[0]) + .sentences() + .toPresentTense() + .out() + t.equal(str, a[1], 'present-tense ' + a.join(' - ')) + }) + // let str = nlp('I’m lookin’ for Amanda Hugginkiss') + // .sentences() + // .toPastTense() + // .out() + // t.equal(str, 'i looked for Amanda Hugginkiss', 'present-tense slang') + t.end() +}) + +test('pronoun-specific', function(t) { + //from present + let m = nlp('i am cool') + .sentences() + .toPresentTense() + t.equal(m.out(), 'i am cool', 'toPresent-I') + m = nlp('i am cool') + .sentences() + .toPastTense() + t.equal(m.out(), 'i was cool', 'toPastTense-I') + m = nlp('i am cool') + .sentences() + .toFutureTense() + t.equal(m.out(), 'i will be cool', 'toFutureTense-I') + + //from future + m = nlp('i will be cool') + .sentences() + .toFutureTense() + t.equal(m.out(), 'i will be cool', 'toFutureTense-I-2') + m = nlp('i will be cool') + .sentences() + .toPastTense() + t.equal(m.out(), 'i was cool', 'toPastTense-I-2') + m = nlp('i will be cool') + .sentences() + .toPresentTense() + t.equal(m.out(), 'i am cool', 'toPresentTense-I-2') + + //from past + m = nlp('i was cool') + .sentences() + .toPresentTense() + t.equal(m.out(), 'i am cool', 'toPresentTense-I-3') + m = nlp('i was cool') + .sentences() + .toPastTense() + t.equal(m.out(), 'i was cool', 'toPastTense-I-3') + m = nlp('i was cool') + .sentences() + .toFutureTense() + t.equal(m.out(), 'i will be cool', 'toFutureTense-I-3') + + //with negative + m = nlp('i was not cool') + .sentences() + .toPresentTense() + t.equal(m.out(), 'i am not cool', 'neg-1') + m = nlp("i wasn't cool") + .sentences() + .toPastTense() + t.equal(m.out(), "i wasn't cool", 'neg-2') + m = nlp('i was not cool') + .sentences() + .toFutureTense() + t.equal(m.out(), 'i will not be cool', 'neg-3') + + //with adverbs + m = nlp('i was really cool') + .sentences() + .toPresentTense() + t.equal(m.out(), 'i am really cool', 'toPresentTense-I-3') + m = nlp('i was really cool') + .sentences() + .toPastTense() + t.equal(m.out(), 'i was really cool', 'toPastTense-I-3') + m = nlp('i was really cool') + .sentences() + .toFutureTense() + t.equal(m.out(), 'i will be really cool', 'toFutureTense-I-3') + t.end() +}) + +test('tense-multiple', function(t) { + let doc = nlp(`he walks down the street and smells the flowers.`) + doc.sentences().toPastTense() + t.equal(doc.text(), 'he walked down the street and smelled the flowers.', 'to-past') + + doc = nlp(`he walked down the street and smelled the flowers.`) + doc.sentences().toPresentTense() + t.equal(doc.text(), 'he walks down the street and smells the flowers.', 'to-pres') + + // past + doc = nlp(`he walked down the street and smelled the flowers.`) + doc.sentences().toFutureTense() + t.equal(doc.text(), 'he will walk down the street and smell the flowers.', 'past-1') + // past-two + doc = nlp(`he walks down the street and smells the flowers.`) + doc.sentences().toFutureTense() + t.equal(doc.text(), 'he will walk down the street and smell the flowers.', 'past-2') + t.end() +}) diff --git a/plugins/syllables/.gitignore b/plugins/syllables/.gitignore new file mode 100644 index 000000000..8b9247097 --- /dev/null +++ b/plugins/syllables/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +coverage/ +.DS_Store +.env +.nyc_output/ +.vscode \ No newline at end of file diff --git a/plugins/syllables/README.md b/plugins/syllables/README.md new file mode 100644 index 000000000..c5c0c7006 --- /dev/null +++ b/plugins/syllables/README.md @@ -0,0 +1,46 @@ +
+ + +
a plugin for compromise
+ + + + + + + + + + +
+
+ +This is a naive syllable tokenizer, and simply splits a compromise document, according to some simple, biased interpretation. + +It makes some judgement-calls about pronunciation, but also where splits make the most sense. + +
+ npm install compromise-syllables +
+ +

+ Demo +

+ +```js +const nlp = require('compromise') +nlp.extend(require('compromise-syllables')) + +let doc = nlp('Chocolate microscopes?') +doc.terms().syllables() +/*[ + {text:'Chocolate', syllables:['cho', 'co', 'late']}, + {text:'microscopes?', syllables:['mic', 'ro', 'scope']} +]*/ +``` + +`.syllables( {options} )` will pass it's optional first parameter to `.json()`. You can see the full set of options [here](https://observablehq.com/@spencermountain/compromise-json). + +Keep in mind there are cultural-differences in syllable pronunciation, which this library has a certain bias. + +MIT diff --git a/plugins/syllables/builds/compromise-syllables.js b/plugins/syllables/builds/compromise-syllables.js new file mode 100644 index 000000000..9bfa8b043 --- /dev/null +++ b/plugins/syllables/builds/compromise-syllables.js @@ -0,0 +1,230 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.compromiseSyllables = factory()); +}(this, (function () { 'use strict'; + + var starts_with_single_vowel_combos = /^(eu)/i; + var joining_consonant_vowel = /^[^aeiou][e]([^d]|$)/; + var cvcv_same_consonant = /^([^aeiouy])[aeiouy]\1[aeiouy]/; + var cvcv_same_vowel = /^[^aeiouy]([aeiouy])[^aeiouy]\1/; + var cvcv_known_consonants = /^([tg][aeiouy]){2}/; + var only_one_or_more_c = /^[^aeiouy]+$/; + var ends_with_vowel = /[aeiouy]$/; + var starts_with_consonant_vowel = /^[^aeiouy][h]?[aeiouy]/; + var ones = [/^[^aeiou]?ion/, /^[^aeiou]?ised/, /^[^aeiou]?iled/, // -ing, -ent + /[aeiou][n][gt]$/, // -ate, -age + /\wa[gt]e$/]; //suffix fixes + + var postprocess = function postprocess(arr) { + //trim whitespace + arr = arr.map(function (w) { + return w.trim(); + }); + arr = arr.filter(function (w) { + return w !== ''; + }); // if (arr.length > 2) { + // return arr; + // } + + var l = arr.length; + + if (l > 1) { + var suffix = arr[l - 2] + arr[l - 1]; + + for (var i = 0; i < ones.length; i++) { + if (suffix.match(ones[i])) { + arr[l - 2] = arr[l - 2] + arr[l - 1]; + arr.pop(); + } + } + } // since the open syllable detection is overzealous, + // sometimes need to rejoin incorrect splits + + + if (arr.length > 1) { + var first_is_open = (arr[0].length === 1 || arr[0].match(starts_with_consonant_vowel)) && arr[0].match(ends_with_vowel); + var second_is_joining = arr[1].match(joining_consonant_vowel); + + if (first_is_open && second_is_joining) { + var possible_combination = arr[0] + arr[1]; + var probably_separate_syllables = possible_combination.match(cvcv_same_consonant) || possible_combination.match(cvcv_same_vowel) || possible_combination.match(cvcv_known_consonants); + + if (!probably_separate_syllables) { + arr[0] = arr[0] + arr[1]; + arr.splice(1, 1); + } + } + } + + if (arr.length > 1) { + var second_to_last_is_open = arr[arr.length - 2].match(starts_with_consonant_vowel) && arr[arr.length - 2].match(ends_with_vowel); + var last_is_joining = arr[arr.length - 1].match(joining_consonant_vowel) && ones.every(function (re) { + return !arr[arr.length - 1].match(re); + }); + + if (second_to_last_is_open && last_is_joining) { + var _possible_combination = arr[arr.length - 2] + arr[arr.length - 1]; + + var _probably_separate_syllables = _possible_combination.match(cvcv_same_consonant) || _possible_combination.match(cvcv_same_vowel) || _possible_combination.match(cvcv_known_consonants); + + if (!_probably_separate_syllables) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]; + arr.splice(arr.length - 1, 1); + } + } + } + + if (arr.length > 1) { + var single = arr[0] + arr[1]; + + if (single.match(starts_with_single_vowel_combos)) { + arr[0] = single; + arr.splice(1, 1); + } + } + + if (arr.length > 1) { + if (arr[arr.length - 1].match(only_one_or_more_c)) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]; + arr.splice(arr.length - 1, 1); + } + } + + return arr; + }; + + var postProcess = postprocess; + + var all_spaces = / +/g; + var ends_with_vowel$1 = /[aeiouy]$/; + var starts_with_consonant_vowel$1 = /^[^aeiouy][h]?[aeiouy]/; + var starts_with_e_then_specials = /^e[sm]/; + var starts_with_e = /^e/; + var ends_with_noisy_vowel_combos = /(eo|eu|ia|oa|ua|ui)$/i; + var aiouy = /[aiouy]/; + var ends_with_ee = /ee$/; // const whitespace_dash = /\s\-/ + //method is nested because it's called recursively + + var doWord = function doWord(w) { + var all = []; + var chars = w.split(''); + var before = ''; + var after = ''; + var current = ''; + + for (var i = 0; i < chars.length; i++) { + before = chars.slice(0, i).join(''); + current = chars[i]; + after = chars.slice(i + 1, chars.length).join(''); + var candidate = before + chars[i]; //it's a consonant that comes after a vowel + + if (before.match(ends_with_vowel$1) && !current.match(ends_with_vowel$1)) { + if (after.match(starts_with_e_then_specials)) { + candidate += 'e'; + after = after.replace(starts_with_e, ''); + } + + all.push(candidate); + return all.concat(doWord(after)); + } //unblended vowels ('noisy' vowel combinations) + + + if (candidate.match(ends_with_noisy_vowel_combos)) { + //'io' is noisy, not in 'ion' + all.push(before); + all.push(current); + return all.concat(doWord(after)); //recursion + } // if candidate is followed by a CV, assume consecutive open syllables + + + if (candidate.match(ends_with_vowel$1) && after.match(starts_with_consonant_vowel$1)) { + all.push(candidate); + return all.concat(doWord(after)); + } + } //if still running, end last syllable + + + if (w.match(aiouy) || w.match(ends_with_ee)) { + //allow silent trailing e + all.push(w); + } else if (w) { + var last = all.length - 1; + + if (last < 0) { + last = 0; + } + + all[last] = (all[last] || '') + w; //append it to the last one + } + + return all; + }; + + var syllables = function syllables(str) { + var all = []; + + if (!str) { + return all; + } + + str = str.replace(/[.,?]/g, ''); + str.split(all_spaces).map(function (s) { + all = all.concat(doWord(s)); + }); // str.split(whitespace_dash).forEach(doWord) + + all = postProcess(all); //for words like 'tree' and 'free' + + if (all.length === 0) { + all = [str]; + } //filter blanks + + + all = all.filter(function (s) { + return s; + }); + return all; + }; // console.log(syllables('civilised')) + + + var syllables_1 = syllables; + + var defaultObj = { + normal: true, + text: true, + terms: false + }; + + var addMethod = function addMethod(Doc) { + /** split each term by typical pronounciation */ + Doc.prototype.syllables = function (obj) { + var n = null; + + if (typeof obj === 'number') { + n = obj; + obj = {}; + } + + var data = this.json(obj || defaultObj); //add syllable data to each phrase + + data = data.map(function (o) { + o.syllables = syllables_1(o.normal || o.text); + return o; + }); + + if (typeof n === 'number') { + data = data[n]; + } + + return data; + }; + + return Doc; + }; + + var src = addMethod; + + return src; + +}))); +//# sourceMappingURL=compromise-syllables.js.map diff --git a/plugins/syllables/builds/compromise-syllables.js.map b/plugins/syllables/builds/compromise-syllables.js.map new file mode 100644 index 000000000..11d6d3513 --- /dev/null +++ b/plugins/syllables/builds/compromise-syllables.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compromise-syllables.js","sources":["../src/postProcess.js","../src/syllables.js","../src/index.js"],"sourcesContent":["const starts_with_single_vowel_combos = /^(eu)/i\nconst joining_consonant_vowel = /^[^aeiou][e]([^d]|$)/\nconst cvcv_same_consonant = /^([^aeiouy])[aeiouy]\\1[aeiouy]/\nconst cvcv_same_vowel = /^[^aeiouy]([aeiouy])[^aeiouy]\\1/\nconst cvcv_known_consonants = /^([tg][aeiouy]){2}/\nconst only_one_or_more_c = /^[^aeiouy]+$/\n\nconst ends_with_vowel = /[aeiouy]$/\nconst starts_with_consonant_vowel = /^[^aeiouy][h]?[aeiouy]/\n\nconst ones = [\n /^[^aeiou]?ion/,\n /^[^aeiou]?ised/,\n /^[^aeiou]?iled/,\n\n // -ing, -ent\n /[aeiou][n][gt]$/,\n\n // -ate, -age\n /\\wa[gt]e$/,\n]\n\n//suffix fixes\nconst postprocess = function(arr) {\n //trim whitespace\n arr = arr.map(function(w) {\n return w.trim()\n })\n arr = arr.filter(function(w) {\n return w !== ''\n })\n // if (arr.length > 2) {\n // return arr;\n // }\n let l = arr.length\n if (l > 1) {\n let suffix = arr[l - 2] + arr[l - 1]\n for (let i = 0; i < ones.length; i++) {\n if (suffix.match(ones[i])) {\n arr[l - 2] = arr[l - 2] + arr[l - 1]\n arr.pop()\n }\n }\n }\n\n // since the open syllable detection is overzealous,\n // sometimes need to rejoin incorrect splits\n if (arr.length > 1) {\n let first_is_open =\n (arr[0].length === 1 || arr[0].match(starts_with_consonant_vowel)) &&\n arr[0].match(ends_with_vowel)\n let second_is_joining = arr[1].match(joining_consonant_vowel)\n\n if (first_is_open && second_is_joining) {\n let possible_combination = arr[0] + arr[1]\n let probably_separate_syllables =\n possible_combination.match(cvcv_same_consonant) ||\n possible_combination.match(cvcv_same_vowel) ||\n possible_combination.match(cvcv_known_consonants)\n\n if (!probably_separate_syllables) {\n arr[0] = arr[0] + arr[1]\n arr.splice(1, 1)\n }\n }\n }\n\n if (arr.length > 1) {\n let second_to_last_is_open =\n arr[arr.length - 2].match(starts_with_consonant_vowel) &&\n arr[arr.length - 2].match(ends_with_vowel)\n let last_is_joining =\n arr[arr.length - 1].match(joining_consonant_vowel) &&\n ones.every(re => !arr[arr.length - 1].match(re))\n\n if (second_to_last_is_open && last_is_joining) {\n let possible_combination = arr[arr.length - 2] + arr[arr.length - 1]\n let probably_separate_syllables =\n possible_combination.match(cvcv_same_consonant) ||\n possible_combination.match(cvcv_same_vowel) ||\n possible_combination.match(cvcv_known_consonants)\n\n if (!probably_separate_syllables) {\n arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]\n arr.splice(arr.length - 1, 1)\n }\n }\n }\n\n if (arr.length > 1) {\n let single = arr[0] + arr[1]\n if (single.match(starts_with_single_vowel_combos)) {\n arr[0] = single\n arr.splice(1, 1)\n }\n }\n\n if (arr.length > 1) {\n if (arr[arr.length - 1].match(only_one_or_more_c)) {\n arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]\n arr.splice(arr.length - 1, 1)\n }\n }\n\n return arr\n}\nmodule.exports = postprocess\n","//chop a string into pronounced syllables\nconst postProcess = require('./postProcess')\n\nconst all_spaces = / +/g\nconst ends_with_vowel = /[aeiouy]$/\nconst starts_with_consonant_vowel = /^[^aeiouy][h]?[aeiouy]/\nconst starts_with_e_then_specials = /^e[sm]/\nconst starts_with_e = /^e/\nconst ends_with_noisy_vowel_combos = /(eo|eu|ia|oa|ua|ui)$/i\nconst aiouy = /[aiouy]/\nconst ends_with_ee = /ee$/\n// const whitespace_dash = /\\s\\-/\n\n//method is nested because it's called recursively\nconst doWord = function(w) {\n let all = []\n let chars = w.split('')\n let before = ''\n let after = ''\n let current = ''\n for (let i = 0; i < chars.length; i++) {\n before = chars.slice(0, i).join('')\n current = chars[i]\n after = chars.slice(i + 1, chars.length).join('')\n let candidate = before + chars[i]\n\n //it's a consonant that comes after a vowel\n if (before.match(ends_with_vowel) && !current.match(ends_with_vowel)) {\n if (after.match(starts_with_e_then_specials)) {\n candidate += 'e'\n after = after.replace(starts_with_e, '')\n }\n all.push(candidate)\n return all.concat(doWord(after))\n }\n\n //unblended vowels ('noisy' vowel combinations)\n if (candidate.match(ends_with_noisy_vowel_combos)) {\n //'io' is noisy, not in 'ion'\n all.push(before)\n all.push(current)\n return all.concat(doWord(after)) //recursion\n }\n\n // if candidate is followed by a CV, assume consecutive open syllables\n if (candidate.match(ends_with_vowel) && after.match(starts_with_consonant_vowel)) {\n all.push(candidate)\n return all.concat(doWord(after))\n }\n }\n //if still running, end last syllable\n if (w.match(aiouy) || w.match(ends_with_ee)) {\n //allow silent trailing e\n all.push(w)\n } else if (w) {\n let last = all.length - 1\n if (last < 0) {\n last = 0\n }\n all[last] = (all[last] || '') + w //append it to the last one\n }\n return all\n}\n\nlet syllables = function(str) {\n let all = []\n if (!str) {\n return all\n }\n str = str.replace(/[.,?]/g, '')\n str.split(all_spaces).map(s => {\n all = all.concat(doWord(s))\n })\n\n // str.split(whitespace_dash).forEach(doWord)\n all = postProcess(all)\n\n //for words like 'tree' and 'free'\n if (all.length === 0) {\n all = [str]\n }\n //filter blanks\n all = all.filter(s => s)\n\n return all\n}\n\n// console.log(syllables('civilised'))\n\nmodule.exports = syllables\n","const getSyllables = require('./syllables')\n\nconst defaultObj = { normal: true, text: true, terms: false }\n\nconst addMethod = function(Doc) {\n /** split each term by typical pronounciation */\n Doc.prototype.syllables = function(obj) {\n let n = null\n if (typeof obj === 'number') {\n n = obj\n obj = {}\n }\n let data = this.json(obj || defaultObj)\n //add syllable data to each phrase\n data = data.map(o => {\n o.syllables = getSyllables(o.normal || o.text)\n return o\n })\n if (typeof n === 'number') {\n data = data[n]\n }\n return data\n }\n\n return Doc\n}\nmodule.exports = addMethod\n"],"names":["starts_with_single_vowel_combos","joining_consonant_vowel","cvcv_same_consonant","cvcv_same_vowel","cvcv_known_consonants","only_one_or_more_c","ends_with_vowel","starts_with_consonant_vowel","ones","postprocess","arr","map","w","trim","filter","l","length","suffix","i","match","pop","first_is_open","second_is_joining","possible_combination","probably_separate_syllables","splice","second_to_last_is_open","last_is_joining","every","re","single","all_spaces","starts_with_e_then_specials","starts_with_e","ends_with_noisy_vowel_combos","aiouy","ends_with_ee","doWord","all","chars","split","before","after","current","slice","join","candidate","replace","push","concat","last","syllables","str","s","postProcess","defaultObj","normal","text","terms","addMethod","Doc","prototype","obj","n","data","json","o","getSyllables"],"mappings":"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"} \ No newline at end of file diff --git a/plugins/syllables/builds/compromise-syllables.min.js b/plugins/syllables/builds/compromise-syllables.min.js new file mode 100644 index 000000000..314455918 --- /dev/null +++ b/plugins/syllables/builds/compromise-syllables.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).compromiseSyllables=t()}(this,(function(){"use strict";var e=/^(eu)/i,t=/^[^aeiou][e]([^d]|$)/,n=/^([^aeiouy])[aeiouy]\1[aeiouy]/,a=/^[^aeiouy]([aeiouy])[^aeiouy]\1/,i=/^([tg][aeiouy]){2}/,u=/^[^aeiouy]+$/,o=/[aeiouy]$/,r=/^[^aeiouy][h]?[aeiouy]/,h=[/^[^aeiou]?ion/,/^[^aeiou]?ised/,/^[^aeiou]?iled/,/[aeiou][n][gt]$/,/\wa[gt]e$/],c=function(c){var l=(c=(c=c.map((function(e){return e.trim()}))).filter((function(e){return""!==e}))).length;if(l>1)for(var f=c[l-2]+c[l-1],m=0;m1){var g=(1===c[0].length||c[0].match(r))&&c[0].match(o),s=c[1].match(t);if(g&&s){var p=c[0]+c[1];p.match(n)||p.match(a)||p.match(i)||(c[0]=c[0]+c[1],c.splice(1,1))}}if(c.length>1){var y=c[c.length-2].match(r)&&c[c.length-2].match(o),v=c[c.length-1].match(t)&&h.every((function(e){return!c[c.length-1].match(e)}));if(y&&v){var d=c[c.length-2]+c[c.length-1];d.match(n)||d.match(a)||d.match(i)||(c[c.length-2]=c[c.length-2]+c[c.length-1],c.splice(c.length-1,1))}}if(c.length>1){var $=c[0]+c[1];$.match(e)&&(c[0]=$,c.splice(1,1))}return c.length>1&&c[c.length-1].match(u)&&(c[c.length-2]=c[c.length-2]+c[c.length-1],c.splice(c.length-1,1)),c},l=/ +/g,f=/[aeiouy]$/,m=/^[^aeiouy][h]?[aeiouy]/,g=/^e[sm]/,s=/^e/,p=/(eo|eu|ia|oa|ua|ui)$/i,y=/[aiouy]/,v=/ee$/,d=function(e){var t=[];return e?((e=e.replace(/[.,?]/g,"")).split(l).map((function(e){t=t.concat(function e(t){for(var n=[],a=t.split(""),i="",u="",o="",r=0;r 2) { + // return arr; + // } + + var l = arr.length; + + if (l > 1) { + var suffix = arr[l - 2] + arr[l - 1]; + + for (var i = 0; i < ones.length; i++) { + if (suffix.match(ones[i])) { + arr[l - 2] = arr[l - 2] + arr[l - 1]; + arr.pop(); + } + } + } // since the open syllable detection is overzealous, + // sometimes need to rejoin incorrect splits + + + if (arr.length > 1) { + var first_is_open = (arr[0].length === 1 || arr[0].match(starts_with_consonant_vowel)) && arr[0].match(ends_with_vowel); + var second_is_joining = arr[1].match(joining_consonant_vowel); + + if (first_is_open && second_is_joining) { + var possible_combination = arr[0] + arr[1]; + var probably_separate_syllables = possible_combination.match(cvcv_same_consonant) || possible_combination.match(cvcv_same_vowel) || possible_combination.match(cvcv_known_consonants); + + if (!probably_separate_syllables) { + arr[0] = arr[0] + arr[1]; + arr.splice(1, 1); + } + } + } + + if (arr.length > 1) { + var second_to_last_is_open = arr[arr.length - 2].match(starts_with_consonant_vowel) && arr[arr.length - 2].match(ends_with_vowel); + var last_is_joining = arr[arr.length - 1].match(joining_consonant_vowel) && ones.every(function (re) { + return !arr[arr.length - 1].match(re); + }); + + if (second_to_last_is_open && last_is_joining) { + var _possible_combination = arr[arr.length - 2] + arr[arr.length - 1]; + + var _probably_separate_syllables = _possible_combination.match(cvcv_same_consonant) || _possible_combination.match(cvcv_same_vowel) || _possible_combination.match(cvcv_known_consonants); + + if (!_probably_separate_syllables) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]; + arr.splice(arr.length - 1, 1); + } + } + } + + if (arr.length > 1) { + var single = arr[0] + arr[1]; + + if (single.match(starts_with_single_vowel_combos)) { + arr[0] = single; + arr.splice(1, 1); + } + } + + if (arr.length > 1) { + if (arr[arr.length - 1].match(only_one_or_more_c)) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]; + arr.splice(arr.length - 1, 1); + } + } + + return arr; +}; + +var postProcess = postprocess; + +var all_spaces = / +/g; +var ends_with_vowel$1 = /[aeiouy]$/; +var starts_with_consonant_vowel$1 = /^[^aeiouy][h]?[aeiouy]/; +var starts_with_e_then_specials = /^e[sm]/; +var starts_with_e = /^e/; +var ends_with_noisy_vowel_combos = /(eo|eu|ia|oa|ua|ui)$/i; +var aiouy = /[aiouy]/; +var ends_with_ee = /ee$/; // const whitespace_dash = /\s\-/ +//method is nested because it's called recursively + +var doWord = function doWord(w) { + var all = []; + var chars = w.split(''); + var before = ''; + var after = ''; + var current = ''; + + for (var i = 0; i < chars.length; i++) { + before = chars.slice(0, i).join(''); + current = chars[i]; + after = chars.slice(i + 1, chars.length).join(''); + var candidate = before + chars[i]; //it's a consonant that comes after a vowel + + if (before.match(ends_with_vowel$1) && !current.match(ends_with_vowel$1)) { + if (after.match(starts_with_e_then_specials)) { + candidate += 'e'; + after = after.replace(starts_with_e, ''); + } + + all.push(candidate); + return all.concat(doWord(after)); + } //unblended vowels ('noisy' vowel combinations) + + + if (candidate.match(ends_with_noisy_vowel_combos)) { + //'io' is noisy, not in 'ion' + all.push(before); + all.push(current); + return all.concat(doWord(after)); //recursion + } // if candidate is followed by a CV, assume consecutive open syllables + + + if (candidate.match(ends_with_vowel$1) && after.match(starts_with_consonant_vowel$1)) { + all.push(candidate); + return all.concat(doWord(after)); + } + } //if still running, end last syllable + + + if (w.match(aiouy) || w.match(ends_with_ee)) { + //allow silent trailing e + all.push(w); + } else if (w) { + var last = all.length - 1; + + if (last < 0) { + last = 0; + } + + all[last] = (all[last] || '') + w; //append it to the last one + } + + return all; +}; + +var syllables = function syllables(str) { + var all = []; + + if (!str) { + return all; + } + + str = str.replace(/[.,?]/g, ''); + str.split(all_spaces).map(function (s) { + all = all.concat(doWord(s)); + }); // str.split(whitespace_dash).forEach(doWord) + + all = postProcess(all); //for words like 'tree' and 'free' + + if (all.length === 0) { + all = [str]; + } //filter blanks + + + all = all.filter(function (s) { + return s; + }); + return all; +}; // console.log(syllables('civilised')) + + +var syllables_1 = syllables; + +var defaultObj = { + normal: true, + text: true, + terms: false +}; + +var addMethod = function addMethod(Doc) { + /** split each term by typical pronounciation */ + Doc.prototype.syllables = function (obj) { + var n = null; + + if (typeof obj === 'number') { + n = obj; + obj = {}; + } + + var data = this.json(obj || defaultObj); //add syllable data to each phrase + + data = data.map(function (o) { + o.syllables = syllables_1(o.normal || o.text); + return o; + }); + + if (typeof n === 'number') { + data = data[n]; + } + + return data; + }; + + return Doc; +}; + +var src = addMethod; + +export default src; diff --git a/plugins/syllables/builds/compromise-verbs.min.js b/plugins/syllables/builds/compromise-verbs.min.js new file mode 100644 index 000000000..5b7cfb5ce --- /dev/null +++ b/plugins/syllables/builds/compromise-verbs.min.js @@ -0,0 +1 @@ +"use strict";const starts_with_single_vowel_combos=/^(eu)/i,joining_consonant_vowel=/^[^aeiou][e]([^d]|$)/,cvcv_same_consonant=/^([^aeiouy])[aeiouy]\1[aeiouy]/,cvcv_same_vowel=/^[^aeiouy]([aeiouy])[^aeiouy]\1/,cvcv_known_consonants=/^([tg][aeiouy]){2}/,only_one_or_more_c=/^[^aeiouy]+$/,ends_with_vowel=/[aeiouy]$/,starts_with_consonant_vowel=/^[^aeiouy][h]?[aeiouy]/,ones=[/^[^aeiou]?ion/,/^[^aeiou]?ised/,/^[^aeiou]?iled/,/[aeiou][n][gt]$/,/\wa[gt]e$/],postprocess=function(e){let t=(e=(e=e.map((function(e){return e.trim()}))).filter((function(e){return""!==e}))).length;if(t>1){let o=e[t-2]+e[t-1];for(let n=0;n1){let t=(1===e[0].length||e[0].match(starts_with_consonant_vowel))&&e[0].match(ends_with_vowel),o=e[1].match(joining_consonant_vowel);if(t&&o){let t=e[0]+e[1];t.match(cvcv_same_consonant)||t.match(cvcv_same_vowel)||t.match(cvcv_known_consonants)||(e[0]=e[0]+e[1],e.splice(1,1))}}if(e.length>1){let t=e[e.length-2].match(starts_with_consonant_vowel)&&e[e.length-2].match(ends_with_vowel),o=e[e.length-1].match(joining_consonant_vowel)&&ones.every(t=>!e[e.length-1].match(t));if(t&&o){let t=e[e.length-2]+e[e.length-1];t.match(cvcv_same_consonant)||t.match(cvcv_same_vowel)||t.match(cvcv_known_consonants)||(e[e.length-2]=e[e.length-2]+e[e.length-1],e.splice(e.length-1,1))}}if(e.length>1){let t=e[0]+e[1];t.match(starts_with_single_vowel_combos)&&(e[0]=t,e.splice(1,1))}return e.length>1&&e[e.length-1].match(only_one_or_more_c)&&(e[e.length-2]=e[e.length-2]+e[e.length-1],e.splice(e.length-1,1)),e};var postProcess=postprocess;const all_spaces=/ +/g,ends_with_vowel$1=/[aeiouy]$/,starts_with_consonant_vowel$1=/^[^aeiouy][h]?[aeiouy]/,starts_with_e_then_specials=/^e[sm]/,starts_with_e=/^e/,ends_with_noisy_vowel_combos=/(eo|eu|ia|oa|ua|ui)$/i,aiouy=/[aiouy]/,ends_with_ee=/ee$/,doWord=function(e){let t=[],o=e.split(""),n="",s="",a="";for(let e=0;e{t=t.concat(doWord(e))}),0===(t=postProcess(t)).length&&(t=[e]),t=t.filter(e=>e)):t};var syllables_1=syllables;const defaultObj={normal:!0,text:!0,terms:!1},addMethod=function(e){return e.prototype.syllables=function(e,t){let o=this.data(t||defaultObj);return o=o.map(e=>(e.syllables=syllables_1(e.normal||e.text),e)),"number"==typeof e&&(o=o[e]),o},e};var src=addMethod;module.exports=src; diff --git a/plugins/syllables/builds/compromise-verbs.mjs b/plugins/syllables/builds/compromise-verbs.mjs new file mode 100644 index 000000000..cad5235da --- /dev/null +++ b/plugins/syllables/builds/compromise-verbs.mjs @@ -0,0 +1,219 @@ +const starts_with_single_vowel_combos = /^(eu)/i; +const joining_consonant_vowel = /^[^aeiou][e]([^d]|$)/; +const cvcv_same_consonant = /^([^aeiouy])[aeiouy]\1[aeiouy]/; +const cvcv_same_vowel = /^[^aeiouy]([aeiouy])[^aeiouy]\1/; +const cvcv_known_consonants = /^([tg][aeiouy]){2}/; +const only_one_or_more_c = /^[^aeiouy]+$/; + +const ends_with_vowel = /[aeiouy]$/; +const starts_with_consonant_vowel = /^[^aeiouy][h]?[aeiouy]/; + +const ones = [ + /^[^aeiou]?ion/, + /^[^aeiou]?ised/, + /^[^aeiou]?iled/, + + // -ing, -ent + /[aeiou][n][gt]$/, + + // -ate, -age + /\wa[gt]e$/, +]; + +//suffix fixes +const postprocess = function(arr) { + //trim whitespace + arr = arr.map(function(w) { + return w.trim() + }); + arr = arr.filter(function(w) { + return w !== '' + }); + // if (arr.length > 2) { + // return arr; + // } + let l = arr.length; + if (l > 1) { + let suffix = arr[l - 2] + arr[l - 1]; + for (let i = 0; i < ones.length; i++) { + if (suffix.match(ones[i])) { + arr[l - 2] = arr[l - 2] + arr[l - 1]; + arr.pop(); + } + } + } + + // since the open syllable detection is overzealous, + // sometimes need to rejoin incorrect splits + if (arr.length > 1) { + let first_is_open = + (arr[0].length === 1 || arr[0].match(starts_with_consonant_vowel)) && + arr[0].match(ends_with_vowel); + let second_is_joining = arr[1].match(joining_consonant_vowel); + + if (first_is_open && second_is_joining) { + let possible_combination = arr[0] + arr[1]; + let probably_separate_syllables = + possible_combination.match(cvcv_same_consonant) || + possible_combination.match(cvcv_same_vowel) || + possible_combination.match(cvcv_known_consonants); + + if (!probably_separate_syllables) { + arr[0] = arr[0] + arr[1]; + arr.splice(1, 1); + } + } + } + + if (arr.length > 1) { + let second_to_last_is_open = + arr[arr.length - 2].match(starts_with_consonant_vowel) && + arr[arr.length - 2].match(ends_with_vowel); + let last_is_joining = + arr[arr.length - 1].match(joining_consonant_vowel) && + ones.every(re => !arr[arr.length - 1].match(re)); + + if (second_to_last_is_open && last_is_joining) { + let possible_combination = arr[arr.length - 2] + arr[arr.length - 1]; + let probably_separate_syllables = + possible_combination.match(cvcv_same_consonant) || + possible_combination.match(cvcv_same_vowel) || + possible_combination.match(cvcv_known_consonants); + + if (!probably_separate_syllables) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]; + arr.splice(arr.length - 1, 1); + } + } + } + + if (arr.length > 1) { + let single = arr[0] + arr[1]; + if (single.match(starts_with_single_vowel_combos)) { + arr[0] = single; + arr.splice(1, 1); + } + } + + if (arr.length > 1) { + if (arr[arr.length - 1].match(only_one_or_more_c)) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1]; + arr.splice(arr.length - 1, 1); + } + } + + return arr +}; +var postProcess = postprocess; + +//chop a string into pronounced syllables + + +const all_spaces = / +/g; +const ends_with_vowel$1 = /[aeiouy]$/; +const starts_with_consonant_vowel$1 = /^[^aeiouy][h]?[aeiouy]/; +const starts_with_e_then_specials = /^e[sm]/; +const starts_with_e = /^e/; +const ends_with_noisy_vowel_combos = /(eo|eu|ia|oa|ua|ui)$/i; +const aiouy = /[aiouy]/; +const ends_with_ee = /ee$/; + +//method is nested because it's called recursively +const doWord = function(w) { + let all = []; + let chars = w.split(''); + let before = ''; + let after = ''; + let current = ''; + for (let i = 0; i < chars.length; i++) { + before = chars.slice(0, i).join(''); + current = chars[i]; + after = chars.slice(i + 1, chars.length).join(''); + let candidate = before + chars[i]; + + //it's a consonant that comes after a vowel + if (before.match(ends_with_vowel$1) && !current.match(ends_with_vowel$1)) { + if (after.match(starts_with_e_then_specials)) { + candidate += 'e'; + after = after.replace(starts_with_e, ''); + } + all.push(candidate); + return all.concat(doWord(after)) + } + + //unblended vowels ('noisy' vowel combinations) + if (candidate.match(ends_with_noisy_vowel_combos)) { + //'io' is noisy, not in 'ion' + all.push(before); + all.push(current); + return all.concat(doWord(after)) //recursion + } + + // if candidate is followed by a CV, assume consecutive open syllables + if (candidate.match(ends_with_vowel$1) && after.match(starts_with_consonant_vowel$1)) { + all.push(candidate); + return all.concat(doWord(after)) + } + } + //if still running, end last syllable + if (w.match(aiouy) || w.match(ends_with_ee)) { + //allow silent trailing e + all.push(w); + } else if (w) { + let last = all.length - 1; + if (last < 0) { + last = 0; + } + all[last] = (all[last] || '') + w; //append it to the last one + } + return all +}; + +let syllables = function(str) { + let all = []; + if (!str) { + return all + } + str = str.replace(/[.,?]/g, ''); + str.split(all_spaces).map(s => { + all = all.concat(doWord(s)); + }); + + // str.split(whitespace_dash).forEach(doWord) + all = postProcess(all); + + //for words like 'tree' and 'free' + if (all.length === 0) { + all = [str]; + } + //filter blanks + all = all.filter(s => s); + + return all +}; + +// console.log(syllables('civilised')) + +var syllables_1 = syllables; + +const defaultObj = { normal: true, text: true, terms: false }; + +const addMethod = function(Doc) { + Doc.prototype.syllables = function(n, obj) { + let data = this.data(obj || defaultObj); + //add syllable data to each phrase + data = data.map(o => { + o.syllables = syllables_1(o.normal || o.text); + return o + }); + if (typeof n === 'number') { + data = data[n]; + } + return data + }; + + return Doc +}; +var src = addMethod; + +export default src; diff --git a/plugins/syllables/package-lock.json b/plugins/syllables/package-lock.json new file mode 100644 index 000000000..3d587db95 --- /dev/null +++ b/plugins/syllables/package-lock.json @@ -0,0 +1,772 @@ +{ + "name": "compromise-syllables", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "12.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", + "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "chalk": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "es-abstract": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-reference": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz", + "integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "re-emitter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.3.tgz", + "integrity": "sha1-+p4xn/3u6zWycpbvDz03TawvUqc=", + "dev": true + }, + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rollup": { + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.5.tgz", + "integrity": "sha512-8rfVdzuTg2kt8ObD9LNJpEwUN7B6lsl3sHc5fddtgICpLjpYeSf4m2+RftBzcCaBTMi1iYX3Ez8zFT4Gj2nJjg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz", + "integrity": "sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^1.7.0", + "terser": "^4.1.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", + "dev": true, + "requires": { + "through": "2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap-dancer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tap-dancer/-/tap-dancer-0.2.0.tgz", + "integrity": "sha512-SKUl8jHmYf/7rugeFTwYGpguRi43zqOTVZOfeh3DKCAlazZerdXd11ER5kNVbsbdWc5FB8wwjlZhjTc0W69iGQ==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "tap-out": "3.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "tap-out": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tap-out/-/tap-out-3.0.0.tgz", + "integrity": "sha512-JzlrjCL3anqI9xHGPfYb6Mo+6nYs60m0tDy6i0sWhYDlrBDVerYPNWoUo1buK3YeWQFdm42KQv8wu9qLf1tL5A==", + "dev": true, + "requires": { + "re-emitter": "1.1.3", + "readable-stream": "2.2.9", + "split": "1.0.0", + "trim": "0.0.1" + } + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "terser": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.1.tgz", + "integrity": "sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/plugins/syllables/package.json b/plugins/syllables/package.json new file mode 100644 index 000000000..7604f8d0c --- /dev/null +++ b/plugins/syllables/package.json @@ -0,0 +1,47 @@ +{ + "name": "compromise-syllables", + "description": "plugin for nlp-compromise", + "version": "0.0.2", + "author": "Spencer Kelly (http://spencermounta.in)", + "main": "./builds/compromise-syllables.js", + "unpkg": "./builds/compromise-syllables.min.js", + "module": "./builds/compromise-syllables.mjs", + "repository": { + "type": "git", + "url": "git://github.com/spencermountain/compromise.git" + }, + "scripts": { + "test": "tape \"./tests/**/*.test.js\" | tap-dancer", + "testb": "TESTENV=prod tape \"./tests/**/*.test.js\" | tap-dancer", + "watch": "amble ./scratch.js", + "build": "rollup -c" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 100 + }, + "files": [ + "builds/" + ], + "eslintIgnore": [ + "builds/*.js" + ], + "peerDependencies": { + "compromise": "^12.*.*" + }, + "dependencies": {}, + "devDependencies": { + "rollup": "1.27.5", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.1.0", + "rollup-plugin-terser": "^5.0.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/plugins/syllables/rollup.config.js b/plugins/syllables/rollup.config.js new file mode 100644 index 000000000..978d8bc14 --- /dev/null +++ b/plugins/syllables/rollup.config.js @@ -0,0 +1,67 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' +const name = 'compromise-syllables' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.mjs`, + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.js`, + format: 'umd', + sourcemap: true, + name: 'compromiseSyllables', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: `builds/${name}.min.js`, + format: 'umd', + name: 'compromiseSyllables', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/plugins/syllables/src/index.js b/plugins/syllables/src/index.js new file mode 100644 index 000000000..8f72a3726 --- /dev/null +++ b/plugins/syllables/src/index.js @@ -0,0 +1,27 @@ +const getSyllables = require('./syllables') + +const defaultObj = { normal: true, text: true, terms: false } + +const addMethod = function(Doc) { + /** split each term by typical pronounciation */ + Doc.prototype.syllables = function(obj) { + let n = null + if (typeof obj === 'number') { + n = obj + obj = {} + } + let data = this.json(obj || defaultObj) + //add syllable data to each phrase + data = data.map(o => { + o.syllables = getSyllables(o.normal || o.text) + return o + }) + if (typeof n === 'number') { + data = data[n] + } + return data + } + + return Doc +} +module.exports = addMethod diff --git a/plugins/syllables/src/postProcess.js b/plugins/syllables/src/postProcess.js new file mode 100644 index 000000000..09d8ce212 --- /dev/null +++ b/plugins/syllables/src/postProcess.js @@ -0,0 +1,107 @@ +const starts_with_single_vowel_combos = /^(eu)/i +const joining_consonant_vowel = /^[^aeiou][e]([^d]|$)/ +const cvcv_same_consonant = /^([^aeiouy])[aeiouy]\1[aeiouy]/ +const cvcv_same_vowel = /^[^aeiouy]([aeiouy])[^aeiouy]\1/ +const cvcv_known_consonants = /^([tg][aeiouy]){2}/ +const only_one_or_more_c = /^[^aeiouy]+$/ + +const ends_with_vowel = /[aeiouy]$/ +const starts_with_consonant_vowel = /^[^aeiouy][h]?[aeiouy]/ + +const ones = [ + /^[^aeiou]?ion/, + /^[^aeiou]?ised/, + /^[^aeiou]?iled/, + + // -ing, -ent + /[aeiou][n][gt]$/, + + // -ate, -age + /\wa[gt]e$/, +] + +//suffix fixes +const postprocess = function(arr) { + //trim whitespace + arr = arr.map(function(w) { + return w.trim() + }) + arr = arr.filter(function(w) { + return w !== '' + }) + // if (arr.length > 2) { + // return arr; + // } + let l = arr.length + if (l > 1) { + let suffix = arr[l - 2] + arr[l - 1] + for (let i = 0; i < ones.length; i++) { + if (suffix.match(ones[i])) { + arr[l - 2] = arr[l - 2] + arr[l - 1] + arr.pop() + } + } + } + + // since the open syllable detection is overzealous, + // sometimes need to rejoin incorrect splits + if (arr.length > 1) { + let first_is_open = + (arr[0].length === 1 || arr[0].match(starts_with_consonant_vowel)) && + arr[0].match(ends_with_vowel) + let second_is_joining = arr[1].match(joining_consonant_vowel) + + if (first_is_open && second_is_joining) { + let possible_combination = arr[0] + arr[1] + let probably_separate_syllables = + possible_combination.match(cvcv_same_consonant) || + possible_combination.match(cvcv_same_vowel) || + possible_combination.match(cvcv_known_consonants) + + if (!probably_separate_syllables) { + arr[0] = arr[0] + arr[1] + arr.splice(1, 1) + } + } + } + + if (arr.length > 1) { + let second_to_last_is_open = + arr[arr.length - 2].match(starts_with_consonant_vowel) && + arr[arr.length - 2].match(ends_with_vowel) + let last_is_joining = + arr[arr.length - 1].match(joining_consonant_vowel) && + ones.every(re => !arr[arr.length - 1].match(re)) + + if (second_to_last_is_open && last_is_joining) { + let possible_combination = arr[arr.length - 2] + arr[arr.length - 1] + let probably_separate_syllables = + possible_combination.match(cvcv_same_consonant) || + possible_combination.match(cvcv_same_vowel) || + possible_combination.match(cvcv_known_consonants) + + if (!probably_separate_syllables) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1] + arr.splice(arr.length - 1, 1) + } + } + } + + if (arr.length > 1) { + let single = arr[0] + arr[1] + if (single.match(starts_with_single_vowel_combos)) { + arr[0] = single + arr.splice(1, 1) + } + } + + if (arr.length > 1) { + if (arr[arr.length - 1].match(only_one_or_more_c)) { + arr[arr.length - 2] = arr[arr.length - 2] + arr[arr.length - 1] + arr.splice(arr.length - 1, 1) + } + } + + return arr +} +module.exports = postprocess diff --git a/plugins/syllables/src/syllables.js b/plugins/syllables/src/syllables.js new file mode 100644 index 000000000..6ca88535d --- /dev/null +++ b/plugins/syllables/src/syllables.js @@ -0,0 +1,90 @@ +//chop a string into pronounced syllables +const postProcess = require('./postProcess') + +const all_spaces = / +/g +const ends_with_vowel = /[aeiouy]$/ +const starts_with_consonant_vowel = /^[^aeiouy][h]?[aeiouy]/ +const starts_with_e_then_specials = /^e[sm]/ +const starts_with_e = /^e/ +const ends_with_noisy_vowel_combos = /(eo|eu|ia|oa|ua|ui)$/i +const aiouy = /[aiouy]/ +const ends_with_ee = /ee$/ +// const whitespace_dash = /\s\-/ + +//method is nested because it's called recursively +const doWord = function(w) { + let all = [] + let chars = w.split('') + let before = '' + let after = '' + let current = '' + for (let i = 0; i < chars.length; i++) { + before = chars.slice(0, i).join('') + current = chars[i] + after = chars.slice(i + 1, chars.length).join('') + let candidate = before + chars[i] + + //it's a consonant that comes after a vowel + if (before.match(ends_with_vowel) && !current.match(ends_with_vowel)) { + if (after.match(starts_with_e_then_specials)) { + candidate += 'e' + after = after.replace(starts_with_e, '') + } + all.push(candidate) + return all.concat(doWord(after)) + } + + //unblended vowels ('noisy' vowel combinations) + if (candidate.match(ends_with_noisy_vowel_combos)) { + //'io' is noisy, not in 'ion' + all.push(before) + all.push(current) + return all.concat(doWord(after)) //recursion + } + + // if candidate is followed by a CV, assume consecutive open syllables + if (candidate.match(ends_with_vowel) && after.match(starts_with_consonant_vowel)) { + all.push(candidate) + return all.concat(doWord(after)) + } + } + //if still running, end last syllable + if (w.match(aiouy) || w.match(ends_with_ee)) { + //allow silent trailing e + all.push(w) + } else if (w) { + let last = all.length - 1 + if (last < 0) { + last = 0 + } + all[last] = (all[last] || '') + w //append it to the last one + } + return all +} + +let syllables = function(str) { + let all = [] + if (!str) { + return all + } + str = str.replace(/[.,?]/g, '') + str.split(all_spaces).map(s => { + all = all.concat(doWord(s)) + }) + + // str.split(whitespace_dash).forEach(doWord) + all = postProcess(all) + + //for words like 'tree' and 'free' + if (all.length === 0) { + all = [str] + } + //filter blanks + all = all.filter(s => s) + + return all +} + +// console.log(syllables('civilised')) + +module.exports = syllables diff --git a/plugins/syllables/tests/_lib.js b/plugins/syllables/tests/_lib.js new file mode 100644 index 000000000..254633449 --- /dev/null +++ b/plugins/syllables/tests/_lib.js @@ -0,0 +1,12 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + nlp = require('../../../') + nlp.extend(require(`../`)) + } else { + nlp = require('../../../src') + nlp.extend(require(`../src`)) + } + + module.exports = nlp +} diff --git a/plugins/syllables/tests/syllables.test.js b/plugins/syllables/tests/syllables.test.js new file mode 100644 index 000000000..f6cf59056 --- /dev/null +++ b/plugins/syllables/tests/syllables.test.js @@ -0,0 +1,73 @@ +const test = require('tape') +const nlp = require('./_lib') + +const words = [ + 'sud den ly', + 'con sti pa tion', + 'di a bo lic', + 'fa ted', + 'ge ne tic', + 'hy giene', + 'o ma ha', + 'i mi ta ted', + 'tree', + 'ci vi lised', + 'went', + 'to ge ther', + 'tog gle', + 'move ment', + 'mo ment', + 'do nate', + 'vi king', + 'wat tage', + 'con gre gate', + 'some thing', + 'sales man', + 're sour ces', + 'eve ry thing', + 'eve ry bo dy', + 'hole', + 'ho ly', + 'sec ret', + 'cause', + 'fate', + 'fates', + 'eu lo gy', + 'e on', + 'rea sons', + 'and', + 'hoc key', + 'wild', + 'fun', + 'fun ny', + 'hor ses', + 'cal ga ry', + 'tor na do', + 'pen', + 'stu dy', + 'ja mai ca', + 'tri ni dad', + 'ca na da', + 'i ran', + 'i raq', + 'sau di a ra bi a', + 'clin ton', + 'hub ris', + 'tur key', + 'cor si ca', + 'dev iled', + // 'horse', + // 'chance', + // 'peo ple' +] + +test('test length', function(t) { + words.forEach(sep => { + let str = sep.replace(/ /g, '') + let doc = nlp(str) + let arr = doc.syllables() + let want = sep.split(/ /g) + t.equal(arr[0].syllables.length, want.length, str) + }) + t.end() +}) diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 000000000..1a4c05123 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,66 @@ +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import { terser } from 'rollup-plugin-terser' +import resolve from 'rollup-plugin-node-resolve' +import babel from 'rollup-plugin-babel' + +export default [ + { + input: 'src/index.js', + output: [ + { + file: 'builds/compromise.mjs', + format: 'esm', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: 'builds/compromise.js', + format: 'umd', + sourcemap: true, + name: 'nlp', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + ], + }, + { + input: 'src/index.js', + output: [ + { + file: 'builds/compromise.min.js', + format: 'umd', + name: 'nlp', + }, + ], + plugins: [ + resolve(), + json(), + commonjs(), + babel({ + babelrc: false, + presets: ['@babel/preset-env'], + }), + terser(), + ], + }, +] diff --git a/scratch.js b/scratch.js index 920215db2..0a4ccdf2d 100644 --- a/scratch.js +++ b/scratch.js @@ -1,5 +1,20 @@ -var nlp = require('./src/index'); -nlp.verbose('tagger'); +const nlp = require('./src/index') +// nlp.verbose(true) +// nlp.extend(require('./plugins/sentences/src')) +// nlp.extend(require('./plugins/numbers/src')) -var doc = nlp('it was cold').debug(); -console.log(doc.verbs().conjugation()); +// let doc = nlp(`i walked to the moon when it was shining`) +// doc.verbs().forEach(d => { +// d.matchOne('walked').replaceWith('sat') +// }) +// doc.sentences().toPastTense() +// doc.debug() + +// let doc = nlp.tokenize(`between june 5th and june 7th`) +// doc.match('between [#Date+] and').debug() +// doc.match('between [.*] and').debug() + +// let doc = nlp('falls over') +// let doc = nlp('i paid $5.20 for the thing') +let doc = nlp('i got 1 peso and £30.').debug() +doc.money().debug() diff --git a/scripts/benchmark.js b/scripts/benchmark.js deleted file mode 100644 index 5910f967f..000000000 --- a/scripts/benchmark.js +++ /dev/null @@ -1,34 +0,0 @@ -var benchmark = require('./lib/benchmark'); -var fs = require('fs'); -var chalk = require('chalk'); - -var redGreen = function(last, now, unit) { - var diff = (now - last).toFixed(2); - var percent = diff / last * 100; - percent = parseInt(percent, 10); - if (percent < 0) { - console.log(' ' + chalk.green(' ' + percent + '% ' + diff + ' ' + unit)); - } else if (percent === 0) { - console.log(' ' + chalk.yellow(' ' + percent + '% ' + diff + ' ' + unit)); - } else { - console.log(' ' + chalk.red('+' + percent + '% ' + diff + ' ' + unit)); - } - console.log(''); -}; - -var compare = function(obj) { - console.log(''); - var last = JSON.parse(fs.readFileSync('./scripts/lib/log.json')); - console.log(' size:'); - redGreen(last.size, obj.size, 'kb'); - console.log(' init:'); - redGreen(last.init, obj.init, 'ms'); - console.log(' parse:'); - redGreen(last.big, obj.big, 'ms'); -}; - -benchmark(obj => { - compare(obj); - // console.log(JSON.stringify(obj, null, 2)); - // fs.writeFileSync('./scripts/lib/log.json', out); -}); diff --git a/scripts/browserTest.js b/scripts/browserTest.js deleted file mode 100644 index 63afa52a4..000000000 --- a/scripts/browserTest.js +++ /dev/null @@ -1,20 +0,0 @@ -var exec = require('shelljs').exec; -var browserifyGlob = '"./node_modules/.bin/browserify-glob"'; -var fileServer = '"./node_modules/.bin/http-server"'; - -//run tests on the client-side -var out = './test/client/compiled_tests.js'; -var cmd = browserifyGlob + ' "./test/unit/**/*.test.js" '; -cmd += ' -t [ babelify --presets [ env ]] > ' + out; -cmd += ' && ' + fileServer + ' test/client -o -c-1'; -exec(cmd); - -//then cleanup that god-awful file in our sourcecode -// exec('rm ' + out); - - -//es5 main (browserify + derequire) -// cmd = lib.browserify + ' "./src/index.js" --standalone nlp'; -// cmd += ' | ' + lib.derequire; -// cmd += ' >> ' + path.es5; -// exec(cmd); diff --git a/scripts/build/es5-build.js b/scripts/build/es5-build.js deleted file mode 100644 index c860b8d7b..000000000 --- a/scripts/build/es5-build.js +++ /dev/null @@ -1,40 +0,0 @@ -var fs = require('fs'); -var exec = require('shelljs').exec; -var chalk = require('chalk'); -var terser = require('terser'); - -var pkg = require('../../package.json'); -var fileSize = require('../lib/filesize'); - -var browserify = '"node_modules/.bin/browserify"'; -var derequire = '"node_modules/.bin/derequire"'; - -var es5 = './builds/compromise.js'; -var es5min = './builds/compromise.min.js'; - -console.log(chalk.yellow(' 🕑 creating es5 build..')); - -var banner = - '/* compromise v' + pkg.version + '\n github.com/nlp-compromise/compromise\n MIT\n*/\n'; - -//es5 main (browserify + derequire) -cmd = browserify + ' "./src/index.js" --standalone nlp'; -cmd += ' -t [ babelify --presets [ @babel/preset-env ] ]'; -cmd += ' | ' + derequire; -cmd += ' >> ' + es5; -exec(cmd); - -var code = fs.readFileSync(es5).toString(); - -var result = terser.minify(code, { - output: { - beautify: false, - preamble: banner - }, - compress: { - passes: 2 - } -}); -fs.writeFileSync(es5min, result.code); - -console.log(chalk.green(' done! es5min ' + fileSize(es5min) + 'k\n')); diff --git a/scripts/build/es6-build.js b/scripts/build/es6-build.js deleted file mode 100644 index 95906b65a..000000000 --- a/scripts/build/es6-build.js +++ /dev/null @@ -1,33 +0,0 @@ -var shelljs = require('shelljs'); -var chalk = require('chalk'); -var fileSize = require('../lib/filesize'); -var pkg = require('../../package.json'); -var exec = shelljs.exec; -var echo = shelljs.echo; - -var browserify = '"node_modules/.bin/browserify"'; -var derequire = '"node_modules/.bin/derequire"'; -var babili = '"node_modules/.bin/babili"'; - -var es6 = './builds/compromise.es6.js'; -var es6min = './builds/compromise.es6.min.js'; - -var banner = '/* compromise v' + pkg.version + '\n http://compromise.cool\n MIT\n*/\n'; -echo(banner).to(es6); - -console.log(chalk.yellow(' 🕑 creating es6 build..')); - -//es6 main (browserify) -var cmd = browserify + ' "./src/index.js" --standalone nlp'; -// cmd += ' -p bundle-collapser/plugin'; -cmd += ' | ' + derequire; -cmd += ' >> ' + es6; -exec(cmd); - -//es6min (babili) -cmd = babili + ' ' + es6; -cmd += ' >> ' + es6min; -exec(cmd); - -//remove the first one -console.log(chalk.green(' done! es6min ' + fileSize(es6min) + 'k\n')); diff --git a/scripts/build/index.js b/scripts/build/index.js deleted file mode 100644 index d2ef53d34..000000000 --- a/scripts/build/index.js +++ /dev/null @@ -1,29 +0,0 @@ -var fs = require('fs'); -var benchmark = require('../lib/benchmark'); -var exec = require('shelljs').exec; - -//pack the tries -require('../pack'); - -//cleanup. remove old builds -exec('rm -rf ./builds && mkdir builds'); - -//build each version -require('./es6-build'); -require('./es5-build'); - -//sanity test them -require('./quicktest'); - -var fileSize = function(src) { - var stats = fs.statSync(src); - return stats['size'] / 1000.0; -}; - -//log the filesize and speed -benchmark(obj => { - obj.size = fileSize('./builds/compromise.min.js'); - var out = JSON.stringify(obj, null, 2); - console.log(out); - fs.writeFileSync('./scripts/lib/log.json', out); -}); diff --git a/scripts/build/quicktest.js b/scripts/build/quicktest.js deleted file mode 100644 index ad21af08a..000000000 --- a/scripts/build/quicktest.js +++ /dev/null @@ -1,17 +0,0 @@ -var assert = require('assert'); -var chalk = require('chalk'); - -console.log(chalk.green('\n==sanity-test builds==')); -//sanity-test the builds -var libs = [ - require('../../builds/compromise.js'), - require('../../builds/compromise.min.js'), - require('../../builds/compromise.es6.min.js') -]; -libs.forEach((nlp, i) => { - console.log(chalk.green(' - - #' + i)); - var r = nlp('John and Joe walked to the store'); - assert(r.people().data().length === 2); - assert(r.verbs().data().length === 1); -}); -console.log(chalk.green('\n 👍')); diff --git a/scripts/buildAll.js b/scripts/buildAll.js new file mode 100644 index 000000000..8db465d1e --- /dev/null +++ b/scripts/buildAll.js @@ -0,0 +1,14 @@ +// ensure all our plugins are up-to-spec +const fs = require('fs') +const path = require('path') +const sh = require('shelljs') + +sh.ls('./plugins').forEach(function(dir) { + console.log('\n\n===' + dir + '===') + sh.exec('cd ./plugins/' + dir + ' && npm run build') + + let pkg = JSON.parse(fs.readFileSync(`./plugins/${dir}/package.json`)) + let stats = fs.statSync(path.join('./plugins', dir, pkg.unpkg)) + let size = (stats['size'] / 1000.0).toFixed(1) + console.log('\n\n-----' + dir + ' ' + size + 'kb -----\n') +}) diff --git a/scripts/coverage.js b/scripts/coverage.js new file mode 100644 index 000000000..abd11cefa --- /dev/null +++ b/scripts/coverage.js @@ -0,0 +1,20 @@ +const exec = require('shelljs').exec +const nyc = './node_modules/nyc/bin/nyc.js' +const codacity = './node_modules/.bin/codacy-coverage' +const tape = './node_modules/tape/bin/tape' +const tapSpec = './node_modules/.bin/tap-dancer' +const test = tape + ' "./tests/**/*.test.js" ' + +//to upload to codacity, set the api key as $CODACY_PROJECT_TOKEN +//export CODACY_PROJECT_TOKEN= + +//run all the tests +console.log('\n 🏃 running coverage tests..') +// exec(nyc + ' --reporter=text-lcov ' + test + ' > coverage.lcov'); +exec(nyc + ' --reporter=html ' + test + ' | ' + tapSpec) + +//publish results for codacity +// console.log('\n\n\nPublishing results to codacity...\n') +// var cmd = nyc + ' report --reporter=text-lcov ' + test + ' | ' + codacity +// exec(cmd) +// console.log('\n 🏃 done!') diff --git a/scripts/filesize.js b/scripts/filesize.js new file mode 100644 index 000000000..f25b7d939 --- /dev/null +++ b/scripts/filesize.js @@ -0,0 +1,11 @@ +var fs = require('fs') +var path = require('path') + +console.log('\n\n----\n') +var buildsDir = path.join(__dirname, '../builds') + +let abs = path.join(buildsDir, './compromise.min.js') +var stats = fs.statSync(abs) +let size = (stats['size'] / 1000.0).toFixed(1) +console.log(' ./min.js : ' + size + ' kb') +console.log('\n') diff --git a/scripts/lib/benchmark.js b/scripts/lib/benchmark.js deleted file mode 100644 index b3c89e14d..000000000 --- a/scripts/lib/benchmark.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; -var filesize = require('./filesize'); -var path = require('path'); -var str = require('../../test/unit/lib/friends'); -var start; -var end; -var src = path.join(__dirname, '../../builds/compromise.min.js'); - -var benchmark = function(cb) { - var obj = {}; - setTimeout(() => { - //init - start = new Date().getTime(); - var nlp = require(src); - end = new Date().getTime(); - obj.init = end - start; - - //small parse - start = new Date().getTime(); - var m = nlp('spencer kelly and dr. spencer kelly'); - end = new Date().getTime(); - obj.sentence = end - start; - - //small match - start = new Date().getTime(); - m.match('#Person').out(); - end = new Date().getTime(); - obj.match = end - start; - (function() { - //big parse - start = new Date().getTime(); - var m2 = nlp(str); - end = new Date().getTime(); - obj.big = end - start; - - //big match - start = new Date().getTime(); - m2.match('#Person').out('normal'); - end = new Date().getTime(); - obj.bigMatch = end - start; - - obj.size = filesize(src); - cb(obj); - })(); - }, 200); -}; -module.exports = benchmark; diff --git a/scripts/lib/filesize.js b/scripts/lib/filesize.js deleted file mode 100644 index 8c3b3a576..000000000 --- a/scripts/lib/filesize.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -var fs = require('fs'); - -var fileSize = function(src) { - var stats = fs.statSync(src); - return (stats['size'] / 1000.0).toFixed(2); -}; - -module.exports = fileSize; diff --git a/scripts/lib/log.json b/scripts/lib/log.json deleted file mode 100644 index 87117b559..000000000 --- a/scripts/lib/log.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "init": 1, - "sentence": 7, - "match": 1, - "big": 667, - "bigMatch": 2, - "size": 235.343 -} \ No newline at end of file diff --git a/scripts/pack.js b/scripts/pack.js index ce2d84e2e..197210b2f 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -1,21 +1,38 @@ -'use strict'; -var chalk = require('chalk'); -var fs = require('fs'); -var path = require('path'); -var nlpPlugin = require('compromise-plugin'); -var fileSize = require('./lib/filesize'); +var fs = require('fs') +var path = require('path') +var efrt = require('efrt') +// var nlpPlugin = require('compromise-plugin') -console.log(chalk.yellow('\n 🕑 packing lexicon..')); -var out = path.join(__dirname, '../src/world/_data.js'); -//cleanup. remove old builds -// exec('rm ' + out); +console.log('\n 🕑 - packing lexicon..') +var outFile = path.join(__dirname, '../src/world/_data.js') -//pack it into one string -var data = require('../data'); -var pckd = nlpPlugin.pack(data); +var lexicon = require('../data') -fs.writeFileSync(out, 'module.exports=`' + pckd + '`', 'utf8'); +//turn them into a series of flat-arrays +let words = Object.keys(lexicon) +let packed = {} +words.forEach(word => { + let tags = lexicon[word] + if (typeof tags === 'string') { + tags = [tags] + } + tags.forEach(tag => { + packed[tag] = packed[tag] || [] + packed[tag].push(word) + }) +}) -// console.log(chalk.blue('\n\n ' + Object.keys(data.words).length + ' words')); -console.log(chalk.blue(' - packed into - ' + fileSize(out) + 'k\n')); -console.log(chalk.green(' done!\n')); +//pack each array into a tiny string +Object.keys(packed).forEach(tag => { + packed[tag] = efrt.pack(packed[tag]) +}) + +//write it to a file in ./src +fs.writeFileSync(outFile, 'module.exports=' + JSON.stringify(packed, null, 2), 'utf8') + +//get filesize +var stats = fs.statSync(outFile) +let size = (stats['size'] / 1000.0).toFixed(1) + +console.log(' - packed into ' + size + 'k\n') +console.log(' done!\n') diff --git a/scripts/pieChart.js b/scripts/pieChart.js deleted file mode 100644 index 378893739..000000000 --- a/scripts/pieChart.js +++ /dev/null @@ -1,24 +0,0 @@ -var exec = require('shelljs').exec; -//use paths, so libs don't need a -g -var browserify = './node_modules/.bin/browserify'; -var derequire = './node_modules/derequire/bin/cmd.js'; - -exec('du -a ./src | sort -n -r | grep .js | head -n 10'); - -//haha-engineering -exec('npm i uglifyify --no-save'); - -exec('rm -rf ./viz'); -exec('mkdir viz'); - -//make the bundle with full-paths -var cmd = browserify + ' --full-paths ./src/index.js --standalone nlp'; -cmd += ' -t [ babelify --presets [ env ] ]'; -cmd += ' -t [ uglifyify --compress --mangle ]'; -cmd += ' | ' + derequire; -cmd += ' >> ./viz/bundle.js'; -exec(cmd); - -exec('discify ./viz/bundle.js > ./viz/output.html'); - -exec('google-chrome ./viz/output.html'); diff --git a/scripts/plugin-check.js b/scripts/plugin-check.js new file mode 100644 index 000000000..94cb36ce2 --- /dev/null +++ b/scripts/plugin-check.js @@ -0,0 +1,10 @@ +// ensure all our plugins are up-to-spec +const sh = require('shelljs') + +sh.ls('./plugins').forEach(function(dir) { + console.log('\n\n===' + dir + '===') + sh.exec('cd ./plugins/' + dir + ' && npm install') + // sh.exec('cd ./plugins/' + dir + ' && npm outdated') + sh.exec('cd ./plugins/' + dir + ' && npm audit') + // sh.exec('cd ./plugins/' + dir + ' && npm run test ') +}) diff --git a/scripts/postpublish/coverage.js b/scripts/postpublish/coverage.js deleted file mode 100644 index 75cd8c1bf..000000000 --- a/scripts/postpublish/coverage.js +++ /dev/null @@ -1,7 +0,0 @@ -var exec = require('shelljs').exec; -var codecov = '15039ad1-b495-48cd-b4a0-bcf124c9b318'; //i don't really care if you steal this. - -//run all the tests -let cmd = `./node_modules/.bin/nyc --reporter=text-lcov ./node_modules/.bin/tape ./test/unit/**/*.test.js > coverage.lcov && ./node_modules/.bin/codecov -t ${codecov}`; -exec(cmd); -console.log('\n 🏃 done!'); diff --git a/scripts/postpublish/index.js b/scripts/postpublish/index.js deleted file mode 100644 index c7be19771..000000000 --- a/scripts/postpublish/index.js +++ /dev/null @@ -1,2 +0,0 @@ -console.log('running post-publish..'); -// require('./coverage'); diff --git a/scripts/prepublish/index.js b/scripts/prepublish/index.js deleted file mode 100644 index 7a5924788..000000000 --- a/scripts/prepublish/index.js +++ /dev/null @@ -1,31 +0,0 @@ -var exec = require('shelljs').exec; -var assert = require('assert'); -var chalk = require('chalk'); - -console.log(chalk.green('\n==checking branch==')); -var branch = exec('git status | grep "On branch" | cut -c 11-').stdout; -branch = branch.trim(); -if (branch !== 'master') { - console.log(chalk.red('\n\n ============ hey, not on master branch ===========\n\n')); -} - -console.log(chalk.green('\n==sanity-test builds==')); -//sanity-test the builds -var libs = [ - require('../../builds/compromise.js'), - require('../../builds/compromise.min.js') -// require('../../builds/compromise.es6.min.js') -]; -libs.forEach(nlp => { - var r = nlp('John and Joe walked to the store'); - assert(r.people().data().length === 2); - assert(r.verbs().data().length === 1); -}); - -//run linter -console.log(chalk.green('\n==run linter==')); -require('./linter'); - -//test builds -console.log(chalk.green('\n==test of builds==')); -require('./testBuild'); diff --git a/scripts/prepublish/linter.js b/scripts/prepublish/linter.js deleted file mode 100644 index e1ae5c0ed..000000000 --- a/scripts/prepublish/linter.js +++ /dev/null @@ -1,12 +0,0 @@ -var exec = require('shelljs').exec; -var path = require('path'); -var eslint = '"node_modules/.bin/eslint"'; - -//run linter -console.log('linting..'); -var cmd = eslint + ' -c .eslintrc --color ' + path.join(__dirname, '../../src/**/*.js'); -console.log(cmd); -exec(cmd, { - async: true -}); -console.log(' - done.'); diff --git a/scripts/prepublish/testBuild.js b/scripts/prepublish/testBuild.js deleted file mode 100644 index 2da3dd998..000000000 --- a/scripts/prepublish/testBuild.js +++ /dev/null @@ -1,7 +0,0 @@ -var exec = require('shelljs').exec; -var tape = '"node_modules/.bin/tape"'; -var tapSpec = '"node_modules/.bin/tap-dancer" --color'; - -console.log('testing built package..'); -exec('TESTENV=prod ' + tape + ' "./test/unit/**/*.test.js" | ' + tapSpec); -console.log(' - done.'); diff --git a/scripts/quicktest.js b/scripts/quicktest.js new file mode 100644 index 000000000..9fdbb8c10 --- /dev/null +++ b/scripts/quicktest.js @@ -0,0 +1,16 @@ +var assert = require('assert') + +console.log('\n==sanity-test builds==') +//sanity-test the builds +var libs = [ + require('../builds/compromise.js'), + require('../builds/compromise.min.js'), + // require('../../builds/compromise.es6.min.js'), +] +libs.forEach((nlp, i) => { + console.log(' - - #' + i) + var r = nlp('John and Joe walked to the store') + assert(r.people().data().length === 2) + assert(r.verbs().data().length === 1) +}) +console.log('\n 👍') diff --git a/scripts/stress-test/package-lock.json b/scripts/stress-test/package-lock.json new file mode 100644 index 000000000..f05457695 --- /dev/null +++ b/scripts/stress-test/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "compromise-stress-test", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "nlp-corpus": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/nlp-corpus/-/nlp-corpus-3.3.0.tgz", + "integrity": "sha512-aoipEO+qNUICPDrnk/1t4qe1Zqj2MgBlTnU/oo4GqwrduQ6ObN+OoU/Yp9A1uAETsdruZUJS7wQIVWJRntfWUw==", + "dev": true + } + } +} diff --git a/scripts/stress-test/package.json b/scripts/stress-test/package.json new file mode 100644 index 000000000..368070e8b --- /dev/null +++ b/scripts/stress-test/package.json @@ -0,0 +1,24 @@ +{ + "author": "Spencer Kelly (http://spencermounta.in)", + "name": "compromise-stress-test", + "description": "stress-testing for nlp-compromise", + "version": "0.0.1", + "private": true, + "scripts": { + "run": "node ./index.js" + }, + "prettier": { + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 120 + }, + "dependencies": {}, + "devDependencies": { + "nlp-corpus": "^3.3.0", + "tap-dancer": "0.2.0", + "tape": "4.11.0" + }, + "license": "MIT" +} diff --git a/scripts/stress-test/speed.js b/scripts/stress-test/speed.js new file mode 100644 index 000000000..d57177fe4 --- /dev/null +++ b/scripts/stress-test/speed.js @@ -0,0 +1,36 @@ +const corpus = require('nlp-corpus') + +const paths = { + // v11: '/Users/spencer/Desktop/compromise/builds/compromise.min.js', + v11: '/Users/spencer/Desktop/compromise/src/index.js', + v12: '../../src', + v12build: '../../builds/compromise.min.js', + // sept2: '/Users/spencer/Desktop/aug-2-start.js', + // start: '/Users/spencer/mountain/compromise/builds/aug-2-start.js', + // two: '/Users/spencer/mountain/compromise/builds/aug-2-2.js', + // start: '/Users/spencer/Desktop/aug-2-start.js', + // two: '/Users/spencer/Desktop/aug-2-2.js', + // ive: '/Users/spencer/Desktop/aug-2-ive.js', + // pos: '/Users/spencer/Desktop/aug-2-pos.js', + // much: '/Users/spencer/Desktop/aug-2-much.js', + // end: '/Users/spencer/Desktop/aug-2-end.js', +} + +function test(build) { + console.log('\n-- testing: ' + build + ' --') + console.time('load') + const nlp = require(paths[build]) + console.timeEnd('load') + + let txt = corpus.sotu.array()[8] + console.time('parse') + let doc = nlp(txt) + console.timeEnd('parse') + + console.time('match') + doc.match('#Noun') + console.timeEnd('match') + console.log('\n') +} + +Object.keys(paths).forEach(test) diff --git a/scripts/stress-test/stress.js b/scripts/stress-test/stress.js new file mode 100644 index 000000000..3eeedd364 --- /dev/null +++ b/scripts/stress-test/stress.js @@ -0,0 +1,13 @@ +const corpus = require('nlp-corpus') +const nlp = require('../../src') +console.log(`\n\n--- running compromise on 100 random texts---\n`) +console.log(' --should take a few minutes--') + +for (let i = 0; i < 100; i++) { + console.log('\n\n---' + i) + let txt = corpus.random() + console.log(txt.substr(0, 60).trim() + ' ... ') + nlp(txt) +} + +console.log('\n\n - done!') diff --git a/scripts/testAll.js b/scripts/testAll.js new file mode 100644 index 000000000..6b5f7a96c --- /dev/null +++ b/scripts/testAll.js @@ -0,0 +1,38 @@ +const sh = require('shelljs') + +// if given, run just one test: +let arg = process.argv[2] +if (arg) { + let code = 0 + console.log(arg + ':') + if (arg === 'main') { + code = sh.exec('tape "./tests/**/*.test.js" | tap-dancer --color always').code + } else { + code = sh.exec(`tape "./plugins/${arg}/tests/**/*.test.js" | tap-dancer --color always`).code + } + sh.exit(code) +} + +// run the main tests: +let fail = false +let code = sh.exec('tape "./tests/**/*.test.js" | tap-dancer --color always').code +if (code !== 0) { + fail = true +} + +// run each plugin's tests: +let plugins = ['adjectives', 'dates', 'ngrams', 'numbers', 'output', 'paragraphs', 'sentences', 'syllables'] +plugins.forEach(dir => { + code = sh.exec(`tape "./plugins/${dir}/tests/**/*.test.js" | tap-dancer --color always`).code + if (code !== 0) { + console.log(dir) + fail = true + } +}) + +// return proper exit-code: +if (fail) { + sh.exit(1) +} else { + sh.exit(0) +} diff --git a/scripts/version.js b/scripts/version.js new file mode 100644 index 000000000..4f66a9d23 --- /dev/null +++ b/scripts/version.js @@ -0,0 +1,6 @@ +var fs = require('fs') +var pkg = require('../package.json') + +// avoid requiring our whole package.json file +// make a small file for our version number +fs.writeFileSync('./src/_version.js', `module.exports = '${pkg.version}'`) diff --git a/src/01-tokenizer/01-sentences.js b/src/01-tokenizer/01-sentences.js new file mode 100644 index 000000000..9df64ac51 --- /dev/null +++ b/src/01-tokenizer/01-sentences.js @@ -0,0 +1,135 @@ +//(Rule-based sentence boundary segmentation) - chop given text into its proper sentences. +// Ignore periods/questions/exclamations used in acronyms/abbreviations/numbers, etc. +// @spencermountain 2017 MIT + +//proper nouns with exclamation marks +// const blacklist = { +// yahoo: true, +// joomla: true, +// jeopardy: true, +// } + +//regs- +const initSplit = /(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g +const hasSomething = /\S/ + +const isAcronym = /[ .][A-Z]\.? *$/i +const hasEllipse = /(?:\u2026|\.{2,}) *$/ +const newLine = /((?:\r?\n|\r)+)/ // Match different new-line formats +const hasLetter = /[a-z0-9\u00C0-\u00FF\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]/i + +const startWhitespace = /^\s+/ + +// Start with a regex: +const naiive_split = function(text) { + let all = [] + //first, split by newline + let lines = text.split(newLine) + for (let i = 0; i < lines.length; i++) { + //split by period, question-mark, and exclamation-mark + let arr = lines[i].split(initSplit) + for (let o = 0; o < arr.length; o++) { + all.push(arr[o]) + } + } + return all +} + +/** does this look like a sentence? */ +const isSentence = function(str, abbrevs) { + // check for 'F.B.I.' + if (isAcronym.test(str) === true) { + return false + } + //check for '...' + if (hasEllipse.test(str) === true) { + return false + } + // must have a letter + if (hasLetter.test(str) === false) { + return false + } + + let txt = str.replace(/[.!?\u203D\u2E18\u203C\u2047-\u2049] *$/, '') + let words = txt.split(' ') + let lastWord = words[words.length - 1].toLowerCase() + // check for 'Mr.' + if (abbrevs.hasOwnProperty(lastWord)) { + return false + } + // //check for jeopardy! + // if (blacklist.hasOwnProperty(lastWord)) { + // return false + // } + return true +} + +const splitSentences = function(text, world) { + let abbrevs = world.cache.abbreviations + + text = text || '' + text = String(text) + let sentences = [] + // First do a greedy-split.. + let chunks = [] + // Ensure it 'smells like' a sentence + if (!text || typeof text !== 'string' || hasSomething.test(text) === false) { + return sentences + } + // Start somewhere: + let splits = naiive_split(text) + // Filter-out the crap ones + for (let i = 0; i < splits.length; i++) { + let s = splits[i] + if (s === undefined || s === '') { + continue + } + //this is meaningful whitespace + if (hasSomething.test(s) === false) { + //add it to the last one + if (chunks[chunks.length - 1]) { + chunks[chunks.length - 1] += s + continue + } else if (splits[i + 1]) { + //add it to the next one + splits[i + 1] = s + splits[i + 1] + continue + } + } + //else, only whitespace, no terms, no sentence + chunks.push(s) + } + + //detection of non-sentence chunks: + //loop through these chunks, and join the non-sentence chunks back together.. + for (let i = 0; i < chunks.length; i++) { + let c = chunks[i] + //should this chunk be combined with the next one? + if (chunks[i + 1] && isSentence(c, abbrevs) === false) { + chunks[i + 1] = c + (chunks[i + 1] || '') + } else if (c && c.length > 0) { + //&& hasLetter.test(c) + //this chunk is a proper sentence.. + sentences.push(c) + chunks[i] = '' + } + } + //if we never got a sentence, return the given text + if (sentences.length === 0) { + return [text] + } + + //move whitespace to the ends of sentences, when possible + //['hello',' world'] -> ['hello ','world'] + for (let i = 1; i < sentences.length; i += 1) { + let ws = sentences[i].match(startWhitespace) + if (ws !== null) { + sentences[i - 1] += ws[0] + sentences[i] = sentences[i].replace(startWhitespace, '') + } + } + return sentences +} + +module.exports = splitSentences +// console.log(sentence_parser('john f. kennedy')); diff --git a/src/01-tokenizer/02-words.js b/src/01-tokenizer/02-words.js new file mode 100644 index 000000000..904efafbe --- /dev/null +++ b/src/01-tokenizer/02-words.js @@ -0,0 +1,109 @@ +const wordlike = /\S/ +const isBoundary = /^[!?.]+$/ +const naiiveSplit = /(\S+)/ +const isSlash = /\/\W*$/ + +const notWord = { + '.': true, + '-': true, //dash + '–': true, //en-dash + '—': true, //em-dash + '--': true, + '...': true, + // '/': true, // 'one / two' +} + +const hasHyphen = function(str) { + //dont split 're-do' + if (/^(re|un)-?[^aeiou]./.test(str) === true) { + return false + } + //letter-number + let reg = /^([a-z\u00C0-\u00FF`"'/]+)(-|–|—)([a-z0-9\u00C0-\u00FF].*)/i + if (reg.test(str) === true) { + return true + } + //support weird number-emdash combo '2010–2011' + // let reg2 = /^([0-9]+)(–|—)([0-9].*)/i + // if (reg2.test(str)) { + // return true + // } + return false +} + +// 'he / she' should be one word +const combineSlashes = function(arr) { + for (let i = 1; i < arr.length - 1; i++) { + if (isSlash.test(arr[i])) { + arr[i - 1] += arr[i] + arr[i + 1] + arr[i] = null + arr[i + 1] = null + } + } + return arr +} + +const splitHyphens = function(word) { + let arr = [] + //support multiple-hyphenated-terms + const hyphens = word.split(/[-–—]/) + for (let o = 0; o < hyphens.length; o++) { + if (o === hyphens.length - 1) { + arr.push(hyphens[o]) + } else { + arr.push(hyphens[o] + '-') + } + } + return arr +} + +//turn a string into an array of terms (naiive for now, lumped later) +const splitWords = function(str) { + let result = [] + let arr = [] + //start with a naiive split + str = str || '' + if (typeof str === 'number') { + str = String(str) + } + + const words = str.split(naiiveSplit) + for (let i = 0; i < words.length; i++) { + //split 'one-two' + if (hasHyphen(words[i]) === true) { + arr = arr.concat(splitHyphens(words[i])) + continue + } + arr.push(words[i]) + } + + //greedy merge whitespace+arr to the right + let carry = '' + for (let i = 0; i < arr.length; i++) { + let word = arr[i] + //if it's more than a whitespace + if (wordlike.test(word) === true && notWord.hasOwnProperty(word) === false && isBoundary.test(word) === false) { + //put whitespace on end of previous term, if possible + if (result.length > 0) { + result[result.length - 1] += carry + result.push(word) + } else { + //otherwise, but whitespace before + result.push(carry + word) + } + carry = '' + } else { + carry += word + } + } + //handle last one + if (carry && result.length > 0) { + result[result.length - 1] += carry //put it on the end + } + // combine 'one / two' + result = combineSlashes(result) + // remove empty results + result = result.filter(s => s) + return result +} +module.exports = splitWords diff --git a/src/01-tokenizer/Pool.js b/src/01-tokenizer/Pool.js new file mode 100644 index 000000000..a6ef632c6 --- /dev/null +++ b/src/01-tokenizer/Pool.js @@ -0,0 +1,46 @@ +/** a key-value store of all terms in our Document */ +class Pool { + constructor(words = {}) { + //quiet this property in console.logs + Object.defineProperty(this, 'words', { + enumerable: false, + value: words, + }) + } + /** throw a new term object in */ + add(term) { + this.words[term.id] = term + return this + } + /** find a term by it's id */ + get(id) { + return this.words[id] + } + /** find a term by it's id */ + remove(id) { + delete this.words[id] + } + merge(pool) { + Object.assign(this.words, pool.words) + return this + } + /** helper method */ + stats() { + return { + words: Object.keys(this.words).length, + } + } +} + +/** make a deep-copy of all terms */ +Pool.prototype.clone = function() { + let keys = Object.keys(this.words) + let words = keys.reduce((h, k) => { + let t = this.words[k].clone() + h[t.id] = t + return h + }, {}) + return new Pool(words) +} + +module.exports = Pool diff --git a/src/01-tokenizer/index.js b/src/01-tokenizer/index.js new file mode 100644 index 000000000..9383e2618 --- /dev/null +++ b/src/01-tokenizer/index.js @@ -0,0 +1,96 @@ +const Term = require('../Term/Term') +const Phrase = require('../Phrase/Phrase') +const Pool = require('./Pool') + +const splitSentences = require('./01-sentences') +const splitTerms = require('./02-words') + +//add forward/backward 'linked-list' prev/next ids +const addLinks = terms => { + terms.forEach((term, i) => { + if (i > 0) { + term.prev = terms[i - 1].id + } + if (terms[i + 1]) { + term.next = terms[i + 1].id + } + }) +} + +/** turn a string into an array of Phrase objects */ +const fromText = function(text = '', world, pool) { + //a bit of validation, first + if (typeof text !== 'string') { + if (typeof text === 'number') { + text = String(text) + } + } + //tokenize into words + let sentences = splitSentences(text, world) + sentences = sentences.map(str => splitTerms(str)) + + //turn them into proper objects + pool = pool || new Pool() + + let phrases = sentences.map(terms => { + terms = terms.map(str => { + let term = new Term(str) + pool.add(term) + return term + }) + //add next/previous ids + addLinks(terms) + + //return phrase objects + return new Phrase(terms[0].id, terms.length, pool) + }) + //return them ready for a Document object + return phrases +} + +// parse the compressed format '3,2|2,4' +const parseTags = function(text, tagList) { + return text.split('|').map(str => { + let numList = str.split(',') + numList = numList.map(n => parseInt(n, 10)) + // convert a list pf numbers into an array of tag names + return numList.map(num => { + if (!tagList[num]) { + console.warn('Compromise import: missing tag at index ' + num) + } + return tagList[num] + }) + }) +} + +/** create a word-pool and Phrase objects from .export() json*/ +const fromJSON = function(json, world) { + if (typeof json === 'string') { + json = JSON.parse(json) + } + let pool = new Pool() + //create Phrase objects + let phrases = json.list.map(o => { + // tokenize words from sentence text + let terms = splitTerms(o[0]) + // unpack the tag data for each term + let tagArr = parseTags(o[1], json.tags) + //create Term objects + terms = terms.map((str, i) => { + let term = new Term(str) + tagArr[i].forEach(tag => term.tag(tag, '', world)) + pool.add(term) + return term + }) + //add prev/next links + addLinks(terms) + // return a proper Phrase object + return new Phrase(terms[0].id, terms.length, pool) + }) + return phrases +} + +module.exports = { + fromText, + fromJSON, +} diff --git a/src/02-tagger/01-init/01-lexicon.js b/src/02-tagger/01-init/01-lexicon.js new file mode 100644 index 000000000..e29d18d14 --- /dev/null +++ b/src/02-tagger/01-init/01-lexicon.js @@ -0,0 +1,61 @@ +/** match a word-sequence, like 'super bowl' in the lexicon */ +const tryMultiple = function(terms, t, world) { + let lex = world.words + //try a two-word version + let txt = terms[t].reduced + ' ' + terms[t + 1].reduced + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-two', world) + terms[t + 1].tag(lex[txt], 'lexicon-two', world) + return 1 + } + //try a three-word version? + if (t + 2 < terms.length) { + txt += ' ' + terms[t + 2].reduced + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-three', world) + terms[t + 1].tag(lex[txt], 'lexicon-three', world) + terms[t + 2].tag(lex[txt], 'lexicon-three', world) + return 2 + } + } + //try a four-word version? + if (t + 3 < terms.length) { + txt += ' ' + terms[t + 3].reduced + if (lex[txt] !== undefined && lex.hasOwnProperty(txt) === true) { + terms[t].tag(lex[txt], 'lexicon-four', world) + terms[t + 1].tag(lex[txt], 'lexicon-four', world) + terms[t + 2].tag(lex[txt], 'lexicon-four', world) + terms[t + 3].tag(lex[txt], 'lexicon-four', world) + return 3 + } + } + return 0 +} + +/** look at each word in our list of known-words */ +const checkLexicon = function(terms, world) { + let lex = world.words + let hasCompound = world.hasCompound // use reduced? + //go through each term, and check the lexicon + for (let t = 0; t < terms.length; t += 1) { + let str = terms[t].clean + //is it the start of a compound word, like 'super bowl'? + if (hasCompound[str] === true && t + 1 < terms.length) { + let foundWords = tryMultiple(terms, t, world) + if (foundWords > 0) { + t += foundWords //skip any already-found words + continue + } + } + //try one-word lexicon + if (lex[str] !== undefined && lex.hasOwnProperty(str) === true) { + terms[t].tag(lex[str], 'lexicon', world) + } + // look at reduced version of term, too + if (str !== terms[t].reduced && lex.hasOwnProperty(terms[t].reduced) === true) { + terms[t].tag(lex[terms[t].reduced], 'lexicon', world) + } + } + return terms +} +module.exports = checkLexicon diff --git a/src/02-tagger/01-init/02-punctuation.js b/src/02-tagger/01-init/02-punctuation.js new file mode 100644 index 000000000..260523e8b --- /dev/null +++ b/src/02-tagger/01-init/02-punctuation.js @@ -0,0 +1,58 @@ +const apostrophes = /[\'‘’‛‵′`´]$/ +const oneLetterAcronym = /^[A-Z]('s|,)?$/ + +const oneLetterWord = { + I: true, + A: true, +} + +const isAcronym = function(term, world) { + let str = term.reduced + // a known acronym like fbi + if (term.tags.Acronym) { + return true + } + // if (term.tags.Adverb || term.tags.Verb || term.tags.Value || term.tags.Plural) { + // return false + // } + // 'PIZZA' is not an acronym. + if (str.length > 4 && world.words[str]) { + return false + } + return term.isAcronym() +} + +// +const checkPunctuation = function(terms, i, world) { + let term = terms[i] + + //check hyphenation + // if (term.post.indexOf('-') !== -1 && terms[i + 1] && terms[i + 1].pre === '') { + // term.tag('Hyphenated', 'has-hyphen', world) + // } + + //an end-tick (trailing apostrophe) - flanders', or Carlos' + if (apostrophes.test(term.text)) { + if (!apostrophes.test(term.pre) && !apostrophes.test(term.post) && term.clean.length > 2) { + let endChar = term.clean[term.clean.length - 2] + //flanders' + if (endChar === 's') { + term.tag(['Possessive', 'Noun'], 'end-tick', world) + return + } + //chillin' + if (endChar === 'n') { + term.tag(['Gerund'], 'chillin', world) + } + } + } + // 'NASA' is, but not 'i REALLY love it.' + if (isAcronym(term, world)) { + term.tag('Acronym', 'acronym-step', world) + term.tag('Noun', 'acronym-infer', world) + } else if (!oneLetterWord.hasOwnProperty(term.text) && oneLetterAcronym.test(term.text)) { + term.tag('Acronym', 'one-letter-acronym', world) + term.tag('Noun', 'one-letter-infer', world) + } +} +module.exports = checkPunctuation diff --git a/src/02-tagger/01-init/03-prefixes.js b/src/02-tagger/01-init/03-prefixes.js new file mode 100644 index 000000000..2de2ba9e3 --- /dev/null +++ b/src/02-tagger/01-init/03-prefixes.js @@ -0,0 +1,22 @@ +const regex = require('./data/startsWith') + +const romanNumeral = /^[IVXLCDM]{2,}$/ +const romanNumValid = /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/ // https://stackoverflow.com/a/267405/168877 + +//try each of the ^regexes in our list +const checkRegex = function(term, world) { + let str = term.text + // do them all! + for (let r = 0; r < regex.length; r += 1) { + if (regex[r][0].test(str) === true) { + term.tagSafe(regex[r][1], 'regex #' + r, world) + break + } + } + // do some more! + //roman numberals - XVII + if (term.text.length >= 2 && romanNumeral.test(str) && romanNumValid.test(str)) { + term.tag('RomanNumeral', 'xvii', world) + } +} +module.exports = checkRegex diff --git a/src/02-tagger/01-init/04-suffixes.js b/src/02-tagger/01-init/04-suffixes.js new file mode 100644 index 000000000..2d4ba640a --- /dev/null +++ b/src/02-tagger/01-init/04-suffixes.js @@ -0,0 +1,40 @@ +const endsWith = require('./data/endsWith') +const suffixMap = require('./data/suffixMap') + +const endRegexs = function(term, world) { + let str = term.clean + let char = str[str.length - 1] + if (endsWith.hasOwnProperty(char) === true) { + let regs = endsWith[char] + for (let r = 0; r < regs.length; r += 1) { + if (regs[r][0].test(str) === true) { + term.tagSafe(regs[r][1], `endReg ${char} #${r}`, world) + break + } + } + } +} + +//sweep-through all suffixes +const knownSuffixes = function(term, world) { + const len = term.clean.length + let max = 7 + if (len <= max) { + max = len - 1 + } + for (let i = max; i > 1; i -= 1) { + let str = term.clean.substr(len - i, len) + if (suffixMap[str.length].hasOwnProperty(str) === true) { + let tag = suffixMap[str.length][str] + term.tagSafe(tag, 'suffix -' + str, world) + break + } + } +} + +//all-the-way-down! +const checkRegex = function(term, world) { + knownSuffixes(term, world) + endRegexs(term, world) +} +module.exports = checkRegex diff --git a/src/02-tagger/01-init/05-emoji.js b/src/02-tagger/01-init/05-emoji.js new file mode 100644 index 000000000..20d9bad0d --- /dev/null +++ b/src/02-tagger/01-init/05-emoji.js @@ -0,0 +1,58 @@ +//from https://www.regextester.com/106421 +const emojiReg = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/ +const emoticon = require('./data/emoticons') +//for us, there's three types - +// * ;) - emoticons +// * 🌵 - unicode emoji +// * :smiling_face: - asci-represented emoji + +//test for forms like ':woman_tone2:‍:ear_of_rice:' +//https://github.com/Kikobeats/emojis-keywords/blob/master/index.js +const isCommaEmoji = raw => { + if (raw.charAt(0) === ':') { + //end comma can be last or second-last ':haircut_tone3:‍♀️' + if (raw.match(/:.?$/) === null) { + return false + } + //ensure no spaces + if (raw.match(' ')) { + return false + } + //reasonably sized + if (raw.length > 35) { + return false + } + return true + } + return false +} + +//check against emoticon whitelist +const isEmoticon = str => { + str = str.replace(/^[:;]/, ':') //normalize the 'eyes' + return emoticon.hasOwnProperty(str) +} + +const tagEmoji = (term, world) => { + let raw = term.pre + term.text + term.post + raw = raw.trim() + //test for :keyword: emojis + if (isCommaEmoji(raw) === true) { + term.tag('Emoji', 'comma-emoji', world) + term.text = raw + term.pre = term.pre.replace(':', '') + term.post = term.post.replace(':', '') + } + //test for unicode emojis + if (term.text.match(emojiReg)) { + term.tag('Emoji', 'unicode-emoji', world) + term.text = raw + } + //test for emoticon ':)' emojis + if (isEmoticon(raw) === true) { + term.tag('Emoticon', 'emoticon-emoji', world) + term.text = raw + } +} + +module.exports = tagEmoji diff --git a/src/02-tagger/01-init/data/emoticons.js b/src/02-tagger/01-init/data/emoticons.js new file mode 100644 index 000000000..0249317e4 --- /dev/null +++ b/src/02-tagger/01-init/data/emoticons.js @@ -0,0 +1,56 @@ +//just some of the most common emoticons +//faster than +//http://stackoverflow.com/questions/28077049/regex-matching-emoticons +module.exports = { + ':(': true, + ':)': true, + ':P': true, + ':p': true, + ':O': true, + ':3': true, + ':|': true, + ':/': true, + ':\\': true, + ':$': true, + ':*': true, + ':@': true, + ':-(': true, + ':-)': true, + ':-P': true, + ':-p': true, + ':-O': true, + ':-3': true, + ':-|': true, + ':-/': true, + ':-\\': true, + ':-$': true, + ':-*': true, + ':-@': true, + ':^(': true, + ':^)': true, + ':^P': true, + ':^p': true, + ':^O': true, + ':^3': true, + ':^|': true, + ':^/': true, + ':^\\': true, + ':^$': true, + ':^*': true, + ':^@': true, + '):': true, + '(:': true, + '$:': true, + '*:': true, + ')-:': true, + '(-:': true, + '$-:': true, + '*-:': true, + ')^:': true, + '(^:': true, + '$^:': true, + '*^:': true, + '<3': true, + ' lastTerm.tags[tag]) + if (foundTag !== undefined) { + let tag = markov.afterThisPos[foundTag] + term.tag(tag, 'after-' + foundTag, world) + continue + } + } + + //look at next word for clues.. + let nextTerm = terms[i + 1] + if (nextTerm) { + // 'term foobar' + if (markov.beforeThisWord.hasOwnProperty(nextTerm.clean) === true) { + let tag = markov.beforeThisWord[nextTerm.clean] + term.tag(tag, 'before-' + nextTerm.clean, world) + continue + } + // 'term Tag' + // (look at next POS tags for clues..) + let foundTag = beforeKeys.find(tag => nextTerm.tags[tag]) + if (foundTag !== undefined) { + let tag = markov.beforeThisPos[foundTag] + term.tag(tag, 'before-' + foundTag, world) + continue + } + } + } +} +module.exports = checkNeighbours diff --git a/src/02-tagger/02-fallbacks/02-case.js b/src/02-tagger/02-fallbacks/02-case.js new file mode 100644 index 000000000..97fb99b28 --- /dev/null +++ b/src/02-tagger/02-fallbacks/02-case.js @@ -0,0 +1,23 @@ +const titleCase = /^[A-Z][a-z'\u00C0-\u00FF]/ +const hasNumber = /[0-9]/ + +/** look for any grammar signals based on capital/lowercase */ +const checkCase = function(terms, world) { + terms.forEach((term, i) => { + //is it a titlecased word? + if (titleCase.test(term.text) === true && hasNumber.test(term.text) === false) { + // tag it as titlecase, if possible + if (i !== 0) { + term.tag('TitleCase', 'case', world) + } else if (term.tags.Person || term.tags.Organization || term.tags.Place) { + term.tag('TitleCase', 'case-person', world) + } + // can we call it a noun? + if (i !== 0) { + //sure! + term.tag('ProperNoun', 'case-noun', world) + } + } + }) +} +module.exports = checkCase diff --git a/src/02-tagger/02-fallbacks/03-stem.js b/src/02-tagger/02-fallbacks/03-stem.js new file mode 100644 index 000000000..059311bca --- /dev/null +++ b/src/02-tagger/02-fallbacks/03-stem.js @@ -0,0 +1,22 @@ +const hasPrefix = /^(re|un)-?[a-z\u00C0-\u00FF]/ +const prefix = /^(re|un)-?/ + +/** check 'rewatch' in lexicon as 'watch' */ +const checkPrefix = function(terms, world) { + let lex = world.words + terms.forEach(term => { + // skip if we have a good tag already + if (term.isKnown() === true) { + return + } + //does it start with 'un|re' + if (hasPrefix.test(term.clean) === true) { + // look for the root word in the lexicon: + let stem = term.clean.replace(prefix, '') + if (stem && stem.length > 3 && lex[stem] !== undefined && lex.hasOwnProperty(stem) === true) { + term.tag(lex[stem], 'stem-' + stem, world) + } + } + }) +} +module.exports = checkPrefix diff --git a/src/02-tagger/02-fallbacks/04-plurals.js b/src/02-tagger/02-fallbacks/04-plurals.js new file mode 100644 index 000000000..c27b66f69 --- /dev/null +++ b/src/02-tagger/02-fallbacks/04-plurals.js @@ -0,0 +1,51 @@ +//these tags don't have plurals +const noPlurals = ['Uncountable', 'Pronoun', 'Place', 'Value', 'Person', 'Month', 'WeekDay', 'Holiday'] +const rules = require('./data/isPlural') +const notPlural = [/ss$/, /sis$/, /[^aeiou][uo]s$/, /'s$/] +const notSingular = [/i$/, /ae$/] + +/** turn nouns into singular/plural */ +const checkPlural = function(t, world) { + if (t.tags.Noun && !t.tags.Acronym) { + let str = t.clean + //skip existing tags, fast + if (t.tags.Singular || t.tags.Plural) { + return + } + //too short + if (str.length <= 3) { + t.tag('Singular', 'short-singular', world) + return + } + //is it impossible to be plural? + if (noPlurals.find(tag => t.tags[tag])) { + return + } + // isPlural suffix rules + if (rules.isPlural.find(reg => reg.test(str))) { + t.tag('Plural', 'plural-rules', world) + return + } + // isSingular suffix rules + if (rules.isSingular.find(reg => reg.test(str))) { + t.tag('Singular', 'singular-rules', world) + return + } + + // finally, fallback 'looks plural' rules.. + if (/s$/.test(str) === true) { + //avoid anything too sketchy to be plural + if (notPlural.find(reg => reg.test(str))) { + return + } + t.tag('Plural', 'plural-fallback', world) + return + } + //avoid anything too sketchy to be singular + if (notSingular.find(reg => reg.test(str))) { + return + } + t.tag('Singular', 'singular-fallback', world) + } +} +module.exports = checkPlural diff --git a/src/02-tagger/02-fallbacks/05-organizations.js b/src/02-tagger/02-fallbacks/05-organizations.js new file mode 100644 index 000000000..cb7d71bbd --- /dev/null +++ b/src/02-tagger/02-fallbacks/05-organizations.js @@ -0,0 +1,44 @@ +let orgWords = require('./data/organizations') + +//could this word be an organization +const maybeOrg = function(t) { + //must be a noun + if (!t.tags.Noun) { + return false + } + //can't be these things + if (t.tags.Pronoun || t.tags.Comma || t.tags.Possessive) { + return false + } + //must be one of these + if (t.tags.Organization || t.tags.Acronym || t.tags.Place || t.titleCase()) { + return true + } + return false +} + +const tagOrgs = function(terms, world) { + for (let i = 0; i < terms.length; i += 1) { + let t = terms[i] + if (orgWords[t.clean] !== undefined && orgWords.hasOwnProperty(t.clean) === true) { + // look-backward - eg. 'Toronto University' + let lastTerm = terms[i - 1] + if (lastTerm !== undefined && maybeOrg(lastTerm) === true) { + lastTerm.tagSafe('Organization', 'org-word-1', world) + t.tagSafe('Organization', 'org-word-2', world) + continue + } + //look-forward - eg. University of Toronto + let nextTerm = terms[i + 1] + if (nextTerm !== undefined && nextTerm.clean === 'of') { + if (terms[i + 2] && maybeOrg(terms[i + 2])) { + t.tagSafe('Organization', 'org-of-word-1', world) + nextTerm.tagSafe('Organization', 'org-of-word-2', world) + terms[i + 2].tagSafe('Organization', 'org-of-word-3', world) + continue + } + } + } + } +} +module.exports = tagOrgs diff --git a/src/02-tagger/02-fallbacks/data/isPlural.js b/src/02-tagger/02-fallbacks/data/isPlural.js new file mode 100644 index 000000000..032cc940e --- /dev/null +++ b/src/02-tagger/02-fallbacks/data/isPlural.js @@ -0,0 +1,53 @@ +//similar to plural/singularize rules, but not the same +const isPlural = [ + /(^v)ies$/i, + /ises$/i, + /ives$/i, + /(antenn|formul|nebul|vertebr|vit)ae$/i, + /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, + /(buffal|tomat|tornad)oes$/i, + /(analy|ba|diagno|parenthe|progno|synop|the)ses$/i, + /(vert|ind|cort)ices$/i, + /(matr|append)ices$/i, + /(x|ch|ss|sh|s|z|o)es$/i, + /is$/i, + /men$/i, + /news$/i, + /.tia$/i, + /(^f)ves$/i, + /(lr)ves$/i, + /(^aeiouy|qu)ies$/i, + /(m|l)ice$/i, + /(cris|ax|test)es$/i, + /(alias|status)es$/i, + /ics$/i, +] + +//similar to plural/singularize rules, but not the same +const isSingular = [ + /(ax|test)is$/i, + /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, + /(octop|vir)i$/i, + /(rl)f$/i, + /(alias|status)$/i, + /(bu)s$/i, + /(al|ad|at|er|et|ed|ad)o$/i, + /(ti)um$/i, + /(ti)a$/i, + /sis$/i, + /(?:(^f)fe|(lr)f)$/i, + /hive$/i, + /s[aeiou]+ns$/i, // sans, siens + /(^aeiouy|qu)y$/i, + /(x|ch|ss|sh|z)$/i, + /(matr|vert|ind|cort)(ix|ex)$/i, + /(m|l)ouse$/i, + /(m|l)ice$/i, + /(antenn|formul|nebul|vertebr|vit)a$/i, + /.sis$/i, + /^(?!talis|.*hu)(.*)man$/i, +] +module.exports = { + isSingular: isSingular, + isPlural: isPlural, +} diff --git a/src/02-tagger/02-fallbacks/data/markov.js b/src/02-tagger/02-fallbacks/data/markov.js new file mode 100644 index 000000000..d60ff4c92 --- /dev/null +++ b/src/02-tagger/02-fallbacks/data/markov.js @@ -0,0 +1,71 @@ +//markov-like stats about co-occurance, for hints about unknown terms +//basically, a little-bit better than the noun-fallback +//just top n-grams from nlp tags, generated from nlp-corpus + +//after this word, here's what happens usually +let afterThisWord = { + i: 'Verb', //44% //i walk.. + first: 'Noun', //50% //first principles.. + it: 'Verb', //33% + there: 'Verb', //35% + not: 'Verb', //33% + because: 'Noun', //31% + if: 'Noun', //32% + but: 'Noun', //26% + who: 'Verb', //40% + this: 'Noun', //37% + his: 'Noun', //48% + when: 'Noun', //33% + you: 'Verb', //35% + very: 'Adjective', // 39% + old: 'Noun', //51% + never: 'Verb', //42% + before: 'Noun', //28% +} + +//in advance of this word, this is what happens usually +let beforeThisWord = { + there: 'Verb', //23% // be there + me: 'Verb', //31% //see me + man: 'Adjective', // 80% //quiet man + only: 'Verb', //27% //sees only + him: 'Verb', //32% //show him + were: 'Noun', //48% //we were + took: 'Noun', //38% //he took + himself: 'Verb', //31% //see himself + went: 'Noun', //43% //he went + who: 'Noun', //47% //person who + jr: 'Person', +} + +//following this POS, this is likely +let afterThisPOS = { + Adjective: 'Noun', //36% //blue dress + Possessive: 'Noun', //41% //his song + Determiner: 'Noun', //47% + Adverb: 'Verb', //20% + Pronoun: 'Verb', //40% + Value: 'Noun', //47% + Ordinal: 'Noun', //53% + Modal: 'Verb', //35% + Superlative: 'Noun', //43% + Demonym: 'Noun', //38% + Honorific: 'Person', // +} + +//in advance of this POS, this is likely +let beforeThisPOS = { + Copula: 'Noun', //44% //spencer is + PastTense: 'Noun', //33% //spencer walked + Conjunction: 'Noun', //36% + Modal: 'Noun', //38% + Pluperfect: 'Noun', //40% + PerfectTense: 'Verb', //32% +} +module.exports = { + beforeThisWord: beforeThisWord, + afterThisWord: afterThisWord, + + beforeThisPos: beforeThisPOS, + afterThisPos: afterThisPOS, +} diff --git a/src/02-tagger/02-fallbacks/data/organizations.js b/src/02-tagger/02-fallbacks/data/organizations.js new file mode 100644 index 000000000..81627d950 --- /dev/null +++ b/src/02-tagger/02-fallbacks/data/organizations.js @@ -0,0 +1,211 @@ +//nouns that also signal the title of an unknown organization +//todo remove/normalize plural forms +const orgWords = [ + 'academy', + 'administration', + 'agence', + 'agences', + 'agencies', + 'agency', + 'airlines', + 'airways', + 'army', + 'assoc', + 'associates', + 'association', + 'assurance', + 'authority', + 'autorite', + 'aviation', + 'bank', + 'banque', + 'board', + 'boys', + 'brands', + 'brewery', + 'brotherhood', + 'brothers', + 'building society', + 'bureau', + 'cafe', + 'caisse', + 'capital', + 'care', + 'cathedral', + 'center', + 'central bank', + 'centre', + 'chemicals', + 'choir', + 'chronicle', + 'church', + 'circus', + 'clinic', + 'clinique', + 'club', + 'co', + 'coalition', + 'coffee', + 'collective', + 'college', + 'commission', + 'committee', + 'communications', + 'community', + 'company', + 'comprehensive', + 'computers', + 'confederation', + 'conference', + 'conseil', + 'consulting', + 'containers', + 'corporation', + 'corps', + 'corp', + 'council', + 'crew', + 'daily news', + 'data', + 'departement', + 'department', + 'department store', + 'departments', + 'design', + 'development', + 'directorate', + 'division', + 'drilling', + 'education', + 'eglise', + 'electric', + 'electricity', + 'energy', + 'ensemble', + 'enterprise', + 'enterprises', + 'entertainment', + 'estate', + 'etat', + 'evening news', + 'faculty', + 'federation', + 'financial', + 'fm', + 'foundation', + 'fund', + 'gas', + 'gazette', + 'girls', + 'government', + 'group', + 'guild', + 'health authority', + 'herald', + 'holdings', + 'hospital', + 'hotel', + 'hotels', + 'inc', + 'industries', + 'institut', + 'institute', + 'institute of technology', + 'institutes', + 'insurance', + 'international', + 'interstate', + 'investment', + 'investments', + 'investors', + 'journal', + 'laboratory', + 'labs', + // 'law', + 'liberation army', + 'limited', + 'local authority', + 'local health authority', + 'machines', + 'magazine', + 'management', + 'marine', + 'marketing', + 'markets', + 'media', + 'memorial', + 'mercantile exchange', + 'ministere', + 'ministry', + 'military', + 'mobile', + 'motor', + 'motors', + 'musee', + 'museum', + // 'network', + 'news', + 'news service', + 'observatory', + 'office', + 'oil', + 'optical', + 'orchestra', + 'organization', + 'partners', + 'partnership', + // 'party', + "people's party", + 'petrol', + 'petroleum', + 'pharmacare', + 'pharmaceutical', + 'pharmaceuticals', + 'pizza', + 'plc', + 'police', + 'polytechnic', + 'post', + 'power', + 'press', + 'productions', + 'quartet', + 'radio', + 'regional authority', + 'regional health authority', + 'reserve', + 'resources', + 'restaurant', + 'restaurants', + 'savings', + 'school', + 'securities', + 'service', + 'services', + 'social club', + 'societe', + 'society', + 'sons', + 'standard', + 'state police', + 'state university', + 'stock exchange', + 'subcommittee', + 'syndicat', + 'systems', + 'telecommunications', + 'telegraph', + 'television', + 'times', + 'tribunal', + 'tv', + 'union', + 'university', + 'utilities', + 'workers', +] + +module.exports = orgWords.reduce(function(h, str) { + h[str] = 'Noun' + return h +}, {}) diff --git a/src/02-tagger/02-fallbacks/index.js b/src/02-tagger/02-fallbacks/index.js new file mode 100644 index 000000000..e37ca91c5 --- /dev/null +++ b/src/02-tagger/02-fallbacks/index.js @@ -0,0 +1,39 @@ +const step = { + neighbours: require('./01-neighbours'), + case: require('./02-case'), + stem: require('./03-stem'), + plural: require('./04-plurals'), + organizations: require('./05-organizations'), +} +// +const fallbacks = function(doc) { + let terms = doc.termList() + let world = doc.world + + // if it's empty, consult it's neighbours, first + step.neighbours(terms, world) + + // is there a case-sensitive clue? + step.case(terms, world) + + // check 'rewatch' as 'watch' + step.stem(terms, world) + + // ... fallback to a noun! + terms.forEach(t => { + if (t.isKnown() === false) { + t.tag('Noun', 'noun-fallback', doc.world) + } + }) + + // turn 'Foo University' into an Org + step.organizations(terms, world) + + //are the nouns singular or plural? + terms.forEach(t => { + step.plural(t, doc.world) + }) + + return doc +} +module.exports = fallbacks diff --git a/src/02-tagger/03-contractions/01-negative.js b/src/02-tagger/03-contractions/01-negative.js new file mode 100644 index 000000000..36805c034 --- /dev/null +++ b/src/02-tagger/03-contractions/01-negative.js @@ -0,0 +1,27 @@ +const hasNegative = /n't$/ + +const irregulars = { + "won't": ['will', 'not'], + wont: ['will', 'not'], + "can't": ['can', 'not'], + cant: ['can', 'not'], + cannot: ['can', 'not'], + "shan't": ['should', 'not'], + dont: ['do', 'not'], + dun: ['do', 'not'], + // "ain't" is ambiguous for is/was +} + +const checkNegative = function(term) { + //check named-ones + if (irregulars.hasOwnProperty(term.clean) === true) { + return irregulars[term.clean] + } + //try it normally + if (hasNegative.test(term.clean) === true) { + let main = term.clean.replace(hasNegative, '') + return [main, 'not'] + } + return null +} +module.exports = checkNegative diff --git a/src/02-tagger/03-contractions/02-simple.js b/src/02-tagger/03-contractions/02-simple.js new file mode 100644 index 000000000..f053926e6 --- /dev/null +++ b/src/02-tagger/03-contractions/02-simple.js @@ -0,0 +1,22 @@ +const contraction = /([a-z\u00C0-\u00FF]+)'([a-z]{1,2})$/i + +//these ones don't seem to be ambiguous +const easy = { + ll: 'will', + ve: 'have', + re: 'are', + m: 'am', + "n't": 'not', +} +// +const checkApostrophe = function(term) { + let parts = term.text.match(contraction) + if (parts === null) { + return null + } + if (easy.hasOwnProperty(parts[2])) { + return [parts[1], easy[parts[2]]] + } + return null +} +module.exports = checkApostrophe diff --git a/src/02-tagger/03-contractions/03-irregulars.js b/src/02-tagger/03-contractions/03-irregulars.js new file mode 100644 index 000000000..f79f73cc2 --- /dev/null +++ b/src/02-tagger/03-contractions/03-irregulars.js @@ -0,0 +1,59 @@ +const irregulars = { + wanna: ['want', 'to'], + gonna: ['going', 'to'], + im: ['i', 'am'], + alot: ['a', 'lot'], + ive: ['i', 'have'], + imma: ['I', 'will'], + + "where'd": ['where', 'did'], + whered: ['where', 'did'], + "when'd": ['when', 'did'], + whend: ['when', 'did'], + "how'd": ['how', 'did'], + howd: ['how', 'did'], + "what'd": ['what', 'did'], + whatd: ['what', 'did'], + // "let's": ['let', 'us'], //too weird + + //multiple word contractions + dunno: ['do', 'not', 'know'], + brb: ['be', 'right', 'back'], + gtg: ['got', 'to', 'go'], + irl: ['in', 'real', 'life'], + tbh: ['to', 'be', 'honest'], + imo: ['in', 'my', 'opinion'], + til: ['today', 'i', 'learned'], + rn: ['right', 'now'], + twas: ['it', 'was'], + '@': ['at'], +} + +// either 'is not' or 'are not' +const doAint = function(term, phrase) { + let terms = phrase.terms() + let index = terms.indexOf(term) + let before = terms.slice(0, index) + //look for the preceding noun + let noun = before.find(t => { + return t.tags.Noun + }) + if (noun && noun.tags.Plural) { + return ['are', 'not'] + } + return ['is', 'not'] +} + +// +const checkIrregulars = function(term, phrase) { + //this word needs it's own logic: + if (term.clean === `ain't` || term.clean === 'aint') { + return doAint(term, phrase) + } + //check white-list + if (irregulars.hasOwnProperty(term.clean)) { + return irregulars[term.clean] + } + return null +} +module.exports = checkIrregulars diff --git a/src/02-tagger/03-contractions/04-possessive.js b/src/02-tagger/03-contractions/04-possessive.js new file mode 100644 index 000000000..ed115689a --- /dev/null +++ b/src/02-tagger/03-contractions/04-possessive.js @@ -0,0 +1,78 @@ +const hasApostropheS = /([a-z\u00C0-\u00FF]+)'s$/i + +const blacklist = { + that: true, + there: true, +} +const isPossessive = (term, pool) => { + // if we already know it + if (term.tags.Possessive) { + return true + } + //a pronoun can't be possessive - "he's house" + if (term.tags.Pronoun || term.tags.QuestionWord) { + return false + } + if (blacklist.hasOwnProperty(term.clean)) { + return false + } + //if end of sentence, it is possessive - "was spencer's" + let nextTerm = pool.get(term.next) + if (!nextTerm) { + return true + } + //a gerund suggests 'is walking' + if (nextTerm.tags.Verb) { + //fix 'jamie's bite' + if (nextTerm.tags.Infinitive) { + return true + } + return false + } + + //spencer's house + if (nextTerm.tags.Noun) { + return true + } + //rocket's red glare + let twoTerm = pool.get(nextTerm.next) + if (twoTerm && twoTerm.tags.Noun && !twoTerm.tags.Pronoun) { + return true + } + //othwerwise, an adjective suggests 'is good' + if (nextTerm.tags.Adjective || nextTerm.tags.Adverb || nextTerm.tags.Verb) { + return false + } + return false +} + +const isHas = (term, phrase) => { + let terms = phrase.terms() + let index = terms.indexOf(term) + let after = terms.slice(index + 1, index + 3) + //look for a past-tense verb + return after.find(t => { + return t.tags.PastTense + }) +} + +const checkPossessive = function(term, phrase, world) { + //the rest of 's + let found = term.text.match(hasApostropheS) + if (found !== null) { + //spencer's thing vs spencer-is + if (isPossessive(term, phrase.pool) === true) { + term.tag('#Possessive', 'isPossessive', world) + return null + } + //'spencer is' + if (found !== null) { + if (isHas(term, phrase)) { + return [found[1], 'has'] + } + return [found[1], 'is'] + } + } + return null +} +module.exports = checkPossessive diff --git a/src/02-tagger/03-contractions/05-perfectTense.js b/src/02-tagger/03-contractions/05-perfectTense.js new file mode 100644 index 000000000..153f274a8 --- /dev/null +++ b/src/02-tagger/03-contractions/05-perfectTense.js @@ -0,0 +1,26 @@ +const hasPerfect = /[a-z\u00C0-\u00FF]'d$/ + +/** split `i'd` into 'i had', or 'i would' */ +const checkPerfect = function(term, phrase) { + if (hasPerfect.test(term.clean)) { + let root = term.clean.replace(/'d$/, '') + //look at the next few words + let terms = phrase.terms() + let index = terms.indexOf(term) + let after = terms.slice(index + 1, index + 4) + //is it before a past-tense verb? - 'i'd walked' + for (let i = 0; i < after.length; i++) { + let t = after[i] + if (t.tags.Verb) { + if (t.tags.PastTense) { + return [root, 'had'] + } + return [root, 'would'] + } + } + //otherwise, 'i'd walk' + return [root, 'would'] + } + return null +} +module.exports = checkPerfect diff --git a/src/02-tagger/03-contractions/06-ranges.js b/src/02-tagger/03-contractions/06-ranges.js new file mode 100644 index 000000000..11d58d1cd --- /dev/null +++ b/src/02-tagger/03-contractions/06-ranges.js @@ -0,0 +1,14 @@ +const isRange = /^([0-9]+)[-–—]([0-9]+)$/i + +//split '2-4' into '2 to 4' +const checkRange = function(term) { + if (term.tags.PhoneNumber === true) { + return null + } + let parts = term.text.match(isRange) + if (parts !== null) { + return [parts[1], 'to', parts[2]] + } + return null +} +module.exports = checkRange diff --git a/src/02-tagger/03-contractions/index.js b/src/02-tagger/03-contractions/index.js new file mode 100644 index 000000000..d2053aa34 --- /dev/null +++ b/src/02-tagger/03-contractions/index.js @@ -0,0 +1,60 @@ +const checkLexicon = require('../01-init/01-lexicon') +const tokenize = require('../../01-tokenizer') +const checkNegative = require('./01-negative') +const checkApostrophe = require('./02-simple') +const checkIrregulars = require('./03-irregulars') +const checkPossessive = require('./04-possessive') +const checkPerfect = require('./05-perfectTense') +const checkRange = require('./06-ranges') +const isNumber = /^[0-9]+$/ + +const createPhrase = function(found, doc) { + //create phrase from ['would', 'not'] + let phrase = tokenize.fromText(found.join(' '), doc.world, doc.pool())[0] + //tag it + let terms = phrase.terms() + checkLexicon(terms, doc.world) + //make these terms implicit + terms.forEach(t => { + t.implicit = t.text + t.text = '' + t.clean = '' + // remove whitespace for implicit terms + t.pre = '' + t.post = '' + // tag number-ranges + if (isNumber.test(t.implicit)) { + t.tags.Number = true + t.tags.Cardinal = true + } + }) + return phrase +} + +const contractions = function(doc) { + let world = doc.world + doc.list.forEach(p => { + let terms = p.terms() + for (let i = 0; i < terms.length; i += 1) { + let term = terms[i] + let found = checkNegative(term) + found = found || checkApostrophe(term) + found = found || checkIrregulars(term, p) + found = found || checkPossessive(term, p, world) + found = found || checkPerfect(term, p) + found = found || checkRange(term, p) + //add them in + if (found !== null) { + let newPhrase = createPhrase(found, doc) + //set text as contraction + let firstTerm = newPhrase.terms(0) + firstTerm.text = term.text + //grab sub-phrase to remove + let match = p.buildFrom(term.id, 1, doc.pool()) + match.replace(newPhrase, doc, true) + } + } + }) + return doc +} +module.exports = contractions diff --git a/src/02-tagger/04-correction/fixAdjective.js b/src/02-tagger/04-correction/fixAdjective.js new file mode 100644 index 000000000..435140ecf --- /dev/null +++ b/src/02-tagger/04-correction/fixAdjective.js @@ -0,0 +1,24 @@ +// +const fixAdjective = function(doc) { + let adj = doc.if('#Adjective') + if (adj.found) { + //still good + adj.match('[still] #Adjective').tag('Adverb', 'still-advb') + //barely even walk + adj.match('(barely|hardly) even').tag('#Adverb', 'barely-even') + //big dreams, critical thinking + adj.match('#Adjective [#PresentTense]').tag('Noun', 'adj-presentTense') + //will secure our + adj.match('will [#Adjective]').tag('Verb', 'will-adj') + //cheering hard - dropped -ly's + adj.match('#PresentTense [(hard|quick|long|bright|slow)]').tag('Adverb', 'lazy-ly') + //his fine + adj.match('(his|her|its) [#Adjective]').tag('Noun', 'his-fine') + //he left + adj.match('#Noun #Adverb? [left]').tag('PastTense', 'left-verb') + //he disguised the thing + adj.match('#Pronoun [#Adjective] #Determiner #Adjective? #Noun').tag('Verb', 'he-adj-the') + } + return doc +} +module.exports = fixAdjective diff --git a/src/02-tagger/04-correction/fixDates.js b/src/02-tagger/04-correction/fixDates.js new file mode 100644 index 000000000..b4c4c3501 --- /dev/null +++ b/src/02-tagger/04-correction/fixDates.js @@ -0,0 +1,140 @@ +const preps = '(in|by|before|during|on|until|after|of|within|all)' //6 +const people = '(january|april|may|june|summer|autumn|jan|sep)' //ambiguous month-names +const verbs = '(may|march)' //ambiguous month-verbs + +const fixDates = function(doc) { + //ambiguous month - person forms + let person = doc.if(people) + if (person.found === true) { + //give to april + person.match(`#Infinitive #Determiner? #Adjective? #Noun? (to|for) [${people}]`).tag('Person', 'ambig-person') + //remind june + person.match(`#Infinitive [${people}]`).tag('Person', 'infinitive-person') + //may waits for + person.match(`[${people}] #PresentTense (to|for)`).tag('Person', 'ambig-active') + //april will + person.match(`[${people}] #Modal`).tag('Person', 'ambig-modal') + //would april + person.match(`#Modal [${people}]`).tag('Person', 'modal-ambig') + //with april + person.match(`(that|with|for) [${people}]`).tag('Person', 'that-month') + //it is may + person.match(`#Copula [${people}]`).tag('Person', 'is-may') + //may is + person.match(`[${people}] #Copula`).tag('Person', 'may-is') + //april the 5th + person.match(`[${people}] the? #Value`).tag('Month', 'person-value') + //wednesday april + person.match(`#Date [${people}]`).tag('Month', 'correction-may') + //may 5th + person.match(`[${people}] the? #Value`).tag('Month', 'may-5th') + //5th of may + person.match(`#Value of [${people}]`).tag('Month', '5th-of-may') + //by april + person + .match(`${preps} [${people}]`) + .ifNo('#Holiday') + .tag('Month', 'preps-month') + //this april + person.match(`(next|this|last) [${people}]`).tag('Month', 'correction-may') //maybe not 'this' + } + + //ambiguous month - verb-forms + let verb = doc.if(verbs) + if (verb.found === true) { + //quickly march + verb.match(`#Adverb [${verbs}]`).tag('Infinitive', 'ambig-verb') + verb.match(`${verbs} [#Adverb]`).tag('Infinitive', 'ambig-verb') + //all march + verb.match(`${preps} [${verbs}]`).tag('Month', 'in-month') + //this march + verb.match(`(next|this|last) [${verbs}]`).tag('Month', 'this-month') + //with date + verb.match(`[${verbs}] the? #Value`).tag('Month', 'march-5th') + verb.match(`#Value of? [${verbs}]`).tag('Month', '5th-of-march') + //nearby + verb.match(`[${verbs}] .? #Date`).tag('Month', 'march-and-feb') + verb.match(`#Date .? [${verbs}]`).tag('Month', 'feb-and-march') + + let march = doc.if('march') + if (march.found === true) { + //march to + march.match('[march] (up|down|back|to|toward)').tag('Infinitive', 'march-to') + //must march + march.match('#Modal [march]').tag('Infinitive', 'must-march') + } + } + //sun 5th + let sun = doc.if('sun') + if (sun.found === true) { + //sun feb 2 + sun.match('[sun] #Date').tag('WeekDay', 'sun-feb') + //sun the 5th + sun + .match('sun the #Ordinal') + .tag('Date') + .firstTerm() + .tag('WeekDay', 'sun-the-5th') + //the sun + sun.match('#Determiner [sun]').tag('Singular', 'the-sun') + } + + //sat, nov 5th + let sat = doc.if('sat') + if (sat.found) { + //sat november + sat.match('[sat] #Date').tag('WeekDay', 'sat-feb') + //this sat + sat.match(`${preps} [sat]`).tag('WeekDay', 'sat') + } + + //months: + let month = doc.if('#Month') + if (month.found === true) { + //June 5-7th + month.match(`#Month #DateRange+`).tag('Date', 'correction-numberRange') + //5th of March + month.match('#Value of #Month').tag('Date', 'value-of-month') + //5 March + month.match('#Cardinal #Month').tag('Date', 'cardinal-month') + //march 5 to 7 + month.match('#Month #Value to #Value').tag('Date', 'value-to-value') + //march the 12th + month.match('#Month the #Value').tag('Date', 'month-the-value') + } + + //months: + let val = doc.if('#Value') + if (val.found === true) { + //values + val.match('#Value #Abbreviation').tag('Value', 'value-abbr') + //seven point five + val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value') + //minus 7 + val.match('(minus|negative) #Value').tag('Value', 'minus-value') + // ten grand + val.match('#Value grand').tag('Value', 'value-grand') + //quarter million + val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal') + //june 7 + val + .match('(#WeekDay|#Month) #Value') + .ifNo('#Money') + .tag('Date', 'date-value') + + //7 june + val + .match('#Value (#WeekDay|#Month)') + .ifNo('#Money') + .tag('Date', 'value-date') + + //may twenty five + val + .match('#TextValue #TextValue') + .if('#Date') + .tag('#Date', 'textvalue-date') + } + + return doc +} +module.exports = fixDates diff --git a/src/02-tagger/04-correction/fixMisc.js b/src/02-tagger/04-correction/fixMisc.js new file mode 100644 index 000000000..35d93a82e --- /dev/null +++ b/src/02-tagger/04-correction/fixMisc.js @@ -0,0 +1,143 @@ +//mostly pos-corections here +const miscCorrection = function(doc) { + //misc: + //foot/feet + doc.match('(foot|feet)').tag('Noun', 'foot-noun') + // blood, sweat, and tears + doc.match('(#Noun && @hasComma) #Noun (and|or) [#PresentTense]').tag('#Noun', 'noun-list') + //3 feet + doc.match('#Value [(foot|feet)]').tag('Unit', 'foot-unit') + //'u' as pronoun + doc.match('#Conjunction [u]').tag('Pronoun', 'u-pronoun-2') + //6 am + doc.match('#Holiday (day|eve)').tag('Holiday', 'holiday-day') + // the captain who + doc.match('#Noun [(who|whom)]').tag('Determiner', 'captain-who') + //timezones + doc.match('(standard|daylight|summer|eastern|pacific|central|mountain) standard? time').tag('Time', 'timezone') + //Brazilian pesos + doc.match('#Demonym #Currency').tag('Currency', 'demonym-currency') + //about to go + doc.match('[about to] #Adverb? #Verb').tag(['Auxiliary', 'Verb'], 'about-to') + //right of way + doc.match('(right|rights) of .').tag('Noun', 'right-of') + // a bit + doc.match('[much] #Adjective').tag('Adverb', 'bit-1') + doc.match('a [bit]').tag('Noun', 'bit-2') + doc.match('a bit much').tag('Determiner Adverb Adjective', 'bit-3') + doc.match('too much').tag('Adverb Adjective', 'bit-4') + // u r cool + doc.match('u r').tag('Pronoun #Copula', 'u r') + // well, ... + doc.match('^(well|so|okay)').tag('Expression', 'well-') + + // some conditional statements + let m = doc.clauses() + + // had he survived, + m.match('^had #Noun+ #PastTense') + .firstTerm() + .tag('Condition', 'had-he') + // were he to survive + m.match('^were #Noun+ to #Infinitive') + .firstTerm() + .tag('Condition', 'were-he') + + //swear-words as non-expression POS + //nsfw + doc.match('holy (shit|fuck|hell)').tag('Expression', 'swears-expression') + doc.match('#Determiner [(shit|damn|hell)]').tag('Noun', 'swears-noun') + doc.match('[(shit|damn|fuck)] (#Determiner|#Possessive|them)').tag('Verb', 'swears-verb') + doc + .match('#Copula fucked up?') + .not('#Copula') + .tag('Adjective', 'swears-adjective') + + //ambig prepositions/conjunctions + let so = doc.if('so') + if (so.found === true) { + //so funny + so.match('[so] #Adjective').tag('Adverb', 'so-adv') + //so the + so.match('[so] #Noun').tag('Conjunction', 'so-conj') + //do so + so.match('do [so]').tag('Noun', 'so-noun') + } + + let all = doc.if('all') + if (all.found === true) { + //all students + all.match('[all] #Determiner? #Noun').tag('Adjective', 'all-noun') + //it all fell apart + all.match('[all] #Verb').tag('Adverb', 'all-verb') + } + + //the ambiguous word 'that' and 'which' + let which = doc.if('which') + if (which.found === true) { + //remind john that + which.match('#Verb #Adverb? #Noun [(that|which)]').tag('Preposition', 'that-prep') + //that car goes + which.match('that #Noun [#Verb]').tag('Determiner', 'that-determiner') + //work, which has been done. + which.match('@hasComma [which] (#Pronoun|#Verb)').tag('Preposition', 'which-copula') + } + + //like + let like = doc.if('like') + if (like.found === true) { + like.match('just [like]').tag('Preposition', 'like-preposition') + //folks like her + like.match('#Noun [like] #Noun').tag('Preposition', 'noun-like') + //look like + like.match('#Verb [like]').tag('Adverb', 'verb-like') + //exactly like + like + .match('#Adverb like') + .notIf('(really|generally|typically|usually|sometimes|often) [like]') + .tag('Adverb', 'adverb-like') + } + + let title = doc.if('@titleCase') + if (title.found === true) { + //FitBit Inc + title.match('@titleCase (ltd|co|inc|dept|assn|bros)').tag('Organization', 'org-abbrv') + //Foo District + title + .match('@titleCase+ (district|region|province|county|prefecture|municipality|territory|burough|reservation)') + .tag('Region', 'foo-district') + //District of Foo + title + .match('(district|region|province|municipality|territory|burough|state) of @titleCase') + .tag('Region', 'district-of-Foo') + } + + let hyph = doc.if('@hasHyphen') + if (hyph.found === true) { + //air-flow + hyph + .match('@hasHyphen .') + .match('#Noun #Verb') + .tag('Noun', 'hyphen-verb') + //connect hyphenated expressions - 'ooh-wee' + hyph + .if('#Expression') + .match('@hasHyphen+') + .tag('Expression', 'ooh-wee') + } + + let place = doc.if('#Place') + if (place.found === true) { + //West Norforlk + place.match('(west|north|south|east|western|northern|southern|eastern)+ #Place').tag('Region', 'west-norfolk') + //some us-state acronyms (exlude: al, in, la, mo, hi, me, md, ok..) + place + .match('#City [#Acronym]') + .match('(al|ak|az|ar|ca|ct|dc|fl|ga|id|il|nv|nh|nj|ny|oh|or|pa|sc|tn|tx|ut|vt|pr)') + .tag('Region', 'us-state') + } + + return doc +} + +module.exports = miscCorrection diff --git a/src/02-tagger/04-correction/fixNouns.js b/src/02-tagger/04-correction/fixNouns.js new file mode 100644 index 000000000..c50fb697f --- /dev/null +++ b/src/02-tagger/04-correction/fixNouns.js @@ -0,0 +1,95 @@ +// +const fixNouns = function(doc) { + let noun = doc.if('#Noun') + if (noun.found === true) { + //'more' is not always an adverb + noun.match('more #Noun').tag('Noun', 'more-noun') + //he quickly foo + noun.match('#Noun #Adverb [#Noun]').tag('Verb', 'quickly-foo') + //fix for busted-up phrasalVerbs + noun.match('#Noun [#Particle]').tag('Preposition', 'repair-noPhrasal') + //John & Joe's + noun.match('#Noun (&|n) #Noun').tag('Organization', 'Noun-&-Noun') + //Aircraft designer + noun.match('#Noun #Actor').tag('Actor', 'thing-doer') + //j.k Rowling + doc.match('#Noun van der? #Noun').tagSafe('#Person', 'von der noun') + //king of spain + doc.match('(king|queen|prince|saint|lady) of? #Noun').tagSafe('#Person', 'king-of-noun') + // addresses + doc.match('#Value #Noun (st|street|rd|road|crescent|cr|way|tr|terrace|avenue|ave)').tag('Address') + // schools + doc.match('#Noun+ (public|private) school').tag('School') + //the word 'second' + noun + .match('[second] #Noun') + .notIf('#Honorific') + .unTag('Unit') + .tag('Ordinal', 'second-noun') + //linear algebra + noun + .match('(#Determiner|#Value) [(linear|binary|mobile|lexical|technical|computer|scientific|formal)] #Noun') + .tag('Noun', 'technical-noun') + + //organization + let org = noun.if('#Organization') + if (org.found === true) { + org.match('#Organization of the? @titleCase').tagSafe('Organization', 'org-of-place') + org.match('#Organization #Country').tag('Organization', 'org-country') + org.match('(world|global|international|national|#Demonym) #Organization').tag('Organization', 'global-org') + org + .match('#TitleCase #Organization') + .ifNo('@hasComma') + .tag('Organization', 'titlecase-org') + } + + let plural = noun.if('#Plural') + if (plural.found === true) { + //some pressing issues + plural.match('some [#Verb] #Plural').tag('Noun', 'correction-determiner6') + + //this rocks + noun.match('(this|that) [#Plural]').tag('PresentTense', 'this-verbs') + } + } + + //acronyms + let acronym = doc.if('#Acronym') + if (acronym.found === true) { + acronym + .match('the [#Acronym]') + .notIf('(iou|fomo|yolo|diy|dui|nimby)') + .tag('Organization', 'the-acronym') + acronym + .match('#Acronym') + .match('#Possessive') + .tag('Organization', 'possessive-acronym') + } + + //possessives + let poss = doc.if('#Possessive') + if (poss.found === true) { + //my buddy + poss.match('#Possessive [#FirstName]').unTag('Person', 'possessive-name') + //spencer kelly's + poss + .match('#FirstName #Acronym? #Possessive') + .ifNo('@hasComma') + .match('#FirstName #Acronym? #LastName') + .tag('Possessive') + //Super Corp's fundraiser + poss + .match('#Organization+ #Possessive') + .ifNo('@hasComma') + .tag('Possessive') + //Los Angeles's fundraiser + poss + .match('#Place+ #Possessive') + .ifNo('@hasComma') + .tag('Possessive') + //her polling + poss.match('#Possessive [#Verb]').tag('Noun', 'correction-possessive') + } + return doc +} +module.exports = fixNouns diff --git a/src/02-tagger/04-correction/fixPerson.js b/src/02-tagger/04-correction/fixPerson.js new file mode 100644 index 000000000..acd48b5c9 --- /dev/null +++ b/src/02-tagger/04-correction/fixPerson.js @@ -0,0 +1,202 @@ +const maybeNoun = + '(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)' +const maybeVerb = '(pat|wade|ollie|will|rob|buck|bob|mark|jack)' +const maybeAdj = '(misty|rusty|dusty|rich|randy)' +const maybeDate = '(april|june|may|jan|august|eve)' +const maybePlace = '(paris|alexandria|houston|kobe|salvador|sydney)' + +const fixPerson = function(doc) { + // clues from honorifics + let hon = doc.if('#Honorific') + if (hon.found === true) { + //mr Putin + doc.match('(mr|mrs|ms|dr) (#TitleCase|#Possessive)+').tag('#Person', 'mr-putin') + //mr X + hon.match('#Honorific #Acronym').tag('Person', 'Honorific-TitleCase') + //remove single 'mr' + hon.match('^#Honorific$').unTag('Person', 'single-honorific') + //first general.. + hon.match('[(1st|2nd|first|second)] #Honorific').tag('Honorific', 'ordinal-honorific') + } + + //methods requiring a titlecase + let title = doc.if('#TitleCase') + if (title.found === true) { + title.match('#Acronym #TitleCase').tagSafe('#Person', 'acronym-titlecase') + //ludwig van beethovan + title.match('#TitleCase (van|al|bin) #TitleCase').tagSafe('Person', 'titlecase-van-titlecase') + //jose de Sucre + title.match('#TitleCase (de|du) la? #TitleCase').tagSafe('Person', 'titlecase-van-titlecase') + + //pope francis + title + .match('(lady|queen|sister) #TitleCase') + .ifNo('#Date') + .ifNo('#Honorific') + .tag('#FemaleName', 'lady-titlecase') + title + .match('(king|pope|father) #TitleCase') + .ifNo('#Date') + .tag('#MaleName', 'poe') + + // jean Foobar + title.match(maybeNoun + ' #Acronym? #TitleCase').tagSafe('Person', 'ray-smith') + // rob Foobar + title.match(maybeVerb + ' #Acronym? #TitleCase').tag('Person', 'rob-smith') + // rusty Foobar + title.match(maybeAdj + ' #Acronym? #TitleCase').tag('Person', 'rusty-smith') + // june Foobar + title.match(maybeDate + ' #Acronym? (#TitleCase && !#Month)').tagSafe('Person', 'june-smith') + } + + let person = doc.if('#Person') + if (person.found === true) { + //Frank jr + person.match('#Person (jr|sr|md)').tag('Person', 'person-honorific') + //peter II + person.match('#Person #Person the? #RomanNumeral').tag('Person', 'roman-numeral') + //'Professor Fink', 'General McCarthy' + person.match('#Honorific #Person').tag('Person', 'Honorific-Person') + // 'john E rockefeller' + person.match('#FirstName [/^[^aiurck]$/]').tag(['Acronym', 'Person'], 'john-e') + //Doctor john smith jr + person.match('#Honorific #Person').tag('Person', 'honorific-person') + //general pearson + person + .match('[(private|general|major|corporal|lord|lady|secretary|premier)] #Honorific? #Person') + .tag('Honorific', 'ambg-honorifics') + //Morgan Shlkjsfne + title + .match('#Person #TitleCase') + .match('#TitleCase #Noun') + .tagSafe('Person', 'person-titlecase') + //a bunch of ambiguous first names + + //Nouns: 'viola' or 'sky' + let ambigNoun = person.if(maybeNoun) + if (ambigNoun.found === true) { + // ambigNoun.match('(#Determiner|#Adverb|#Pronoun|#Possessive) [' + maybeNoun + ']').tag('Noun', 'the-ray') + ambigNoun.match(maybeNoun + ' #Person').tagSafe('Person', 'ray-smith') + } + + //Verbs: 'pat' or 'wade' + let ambigVerb = person.if(maybeVerb) + if (ambigVerb === true) { + ambigVerb.match('(#Modal|#Adverb) [' + maybeVerb + ']').tag('Verb', 'would-mark') + ambigVerb.match(maybeVerb + ' #Person').tag('Person', 'rob-smith') + } + + //Adjectives: 'rusty' or 'rich' + let ambigAdj = person.if(maybeAdj) + if (ambigAdj.found === true) { + ambigAdj.match('#Adverb [' + maybeAdj + ']').tag('Adjective', 'really-rich') + ambigAdj.match(maybeAdj + ' #Person').tag('Person', 'randy-smith') + } + + //Dates: 'june' or 'may' + let ambigDate = person.if(maybeDate) + if (ambigDate.found === true) { + ambigDate.match(String(maybeDate) + ' #Person').tagSafe('Person', 'june-smith') + ambigDate.match('(in|during|on|by|before|#Date) [' + maybeDate + ']').tagSafe('Date', 'in-june') + ambigDate.match(maybeDate + ' (#Date|#Value)').tagSafe('Date', 'june-5th') + } + + //Places: paris or syndey + let ambigPlace = person.if(maybePlace) + if (ambigPlace.found === true) { + ambigPlace.match('(in|near|at|from|to|#Place) [' + maybePlace + ']').tagSafe('Place', 'in-paris') + ambigPlace.match('[' + maybePlace + '] #Place').tagSafe('Place', 'paris-france') + // ambigPlace.match('[' + maybePlace + '] #Person').tagSafe('Person', 'paris-hilton') + } + + //this one is tricky + let al = person.if('al') + if (al.found === true) { + al.match('al (#Person|#TitleCase)').tagSafe('#Person', 'al-borlen') + al.match('#TitleCase al #TitleCase').tagSafe('#Person', 'arabic-al-arabic') + } + + let firstName = person.if('#FirstName') + if (firstName.found === true) { + //ferdinand de almar + firstName.match('#FirstName de #Noun').tag('#Person', 'firstname-de-noun') + //Osama bin Laden + firstName.match('#FirstName (bin|al) #Noun').tag('#Person', 'firstname-al-noun') + //John L. Foo + firstName.match('#FirstName #Acronym #TitleCase').tag('Person', 'firstname-acronym-titlecase') + //Andrew Lloyd Webber + firstName.match('#FirstName #FirstName #TitleCase').tag('Person', 'firstname-firstname-titlecase') + //Mr Foo + firstName.match('#Honorific #FirstName? #TitleCase').tag('Person', 'Honorific-TitleCase') + //peter the great + firstName.match('#FirstName the #Adjective').tag('Person', 'determiner5') + + //very common-but-ambiguous lastnames + firstName + .match('#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)') + .tag('#Person', 'firstname-maybe') + + //John Foo + firstName + .match('#FirstName #TitleCase #TitleCase?') + .match('#Noun+') + .tag('Person', 'firstname-titlecase') + //Joe K. Sombrero + firstName + .match('#FirstName #Acronym #Noun') + .ifNo('#Date') + .tag('#Person', 'n-acro-noun') + .lastTerm() + .tag('#LastName', 'n-acro-noun') + + // Dwayne 'the rock' Johnson + firstName + .match('#FirstName [#Determiner #Noun] #LastName') + .tag('#NickName', 'first-noun-last') + .tag('#Person', 'first-noun-last') + + //john bodego's + firstName + .match('#FirstName (#Singular|#Possessive)') + .ifNo('(#Date|#Pronoun|#NickName)') + .tag('#Person', 'first-possessive') + .lastTerm() + .tag('#LastName', 'first-possessive') + + // Firstname x (dangerous) + let tmp = firstName + .match('#FirstName (#Noun|#TitleCase)') + .ifNo('^#Possessive') + .ifNo('#ClauseEnd .') + .ifNo('#Pronoun') + tmp.lastTerm().tag('#LastName', 'firstname-noun') + } + + let lastName = person.if('#LastName') + if (lastName.found === true) { + //is foo Smith + lastName.match('#Copula [(#Noun|#PresentTense)] #LastName').tag('#FirstName', 'copula-noun-lastname') + // x Lastname + lastName + .match('[#Noun] #LastName') + .canBe('#FirstName') + .tag('#FirstName', 'noun-lastname') + //ambiguous-but-common firstnames + lastName + .match( + '[(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill)] #LastName' + ) + .tag('#FirstName', 'maybe-lastname') + //Jani K. Smith + lastName + .match('(#TitleCase|#Singular) #Acronym? #LastName') + .ifNo('#Date') + .tag('#Person', 'title-acro-noun') + .lastTerm() + .tag('#LastName', 'title-acro-noun') + } + } + + return doc +} +module.exports = fixPerson diff --git a/src/02-tagger/04-correction/fixThe.js b/src/02-tagger/04-correction/fixThe.js new file mode 100644 index 000000000..00b786170 --- /dev/null +++ b/src/02-tagger/04-correction/fixThe.js @@ -0,0 +1,66 @@ +//Determiner-signals +const fixThe = function(doc) { + let det = doc.if('#Determiner') + + if (det.found === true) { + let adj = det.if('#Adjective') + if (adj.found) { + //the nice swim + adj.match('(the|this|those|these) #Adjective [#Verb]').tag('Noun', 'the-adj-verb') + // the truly nice swim + adj.match('(the|this|those|these) #Adverb #Adjective [#Verb]').tag('Noun', 'correction-determiner4') + //the orange is + adj.match('#Determiner [#Adjective] (#Copula|#PastTense|#Auxiliary)').tag('Noun', 'the-adj-2') + //the orange. + adj + .match('#Determiner #Adjective$') + .notIf('(#Comparative|#Superlative)') + .terms(1) + .tag('Noun', 'the-adj-1') + } + + let inf = det.if('#Infinitive') + if (inf.found) { + // a stream runs + inf.match('(the|this|a|an) [#Infinitive] #Adverb? #Verb').tag('Noun', 'correction-determiner5') + //the test string + inf.match('#Determiner [#Infinitive] #Noun').tag('Noun', 'correction-determiner7') + //by a bear. + inf.match('#Determiner [#Infinitive]$').tag('Noun', 'a-inf') + } + + //the wait to vote + det.match('(the|this) [#Verb] #Preposition .').tag('Noun', 'correction-determiner1') + //a sense of + det.match('#Determiner [#Verb] of').tag('Noun', 'the-verb-of') + //the threat of force + det.match('#Determiner #Noun of [#Verb]').tag('Noun', 'noun-of-noun') + //a close + det.match('#Determiner #Adverb? [close]').tag('Adjective', 'a-close') + //the western line + det.match('#Determiner [(western|eastern|northern|southern|central)] #Noun').tag('Noun', 'western-line') + //the swim + det.match('(the|those|these) [(#Infinitive|#PresentTense|#PastTense)]').tag('Noun', 'correction-determiner2') + } + + let an = doc.if('(a|an)') + if (an.found === true) { + //a staggering cost + an.match('(a|an) [#Gerund]').tag('Adjective', 'correction-a|an') + //did a 900, paid a 20 + an.match('#Verb (a|an) [#Value]').tag('Singular', 'a-value') + //a tv show + an.match('(a|an) #Noun [#Infinitive]').tag('Noun', 'a-noun-inf') + //a great run + an.match('(a|an) #Adjective (#Infinitive|#PresentTense)') + .terms(2) + .tag('Noun', 'correction-a|an2') + //'a/an' can mean 1 - "a hour" + an.match('[(a|an)] (#Duration|hundred|thousand|million|billion|trillion)') + .ifNo('#Plural') + .tag('Value', 'a-is-one') + } + + return doc +} +module.exports = fixThe diff --git a/src/02-tagger/04-correction/fixValue.js b/src/02-tagger/04-correction/fixValue.js new file mode 100644 index 000000000..d89942049 --- /dev/null +++ b/src/02-tagger/04-correction/fixValue.js @@ -0,0 +1,37 @@ +const units = '(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)' + +// +const fixValue = function(doc) { + let val = doc.if('#Value') + if (val.found === true) { + //1 800 PhoneNumber + val.match('1 #Value #PhoneNumber').tag('PhoneNumber', '1-800-Value') + //(454) 232-9873 + val.match('#NumericValue #PhoneNumber').tag('PhoneNumber', '(800) PhoneNumber') + //three trains + val.match('#Value [#PresentTense]').tag('Plural', 'value-presentTense') + //money + let m = val.match('#Value+ #Currency') + m.lastTerm().tag('Unit', 'money-unit') + m.match('#Value+').tag('Money', 'value-currency') + } + //5 kg. + val.match('#Value #Abbreviation').tag('Value', 'value-abbr') + //seven point five + val.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value') + //minus 7 + val.match('(minus|negative) #Value').tag('Value', 'minus-value') + // ten grand + val.match('#Value grand').tag('Value', 'value-grand') + //quarter million + val.match('(a|the) [(half|quarter)] #Ordinal').tag('Value', 'half-ordinal') + //eg 'trillion' + let mult = val.if(units) + if (mult.found === true) { + mult.match('a #Value').tag('Value', 'a-value') //? + // mult.match('#Ordinal (half|quarter)').tag('Value', 'ordinal-half');//not ready + mult.match(`${units} and #Value`).tag('Value', 'magnitude-and-value') + } + return doc +} +module.exports = fixValue diff --git a/src/02-tagger/04-correction/fixVerb.js b/src/02-tagger/04-correction/fixVerb.js new file mode 100644 index 000000000..7c5805d36 --- /dev/null +++ b/src/02-tagger/04-correction/fixVerb.js @@ -0,0 +1,150 @@ +const advb = '(#Adverb|not)+?' +// +const fixVerb = function(doc) { + let vb = doc.if('#Verb') + if (vb.found) { + vb.match('[(do|does|will|have|had)] (not|#Adverb)? #Verb').tag('Auxiliary', 'have-had') + //still make + vb.match('[still] #Verb').tag('Adverb', 'still-verb') + //'u' as pronoun + vb.match('[u] #Verb').tag('Pronoun', 'u-pronoun-1') + //is no walk + vb.match('is no [#Verb]').tag('Noun', 'is-no-verb') + //different views than + vb.match('[#Verb] than').tag('Noun', 'correction') + // smoked poutine is + vb.match('[#PastTense] #Singular is').tag('#Adjective', 'smoked-poutine') + // baked onions are + vb.match('[#PastTense] #Plural are').tag('#Adjective', 'baked-onions') + // goes to sleep + vb.match('(go|goes|went) to [#Infinitive]').tag('#Noun', 'goes-to-verb') + + //there are reasons + vb.match('there (are|were) #Adjective? [#PresentTense]').tag('Plural', 'there-are') + //jack seems guarded + vb.match('#Singular (seems|appears) #Adverb? [#PastTense$]').tag('Adjective', 'seems-filled') + //fall over + vb.match('#PhrasalVerb [#PhrasalVerb]').tag('Particle', 'phrasal-particle') + //went to sleep + // vb.match('#Verb to #Verb').lastTerm().tag('Noun', 'verb-to-verb'); + //been walking + vb.match(`(be|been) ${advb} #Gerund`) + .not('#Verb$') + .tag('Auxiliary', 'be-walking') + + // directive verb - 'use reverse' + vb.match('(try|use|attempt|build|make) #Verb') + .ifNo('(@hasComma|#Negative|#Copula|will|be)') + .lastTerm() + .tag('#Noun', 'do-verb') + //infinitive verbs suggest plural nouns - 'XYZ walk to the store' + // r.match(`#Singular+ #Infinitive`).match('#Singular+').tag('Plural', 'infinitive-make-plural'); + + let modal = vb.if('(#Modal|did|had|has)') + if (modal.found === true) { + //support a splattering of auxillaries before a verb + modal + .match(`(has|had) ${advb} #PastTense`) + .not('#Verb$') + .tag('Auxiliary', 'had-walked') + //would walk + modal + .match(`(#Modal|did) ${advb} #Verb`) + .not('#Verb$') + .tag('Auxiliary', 'modal-verb') + //would have had + modal + .match(`#Modal ${advb} have ${advb} had ${advb} #Verb`) + .not('#Verb$') + .tag('Auxiliary', 'would-have') + //would be walking + modal + .match(`#Modal ${advb} be ${advb} #Verb`) + .not('#Verb$') + .tag('Auxiliary', 'would-be') + //would been walking + modal + .match(`(#Modal|had|has) ${advb} been ${advb} #Verb`) + .not('#Verb$') + .tag('Auxiliary', 'would-be') + } + + let copula = vb.if('#Copula') + if (copula.found === true) { + //was walking + copula + .match(`#Copula ${advb} #Gerund`) + .not('#Verb$') + .tag('Auxiliary', 'copula-walking') + //is mark hughes + copula.match('#Copula [#Infinitive] #Noun').tag('Noun', 'is-pres-noun') + // + copula.match('[#Infinitive] #Copula').tag('Noun', 'inf-copula') + //sometimes not-adverbs + copula.match('#Copula [(just|alone)]$').tag('Adjective', 'not-adverb') + //jack is guarded + copula.match('#Singular is #Adverb? [#PastTense$]').tag('Adjective', 'is-filled') + //is eager to go + copula.match('#Copula [#Adjective to] #Verb').tag('Verb', 'adj-to') + + //sometimes adverbs - 'pretty good','well above' + copula + .match('#Copula (pretty|dead|full|well) (#Adjective|#Noun)') + .ifNo('@hasComma') + .tag('#Copula #Adverb #Adjective', 'sometimes-adverb') + } + + //Gerund - 'walking' + let gerund = vb.if('#Gerund') + if (gerund.found === true) { + //walking is cool + gerund.match('[#Gerund] #Adverb? not? #Copula').tag('Activity', 'gerund-copula') + //walking should be fun + gerund.match('[#Gerund] #Modal').tag('Activity', 'gerund-modal') + //running-a-show + gerund.match('#Gerund #Determiner [#Infinitive]').tag('Noun', 'running-a-show') + //setting records + // doc.match('#Gerund [#PresentTense]').tag('Plural', 'setting-records'); + } + + //'will be' + let willBe = vb.if('will #Adverb? not? #Adverb? be') + if (willBe.found === true) { + //will be running (not copula + if (willBe.has('will #Adverb? not? #Adverb? be #Gerund') === false) { + //tag it all + willBe.match('will not? be').tag('Copula', 'will-be-copula') + //for more complex forms, just tag 'be' + willBe + .match('will #Adverb? not? #Adverb? be #Adjective') + .match('be') + .tag('Copula', 'be-copula') + } + } + } + + //question words + let m = doc.if('(who|what|where|why|how|when)') + if (m.found) { + //the word 'how' + m.match('^how').tag('QuestionWord', 'how-question') + m.match('[how] (#Determiner|#Copula|#Modal|#PastTense)').tag('QuestionWord', 'how-is') + // //the word 'which' + m.match('^which').tag('QuestionWord', 'which-question') + m.match('[which] . (#Noun)+ #Pronoun').tag('QuestionWord', 'which-question2') + m.match('which').tag('QuestionWord', 'which-question3') + + //how he is driving + m.match('[#QuestionWord] #Noun #Copula #Adverb? (#Verb|#Adjective)') + .unTag('QuestionWord') + .tag('Conjunction', 'how-he-is-x') + + //when i go fishing + m.match('#QuestionWord #Noun #Adverb? #Infinitive not? #Gerund') + .unTag('QuestionWord') + .tag('Conjunction', 'when i go fishing') + } + + return doc +} +module.exports = fixVerb diff --git a/src/02-tagger/04-correction/index.js b/src/02-tagger/04-correction/index.js new file mode 100644 index 000000000..c4d5fdda5 --- /dev/null +++ b/src/02-tagger/04-correction/index.js @@ -0,0 +1,54 @@ +const fixMisc = require('./fixMisc') +const fixDeterminer = require('./fixThe') +const fixNouns = require('./fixNouns') +const fixPerson = require('./fixPerson') +const fixVerb = require('./fixVerb') +const fixAdjective = require('./fixAdjective') +const fixValue = require('./fixValue') +const fixDates = require('./fixDates') + +// det: 131.338ms +// verb: 100.828ms +// dates: 80.874ms +// person: 66.054ms +// nouns: 51.340ms +// adj: 19.760ms +// value: 12.950ms +// misc: 43.359ms + +//sequence of match-tag statements to correct mis-tags +const corrections = function(doc) { + // console.time('det') + fixDeterminer(doc) //27 + // console.timeEnd('det') + + // console.time('nouns') + fixNouns(doc) //30 + // // console.timeEnd('nouns') + + // // console.time('person') + fixPerson(doc) //58 + // // console.timeEnd('person') + + // // console.time('verb') + fixVerb(doc) //50 + // // console.timeEnd('verb') + + // // console.time('adj') + fixAdjective(doc) //8 + // // console.timeEnd('adj') + + // // console.time('value') + fixValue(doc) //12 + // // console.timeEnd('value') + + // // console.time('dates') + fixDates(doc) //92 + // // console.timeEnd('dates') + + // // console.time('misc') + fixMisc(doc) //43 + // console.timeEnd('misc') + return doc +} +module.exports = corrections diff --git a/src/02-tagger/index.js b/src/02-tagger/index.js new file mode 100644 index 000000000..66e9e4696 --- /dev/null +++ b/src/02-tagger/index.js @@ -0,0 +1,34 @@ +const init = require('./01-init') +const fallbacks = require('./02-fallbacks') +const contractions = require('./03-contractions') +const corrections = require('./04-correction') + +/** POS-tag all terms in this document */ +const tagger = function(doc) { + let terms = doc.termList() + // check against any known-words + doc = init(doc, terms) + + // everything has gotta be something. ¯\_(:/)_/¯ + doc = fallbacks(doc, terms) + + // support "didn't" & "spencer's" + doc = contractions(doc) + + //set our cache, to speed things up + doc.cache() + + // wiggle-around the results, so they make more sense + doc = corrections(doc) + + //remove our cache + // doc.uncache() + + // run any user-given tagger functions + doc.world.taggers.forEach(fn => { + fn(doc) + }) + + return doc +} +module.exports = tagger diff --git a/src/Doc/Doc.js b/src/Doc/Doc.js new file mode 100644 index 000000000..adba7dfbf --- /dev/null +++ b/src/Doc/Doc.js @@ -0,0 +1,88 @@ +const methods = { + misc: require('./methods'), + selections: require('../Subset/_simple'), +} +const tagger = require('../02-tagger') +const tokenize = require('../01-tokenizer') +const extend = require('../Subset') + +/** a parsed text object */ +class Doc { + constructor(list, from, world) { + this.list = list + //quiet these properties in console.logs + Object.defineProperty(this, 'from', { + enumerable: false, + value: from, + writable: true, + }) + //borrow some missing data from parent + if (world === undefined && from !== undefined) { + world = from.world + } + //'world' getter + Object.defineProperty(this, 'world', { + enumerable: false, + value: world, + // writable: true, //todo: add me? + }) + //fast-scans for our data + + //'found' getter + Object.defineProperty(this, 'found', { + get: () => this.list.length > 0, + }) + //'length' getter + Object.defineProperty(this, 'length', { + get: () => this.list.length, + }) + // this is way easier than .constructor.name... + Object.defineProperty(this, 'isA', { + get: () => 'Doc', + }) + } + + /** run part-of-speech tagger on all results*/ + tagger() { + return tagger(this) + } + + /** pool is stored on phrase objects */ + pool() { + if (this.list.length > 0) { + return this.list[0].pool + } + return this.all().list[0].pool + } +} + +/** create a new Document object */ +Doc.prototype.buildFrom = function(list) { + list = list.map(p => p.clone(true)) + // new this.constructor() + let doc = new Doc(list, this, this.world) + return doc +} + +/** create a new Document from plaintext. */ +Doc.prototype.fromText = function(str) { + let list = tokenize.fromText(str, this.world, this.pool()) + return this.buildFrom(list) +} + +Object.assign(Doc.prototype, methods.misc) +Object.assign(Doc.prototype, methods.selections) + +//add sub-classes +extend(Doc) + +//aliases +const aliases = { + untag: 'unTag', + and: 'match', + notIf: 'ifNo', + only: 'if', + onlyIf: 'if', +} +Object.keys(aliases).forEach(k => (Doc.prototype[k] = Doc.prototype[aliases[k]])) +module.exports = Doc diff --git a/src/Doc/match/parseToken.js b/src/Doc/match/parseToken.js new file mode 100644 index 000000000..569cede46 --- /dev/null +++ b/src/Doc/match/parseToken.js @@ -0,0 +1,164 @@ +/* break-down a match expression into this: +{ + word:'', + tag:'', + regex:'', + + start:false, + end:false, + negative:false, + anything:false, + greedy:false, + optional:false, + + capture:false, + choices:[], +} +*/ +const hasMinMax = /\{([0-9]+,?[0-9]*)\}/ +const andSign = /&&/ + +const titleCase = str => { + return str.charAt(0).toUpperCase() + str.substr(1) +} + +const end = function(str) { + return str[str.length - 1] +} +const start = function(str) { + return str[0] +} +const stripStart = function(str) { + return str.substr(1) +} +const stripEnd = function(str) { + return str.substr(0, str.length - 1) +} +const stripBoth = function(str) { + str = stripStart(str) + str = stripEnd(str) + return str +} + +// +const parseToken = function(w) { + let obj = {} + //collect any flags (do it twice) + for (let i = 0; i < 2; i += 1) { + //back-flags + if (end(w) === '+') { + obj.greedy = true + w = stripEnd(w) + } + if (w !== '*' && end(w) === '*' && w !== '\\*') { + obj.greedy = true + w = stripEnd(w) + } + if (end(w) === '?') { + obj.optional = true + w = stripEnd(w) + } + if (end(w) === '$') { + obj.end = true + w = stripEnd(w) + } + //front-flags + if (start(w) === '^') { + obj.start = true + w = stripStart(w) + } + if (start(w) === '!') { + obj.negative = true + w = stripStart(w) + } + //wrapped-flags + if (start(w) === '(' && end(w) === ')') { + // support (one && two) + if (andSign.test(w)) { + obj.choices = w.split(andSign) + obj.operator = 'and' + } else { + obj.choices = w.split('|') + obj.operator = 'or' + } + //remove '(' and ')' + obj.choices[0] = stripStart(obj.choices[0]) + let last = obj.choices.length - 1 + obj.choices[last] = stripEnd(obj.choices[last]) + // clean up the results + obj.choices = obj.choices.map(s => s.trim()) + obj.choices = obj.choices.filter(s => s) + //recursion alert! + obj.choices = obj.choices.map(parseToken) + w = '' + } + //capture group (this one can span multiple-terms) + if (start(w) === '[' || end(w) === ']') { + obj.capture = true + w = w.replace(/^\[/, '') + w = w.replace(/\]$/, '') + } + //regex + if (start(w) === '/' && end(w) === '/') { + w = stripBoth(w) + obj.regex = new RegExp(w) + return obj + } + //soft-match + if (start(w) === '~' && end(w) === '~') { + w = stripBoth(w) + obj.soft = true + obj.word = w + return obj + } + } + // support #Tag{0,9} + if (hasMinMax.test(w) === true) { + w = w.replace(hasMinMax, (a, b) => { + let arr = b.split(/,/g) + if (arr.length === 1) { + // '{3}' Exactly three times + obj.min = Number(arr[0]) + obj.max = Number(arr[0]) + } else { + // '{2,4}' Two to four times + // '{3,}' Three or more times + obj.min = Number(arr[0]) + obj.max = Number(arr[1] || 999) + } + obj.greedy = true + return '' + }) + } + + //do the actual token content + if (start(w) === '#') { + obj.tag = stripStart(w) + obj.tag = titleCase(obj.tag) + return obj + } + //dynamic function on a term object + if (start(w) === '@') { + obj.method = stripStart(w) + return obj + } + if (w === '.') { + obj.anything = true + return obj + } + //support alone-astrix + if (w === '*') { + obj.anything = true + obj.greedy = true + obj.optional = true + return obj + } + if (w) { + //somehow handle encoded-chars? + w = w.replace('\\*', '*') + w = w.replace('\\.', '.') + obj.word = w.toLowerCase() + } + return obj +} +module.exports = parseToken diff --git a/src/Doc/match/syntax.js b/src/Doc/match/syntax.js new file mode 100644 index 000000000..8c5d01e86 --- /dev/null +++ b/src/Doc/match/syntax.js @@ -0,0 +1,109 @@ +const parseToken = require('./parseToken') + +const isArray = function(arr) { + return Object.prototype.toString.call(arr) === '[object Array]' +} + +//split-up by (these things) +const byParentheses = function(str) { + let arr = str.split(/([\^\[\!]*\(.*?\)[?+*]*\]?\$?)/) + arr = arr.map(s => s.trim()) + return arr +} + +const byWords = function(arr) { + let words = [] + arr.forEach(a => { + //keep brackets lumped together + if (/^[[^_/]?\(/.test(a[0])) { + words.push(a) + return + } + let list = a.split(' ') + list = list.filter(w => w) + words = words.concat(list) + }) + return words +} + +//turn an array into a 'choices' list +const byArray = function(arr) { + return [ + { + choices: arr.map(s => { + return { + word: s, + } + }), + }, + ] +} + +const postProcess = function(tokens) { + //ensure there's only one consecutive capture group. + let count = tokens.filter(t => t.capture === true).length + if (count > 1) { + let captureArr = tokens.map(t => t.capture) + let first = captureArr.indexOf(true) + let last = captureArr.length - 1 - captureArr.reverse().indexOf(true) + //'fill in' capture groups between start-end + for (let i = first; i < last; i++) { + tokens[i].capture = true + } + } + return tokens +} + +const fromDoc = function(doc) { + if (!doc || !doc.list || !doc.list[0]) { + return [] + } + let ids = [] + doc.list.forEach(p => { + p.terms().forEach(t => { + ids.push({ id: t.id }) + }) + }) + return [{ choices: ids, greedy: true }] +} + +/** parse a match-syntax string into json */ +const syntax = function(input) { + // fail-fast + if (input === null || input === undefined || input === '') { + return [] + } + //try to support a ton of different formats: + if (typeof input === 'object') { + if (isArray(input)) { + if (input.length === 0 || !input[0]) { + return [] + } + + //is it a pre-parsed reg-list? + if (typeof input[0] === 'object') { + return input + } + //support a flat array of normalized words + if (typeof input[0] === 'string') { + return byArray(input) + } + } + //support passing-in a compromise object as a match + if (input && input.isA === 'Doc') { + return fromDoc(input) + } + return [] + } + if (typeof input === 'number') { + input = String(input) //go for it? + } + let tokens = byParentheses(input) + tokens = byWords(tokens) + tokens = tokens.map(parseToken) + //clean up anything weird + tokens = postProcess(tokens) + // console.log(JSON.stringify(tokens, null, 2)) + return tokens +} +module.exports = syntax diff --git a/src/Doc/methods/01-utils.js b/src/Doc/methods/01-utils.js new file mode 100644 index 000000000..639c26b11 --- /dev/null +++ b/src/Doc/methods/01-utils.js @@ -0,0 +1,101 @@ +// const cache = require('./_setCache') + +/** return the root, first document */ +exports.all = function() { + return this.parents()[0] || this +} + +/** return the previous result */ +exports.parent = function() { + if (this.from) { + return this.from + } + return this +} + +/** return a list of all previous results */ +exports.parents = function(n) { + let arr = [] + const addParent = function(doc) { + if (doc.from) { + arr.push(doc.from) + addParent(doc.from) + } + } + addParent(this) + arr = arr.reverse() + if (typeof n === 'number') { + return arr[n] + } + return arr +} + +/** deep-copy the document, so that no references remain */ +exports.clone = function(doShallow) { + let list = this.list.map(ts => ts.clone(doShallow)) + let tmp = this.buildFrom(list) + return tmp +} + +/** how many seperate terms does the document have? */ +exports.wordCount = function() { + return this.list.reduce((count, p) => { + count += p.wordCount() + return count + }, 0) +} +exports.wordcount = exports.wordCount + +/** turn on logging for decision-debugging */ +// exports.verbose = function(bool) { +// if (bool === undefined) { +// bool = true +// } +// this.world.verbose = bool +// } + +/** freeze the current state of the document, for speed-purposes*/ +exports.cache = function(options) { + options = options || {} + this.list.forEach(p => { + let words = {} + p.cache = p.cache || {} + p.cache.terms = p.cache.terms || p.terms() + // cache all the terms + p.cache.terms.forEach(t => { + words[t.clean] = true + words[t.reduced] = true + words[t.text.toLowerCase()] = true + if (t.implicit) { + words[t.implicit] = true + } + if (t.root) { + words[t.root] = true + } + if (t.alias !== undefined) { + words = Object.assign(words, t.alias) + } + if (options.root) { + t.setRoot(this.world) + words[t.root] = true + } + }) + delete words[''] + p.cache.words = words + }) + return this +} + +/** un-freezes the current state of the document, so it may be transformed */ +exports.uncache = function() { + this.list.forEach(p => { + p.cache = {} + }) + // do parents too? + this.parents().forEach(doc => { + doc.list.forEach(p => { + p.cache = {} + }) + }) + return this +} diff --git a/src/Doc/methods/02-accessors.js b/src/Doc/methods/02-accessors.js new file mode 100644 index 000000000..e999943a8 --- /dev/null +++ b/src/Doc/methods/02-accessors.js @@ -0,0 +1,58 @@ +/** use only the first result(s) */ +exports.first = function(n) { + if (n === undefined) { + return this.get(0) + } + return this.slice(0, n) +} + +/** use only the last result(s) */ +exports.last = function(n) { + if (n === undefined) { + return this.get(this.list.length - 1) + } + let end = this.list.length + return this.slice(end - n, end) +} + +/** grab a given subset of the results*/ +exports.slice = function(start, end) { + let list = this.list.slice(start, end) + return this.buildFrom(list) +} + +/* grab nth result */ +exports.eq = function(n) { + let p = this.list[n] + if (p === undefined) { + return this.buildFrom([]) + } + return this.buildFrom([p]) +} +exports.get = exports.eq + +/** grab term[0] for every match */ +exports.firstTerm = function() { + return this.match('^.') +} +/** grab the last term for every match */ +exports.lastTerm = function() { + return this.match('.$') +} + +/** return a flat array of term objects */ +exports.termList = function(num) { + let arr = [] + //'reduce' but faster + for (let i = 0; i < this.list.length; i++) { + let terms = this.list[i].terms() + for (let o = 0; o < terms.length; o++) { + arr.push(terms[o]) + //support .termList(4) + if (num !== undefined && arr[num] !== undefined) { + return arr[num] + } + } + } + return arr +} diff --git a/src/Doc/methods/03-match.js b/src/Doc/methods/03-match.js new file mode 100644 index 000000000..494d52655 --- /dev/null +++ b/src/Doc/methods/03-match.js @@ -0,0 +1,136 @@ +const parseSyntax = require('../match/syntax') + +/** return a new Doc, with this one as a parent */ +exports.match = function(reg) { + //parse-up the input expression + let regs = parseSyntax(reg) + if (regs.length === 0) { + return this.buildFrom([]) + } + //try expression on each phrase + let matches = this.list.reduce((arr, p) => { + return arr.concat(p.match(regs)) + }, []) + return this.buildFrom(matches) +} + +/** return all results except for this */ +exports.not = function(reg) { + //parse-up the input expression + let regs = parseSyntax(reg) + //if it's empty, return them all! + if (regs.length === 0) { + return this + } + //try expression on each phrase + let matches = this.list.reduce((arr, p) => { + return arr.concat(p.not(regs)) + }, []) + return this.buildFrom(matches) +} + +/** return only the first match */ +exports.matchOne = function(reg) { + let regs = parseSyntax(reg) + for (let i = 0; i < this.list.length; i++) { + let match = this.list[i].match(regs) + return this.buildFrom(match) + } + return this.buildFrom([]) +} + +/** return each current phrase, only if it contains this match */ +exports.if = function(reg) { + let regs = parseSyntax(reg) + let found = this.list.filter(p => p.match(regs).length > 0) + return this.buildFrom(found) +} + +/** Filter-out any current phrases that have this match*/ +exports.ifNo = function(reg) { + let regs = parseSyntax(reg) + let found = this.list.filter(p => p.match(regs).length === 0) + return this.buildFrom(found) +} + +/**Return a boolean if this match exists */ +exports.has = function(reg) { + let regs = parseSyntax(reg) + return this.list.some(p => p.has(regs) === true) +} + +/** match any terms after our matches, within the sentence */ +exports.lookAhead = function(reg) { + // find everything afterwards, by default + if (!reg) { + reg = '.*' + } + let regs = parseSyntax(reg) + let matches = [] + this.list.forEach(p => { + matches = matches.concat(p.lookAhead(regs)) + }) + matches = matches.filter(p => p) + return this.buildFrom(matches) +} +exports.lookAfter = exports.lookAhead + +/** match any terms before our matches, within the sentence */ +exports.lookBehind = function(reg) { + // find everything afterwards, by default + if (!reg) { + reg = '.*' + } + let regs = parseSyntax(reg) + let matches = [] + this.list.forEach(p => { + matches = matches.concat(p.lookBehind(regs)) + }) + matches = matches.filter(p => p) + return this.buildFrom(matches) +} +exports.lookBefore = exports.lookBehind + +/** return all terms before a match, in each phrase */ +exports.before = function(reg) { + let regs = parseSyntax(reg) + //only the phrases we care about + let phrases = this.if(regs).list + let befores = phrases.map(p => { + let ids = p.terms().map(t => t.id) + //run the search again + let m = p.match(regs)[0] + let index = ids.indexOf(m.start) + //nothing is before a first-term match + if (index === 0 || index === -1) { + return null + } + return p.buildFrom(p.start, index) + }) + befores = befores.filter(p => p !== null) + return this.buildFrom(befores) +} + +/** return all terms after a match, in each phrase */ +exports.after = function(reg) { + let regs = parseSyntax(reg) + //only the phrases we care about + let phrases = this.if(regs).list + let befores = phrases.map(p => { + let terms = p.terms() + let ids = terms.map(t => t.id) + //run the search again + let m = p.match(regs)[0] + let index = ids.indexOf(m.start) + //skip if nothing is after it + if (index === -1 || !terms[index + m.length]) { + return null + } + //create the new phrase, after our match. + let id = terms[index + m.length].id + let len = p.length - index - m.length + return p.buildFrom(id, len) + }) + befores = befores.filter(p => p !== null) + return this.buildFrom(befores) +} diff --git a/src/Doc/methods/04-tag.js b/src/Doc/methods/04-tag.js new file mode 100644 index 000000000..5505c274a --- /dev/null +++ b/src/Doc/methods/04-tag.js @@ -0,0 +1,39 @@ +const setTag = require('./_setTag') + +/** Give all terms the given tag */ +exports.tag = function(tags, why) { + if (!tags) { + return this + } + setTag(tags, this, false, why) + return this +} + +/** Only apply tag to terms if it is consistent with current tags */ +exports.tagSafe = function(tags, why) { + if (!tags) { + return this + } + setTag(tags, this, true, why) + return this +} + +/** Remove this term from the given terms */ +exports.unTag = function(tags, why) { + this.list.forEach(p => { + p.terms().forEach(t => t.unTag(tags, why, this.world)) + }) + return this +} + +/** return only the terms that can be this tag*/ +exports.canBe = function(tag) { + if (!tag) { + return this + } + let world = this.world + let matches = this.list.reduce((arr, p) => { + return arr.concat(p.canBe(tag, world)) + }, []) + return this.buildFrom(matches) +} diff --git a/src/Doc/methods/05-loops.js b/src/Doc/methods/05-loops.js new file mode 100644 index 000000000..d478f92a5 --- /dev/null +++ b/src/Doc/methods/05-loops.js @@ -0,0 +1,111 @@ +/* run each phrase through a function, and create a new document */ +exports.map = function(fn) { + if (!fn) { + return this + } + let list = this.list.map((p, i) => { + let doc = this.buildFrom([p]) + doc.from = null //it's not a child/parent + let res = fn(doc, i) + if (res.list && res.list[0]) { + return res.list[0] + } + return res + }) + if (list.length === 0) { + return this.buildFrom(list) + } + // if it is not a list of Phrase objects, then don't try to make a Doc object + if (typeof list[0] !== 'object' || list[0].isA !== 'Phrase') { + return list + } + return this.buildFrom(list) +} + +/** run a function on each phrase */ +exports.forEach = function(fn, detachParent) { + if (!fn) { + return this + } + this.list.forEach((p, i) => { + let sub = this.buildFrom([p]) + // if we're doing fancy insertions, we may want to skip updating the parent each time. + if (detachParent === true) { + sub.from = null // + } + // let len + // console.log(sub.from.list[0].text()) + fn(sub, i) + // console.log(sub.from.list[0].text()) + }) + return this +} + +/** return only the phrases that return true */ +exports.filter = function(fn) { + if (!fn) { + return this + } + let list = this.list.filter((p, i) => { + let doc = this.buildFrom([p]) + doc.from = null //it's not a child/parent + return fn(doc, i) + }) + return this.buildFrom(list) +} + +/** return a document with only the first phrase that matches */ +exports.find = function(fn) { + if (!fn) { + return this + } + let phrase = this.list.find((p, i) => { + let doc = this.buildFrom([p]) + doc.from = null //it's not a child/parent + return fn(doc, i) + }) + if (phrase) { + return this.buildFrom([phrase]) + } + return undefined +} + +/** return true or false if there is one matching phrase */ +exports.some = function(fn) { + if (!fn) { + return this + } + return this.list.some((p, i) => { + let doc = this.buildFrom([p]) + doc.from = null //it's not a child/parent + return fn(doc, i) + }) +} + +/** sample a subset of the results */ +exports.random = function(n) { + if (!this.found) { + return this + } + let r = Math.floor(Math.random() * this.list.length) + if (n === undefined) { + let list = [this.list[r]] + return this.buildFrom(list) + } + //prevent it from going over the end + if (r + n > this.length) { + r = this.length - n + r = r < 0 ? 0 : r + } + return this.slice(r, r + n) +} + +/** combine each phrase into a new data-structure */ +// exports.reduce = function(fn, h) { +// let list = this.list.reduce((_h, ts) => { +// let doc = this.buildFrom([ts]) +// doc.from = null //it's not a child/parent +// return fn(_h, doc) +// }, h) +// return this.buildFrom(list) +// } diff --git a/src/Doc/methods/06-lookup.js b/src/Doc/methods/06-lookup.js new file mode 100644 index 000000000..53d28167d --- /dev/null +++ b/src/Doc/methods/06-lookup.js @@ -0,0 +1,57 @@ +const tokenize = require('../../01-tokenizer/02-words') + +// compare one term and one match +const doesMatch = function(term, str) { + if (str === '') { + return false + } + return term.reduced === str || term.implicit === str || term.root === str || term.text.toLowerCase() === str +} + +// is this lookup found in these terms? +const findStart = function(arr, terms) { + //find the start + for (let i = 0; i < terms.length; i++) { + if (doesMatch(terms[i], arr[0])) { + if (arr.every((a, n) => doesMatch(terms[i + n], a) === true)) { + return terms[i].id + } + } + } + return false +} + +/** lookup an array of words or phrases */ +exports.lookup = function(arr) { + if (typeof arr === 'string') { + arr = [arr] + } + let lookups = arr.map(str => { + str = str.toLowerCase() + let words = tokenize(str) + words = words.map(s => s.trim()) + return words + }) + this.cache() + let found = [] + // try each lookup + lookups.forEach(a => { + //try each phrase + this.list.forEach(p => { + // cache-miss, skip. + if (p.cache.words[a[0]] !== true) { + return + } + //we found a potential match + let terms = p.terms() + let id = findStart(a, terms) + if (id !== false) { + // create the actual phrase + let phrase = p.buildFrom(id, a.length) + found.push(phrase) + return + } + }) + }) + return this.buildFrom(found) +} diff --git a/src/Doc/methods/_debug.js b/src/Doc/methods/_debug.js new file mode 100644 index 000000000..bfaedee56 --- /dev/null +++ b/src/Doc/methods/_debug.js @@ -0,0 +1,73 @@ +const tagset = require('../../world/tags') + +// https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color +const reset = '\x1b[0m' + +const padEnd = function(str, width) { + str = str.toString() + while (str.length < width) { + str += ' ' + } + return str +} + +//cheaper than requiring chalk +const cli = { + green: function(str) { + return '\x1b[32m' + str + reset + }, + red: function(str) { + return '\x1b[31m' + str + reset + }, + blue: function(str) { + return '\x1b[34m' + str + reset + }, + magenta: function(str) { + return '\x1b[35m' + str + reset + }, + cyan: function(str) { + return '\x1b[36m' + str + reset + }, + yellow: function(str) { + return '\x1b[33m' + str + reset + }, + black: function(str) { + return '\x1b[30m' + str + reset + }, +} + +const tagString = function(tags) { + tags = tags.map(tag => { + if (!tagset.hasOwnProperty(tag)) { + return tag + } + const c = tagset[tag].color || 'blue' + return cli[c](tag) + }) + return tags.join(', ') +} + +//output some helpful stuff to the console +const debug = function(doc) { + console.log(cli.blue('=====')) + doc.list.forEach(p => { + console.log(cli.blue(' -----')) + p.terms().forEach(t => { + let tags = Object.keys(t.tags) + let text = t.text || '-' + if (t.implicit) { + text = '[' + t.implicit + ']' + } + if (typeof module !== undefined) { + text = cli.yellow(text) + } + let word = "'" + text + "'" + word = padEnd(word, 18) + let str = cli.blue(' | ') + word + ' - ' + tagString(tags) + console.log(str) + }) + }) + console.log('') + return doc +} +module.exports = debug diff --git a/src/Doc/methods/_setTag.js b/src/Doc/methods/_setTag.js new file mode 100644 index 000000000..ab6054ee7 --- /dev/null +++ b/src/Doc/methods/_setTag.js @@ -0,0 +1,30 @@ +/** apply a tag, or tags to all terms */ +const tagTerms = function(tag, doc, safe, reason) { + let tagList = [] + if (typeof tag === 'string') { + tagList = tag.split(' ') + } + + // console.log(doc.parents().length) + //do indepenent tags for each term: + doc.list.forEach(p => { + let terms = p.terms() + // tagSafe - apply only to fitting terms + if (safe === true) { + terms = terms.filter(t => t.canBe(tag, doc.world)) + } + terms.forEach((t, i) => { + //fancy version: + if (tagList.length > 1) { + if (tagList[i] && tagList[i] !== '.') { + t.tag(tagList[i], reason, doc.world) + } + } else { + //non-fancy version (same tag for all terms) + t.tag(tag, reason, doc.world) + } + }) + }) + return +} +module.exports = tagTerms diff --git a/src/Doc/methods/index.js b/src/Doc/methods/index.js new file mode 100644 index 000000000..896792eb5 --- /dev/null +++ b/src/Doc/methods/index.js @@ -0,0 +1,25 @@ +module.exports = Object.assign( + {}, + require('./01-utils'), + require('./02-accessors'), + require('./03-match'), + require('./04-tag'), + require('./05-loops'), + require('./06-lookup'), + + require('./insert/01-replace'), + require('./insert/02-insert'), + + require('./output/01-text'), + require('./output/02-json'), + require('./output/03-out'), + require('./output/04-export'), + + require('./transform/01-sort'), + require('./transform/02-normalize'), + require('./transform/03-split'), + require('./transform/04-case'), + require('./transform/05-whitespace'), + require('./transform/06-join'), + require('./transform/07-contract') +) diff --git a/src/Doc/methods/insert/01-replace.js b/src/Doc/methods/insert/01-replace.js new file mode 100644 index 000000000..68a34d4da --- /dev/null +++ b/src/Doc/methods/insert/01-replace.js @@ -0,0 +1,61 @@ +const tokenize = require('../../../01-tokenizer') + +const titleCase = str => { + return str.charAt(0).toUpperCase() + str.substr(1) +} + +/** substitute-in new content */ +exports.replaceWith = function(replace, keepTags, keepCase) { + if (!replace) { + return this.delete() + } + // clear the cache + this.uncache() + // return this + this.list.forEach(p => { + let input = replace + // accept a function for replace + if (typeof replace === 'function') { + input = replace(p) + } + let newPhrases + // accept a Doc object to replace + if (input && typeof input === 'object' && input.isA === 'Doc') { + newPhrases = input.list + this.pool().merge(input.pool()) + } else if (typeof input === 'string') { + //input is a string + if (keepCase === true && p.terms(0).isTitleCase()) { + input = titleCase(input) + } + newPhrases = tokenize.fromText(input, this.world, this.pool()) + //tag the new phrases + let tmpDoc = this.buildFrom(newPhrases) + tmpDoc.tagger() + } else { + return //don't even bother + } + + // try to keep its old tags, if appropriate + if (keepTags === true) { + let oldTags = p.json({ terms: { tags: true } }).terms + newPhrases[0].terms().forEach((t, i) => { + if (oldTags[i]) { + t.tagSafe(oldTags[i].tags, 'keptTag', this.world) + } + }) + } + p.replace(newPhrases[0], this) //Oneday: support multi-sentence replacements + }) + return this +} + +/** search and replace match with new content */ +exports.replace = function(match, replace, keepTags, keepCase) { + // if there's no 2nd param, use replaceWith + if (replace === undefined) { + return this.replaceWith(match) + } + this.match(match).replaceWith(replace, keepTags, keepCase) + return this +} diff --git a/src/Doc/methods/insert/02-insert.js b/src/Doc/methods/insert/02-insert.js new file mode 100644 index 000000000..540fc077b --- /dev/null +++ b/src/Doc/methods/insert/02-insert.js @@ -0,0 +1,80 @@ +const tokenize = require('../../../01-tokenizer') + +/** add these new terms to the end*/ +exports.append = function(str) { + if (!str) { + return this + } + // clear the cache + this.uncache() + //add it to end of every phrase + this.list.forEach(p => { + //build it + let phrase = tokenize.fromText(str, this.world, this.pool())[0] //assume it's one sentence, for now + //tag it + let tmpDoc = this.buildFrom([phrase]) + tmpDoc.tagger() + // push it onto the end + p.append(phrase, this) + }) + return this +} +exports.insertAfter = exports.append +exports.insertAt = exports.append + +/** add these new terms to the front*/ +exports.prepend = function(str) { + if (!str) { + return this + } + // clear the cache + this.uncache() + //add it to start of every phrase + this.list.forEach(p => { + //build it + let phrase = tokenize.fromText(str, this.world, this.pool())[0] //assume it's one sentence, for now + //tag it + let tmpDoc = this.buildFrom([phrase]) + tmpDoc.tagger() + // add it to the start + p.prepend(phrase, this) + }) + return this +} +exports.insertBefore = exports.prepend + +/** add these new things to the end*/ +exports.concat = function() { + // clear the cache + this.uncache() + let list = this.list.slice(0) + //repeat for any number of params + for (let i = 0; i < arguments.length; i++) { + let arg = arguments[i] + //support a fresh string + if (typeof arg === 'string') { + let arr = tokenize.fromText(arg, this.world) + //TODO: phrase.tagger()? + list = list.concat(arr) + } else if (arg.isA === 'Doc') { + list = list.concat(arg.list) + } else if (arg.isA === 'Phrase') { + list.push(arg) + } + } + return this.buildFrom(list) +} + +/** fully remove these terms from the document */ +exports.delete = function(match) { + // clear the cache + this.uncache() + let toRemove = this + if (match) { + toRemove = this.match(match) + } + toRemove.list.forEach(phrase => phrase.delete(this)) + return this +} +// aliases +exports.remove = exports.delete diff --git a/src/Doc/methods/output/01-text.js b/src/Doc/methods/output/01-text.js new file mode 100644 index 000000000..b80f0c1ea --- /dev/null +++ b/src/Doc/methods/output/01-text.js @@ -0,0 +1,25 @@ +/** return the document as text */ +exports.text = function(options) { + options = options || {} + //are we showing every phrase? + let showFull = false + if (this.parents().length === 0) { + showFull = true + } + // cache roots, if necessary + if (options === 'root' || (typeof options === 'object' && options.root)) { + this.list.forEach(p => { + p.terms().forEach(t => { + if (t.root === null) { + t.setRoot(this.world) + } + }) + }) + } + + return this.list.reduce((str, p, i) => { + const trimPre = !showFull && i === 0 + const trimPost = !showFull && i === this.list.length - 1 + return str + p.text(options, trimPre, trimPost) + }, '') +} diff --git a/src/Doc/methods/output/02-json.js b/src/Doc/methods/output/02-json.js new file mode 100644 index 000000000..307511090 --- /dev/null +++ b/src/Doc/methods/output/02-json.js @@ -0,0 +1,108 @@ +const jsonDefaults = { text: true, terms: true, trim: true } + +// get all character startings in doc +const termOffsets = function(doc) { + let elapsed = 0 + let index = 0 + let offsets = {} + doc.termList().forEach(term => { + offsets[term.id] = { + index: index, + start: elapsed + term.pre.length, + length: term.text.length, + } + elapsed += term.pre.length + term.text.length + term.post.length + index += 1 + }) + return offsets +} + +/** pull out desired metadata from the document */ +exports.json = function(options = {}) { + //support json(3) format + if (typeof options === 'number' && this.list[options]) { + return this.list[options].json(jsonDefaults) + } + options = Object.assign({}, jsonDefaults, options) + + // cache roots, if necessary + if (options === 'root' || (typeof options === 'object' && options.root)) { + this.list.forEach(p => { + p.terms().forEach(t => { + if (t.root === null) { + t.setRoot(this.world) + } + }) + }) + } + + if (options.unique) { + options.reduced = true + } + if (options.offset) { + options.terms = options.terms === true ? {} : options.terms + options.terms.offset = true + } + if (options.index || options.terms.index) { + options.terms = options.terms === true ? {} : options.terms + options.terms.id = true + } + let result = this.list.map(p => { + return p.json(options, this.world) + }) + // add offset and index data for each term + if (options.terms.offset || options.offset || options.terms.index || options.index) { + // calculate them, (from beginning of doc) + let offsets = termOffsets(this.all()) + // add index values + if (options.terms.index || options.index) { + result.forEach(o => { + o.terms.forEach(t => { + t.index = offsets[t.id].index + }) + o.index = o.terms[0].index + }) + } + // add offset values + if (options.terms.offset || options.offset) { + result.forEach(o => { + o.terms.forEach(t => { + t.offset = offsets[t.id] || {} + }) + let len = o.terms.reduce((n, t) => { + n += t.offset.length || 0 + return n + }, 0) + o.offset = o.terms[0].offset + o.offset.length = len + }) + } + } + // add frequency #s + if (options.frequency || options.freq || options.count) { + let obj = {} + this.list.forEach(p => { + let str = p.text('reduced') + obj[str] = obj[str] || 0 + obj[str] += 1 + }) + this.list.forEach((p, i) => { + result[i].count = obj[p.text('reduced')] + }) + } + // remove duplicates + if (options.unique) { + let already = {} + result = result.filter(o => { + if (already[o.reduced] === true) { + return false + } + already[o.reduced] = true + return true + }) + } + return result +} + +//aliases +exports.data = exports.json diff --git a/src/Doc/methods/output/03-out.js b/src/Doc/methods/output/03-out.js new file mode 100644 index 000000000..3f9324906 --- /dev/null +++ b/src/Doc/methods/output/03-out.js @@ -0,0 +1,52 @@ +const debug = require('../_debug') +const topk = require('./_topk') + +/** pretty-print the current document and its tags */ +exports.debug = function() { + debug(this) + return this +} + +/** some named output formats */ +exports.out = function(method) { + if (method === 'text') { + return this.text() + } + if (method === 'normal') { + return this.text('normal') + } + if (method === 'json') { + return this.json() + } + if (method === 'offset' || method === 'offsets') { + return this.json({ offset: true }) + } + if (method === 'array') { + return this.json({ terms: false }).map(obj => obj.text) + } + if (method === 'freq' || method === 'frequency') { + return topk(this) + } + if (method === 'terms') { + let list = [] + this.json({ text: false, terms: { text: true } }).forEach(obj => { + let terms = obj.terms.map(t => t.text) + terms = terms.filter(t => t) + list = list.concat(terms) + }) + return list + } + if (method === 'tags') { + return this.list.map(p => { + return p.terms().reduce((h, t) => { + h[t.clean || t.implicit] = Object.keys(t.tags) + return h + }, {}) + }) + } + if (method === 'debug') { + debug(this) + return this + } + return this.text() +} diff --git a/src/Doc/methods/output/04-export.js b/src/Doc/methods/output/04-export.js new file mode 100644 index 000000000..49bc497b2 --- /dev/null +++ b/src/Doc/methods/output/04-export.js @@ -0,0 +1,75 @@ +// compress a list of things by frequency +const topk = function(list) { + let counts = {} + list.forEach(a => { + counts[a] = counts[a] || 0 + counts[a] += 1 + }) + let arr = Object.keys(counts) + arr = arr.sort((a, b) => { + if (counts[a] > counts[b]) { + return -1 + } else { + return 1 + } + }) + // arr = arr.filter(a => counts[a] > 1) + return arr.map(a => [a, counts[a]]) +} + +// remove implied tags, like 'Noun' when we have 'Plural' +const reduceTags = function(tags, world) { + let tagset = world.tags + let implied = [] + tags.forEach(tag => { + if (tagset[tag] && tagset[tag].isA) { + implied = implied.concat(tagset[tag].isA) + } + }) + implied = implied.reduce((h, tag) => { + h[tag] = true + return h + }, {}) + tags = tags.filter(tag => !implied[tag]) + // tags + return tags +} + +/** store a parsed document for later use */ +exports.export = function() { + let phraseList = this.json({ text: true, trim: false, terms: { tags: true, whitespace: true } }) + // let phraseList = json.map(p => p.terms) + let allTags = [] + phraseList.forEach(p => { + p.terms.forEach(t => { + // reduce redundant tags + let tags = reduceTags(t.tags, this.world) + allTags = allTags.concat(tags) + }) + }) + // compress the top tags + allTags = topk(allTags) + let tagMap = {} + allTags.forEach((a, i) => { + tagMap[a[0]] = i + }) + + //use index numbers instead of redundant tag-names + phraseList = phraseList.map(p => { + let terms = p.terms.map(term => { + let tags = term.tags + tags = reduceTags(tags, this.world) + tags = tags.map(tag => tagMap[tag]) + tags = tags.join(',') + return tags + }) + terms = terms.join('|') + return [p.text, terms] + }) + + return { + tags: Object.keys(tagMap), + // words: {}, + list: phraseList, + } +} diff --git a/src/Doc/methods/output/_topk.js b/src/Doc/methods/output/_topk.js new file mode 100644 index 000000000..8d65f85da --- /dev/null +++ b/src/Doc/methods/output/_topk.js @@ -0,0 +1,24 @@ +const topk = function(doc) { + let list = doc.json({ text: false, terms: false, reduced: true }) + // combine them + let obj = {} + list.forEach(o => { + if (!obj[o.reduced]) { + o.count = 0 + obj[o.reduced] = o + } + obj[o.reduced].count += 1 + }) + let arr = Object.keys(obj).map(k => obj[k]) + // sort them + arr.sort((a, b) => { + if (a.count > b.count) { + return -1 + } else if (a.count < b.count) { + return 1 + } + return 0 + }) + return arr +} +module.exports = topk diff --git a/src/Doc/methods/transform/01-sort.js b/src/Doc/methods/transform/01-sort.js new file mode 100644 index 000000000..fa5fd60f9 --- /dev/null +++ b/src/Doc/methods/transform/01-sort.js @@ -0,0 +1,142 @@ +const methods = { + /** alphabetical order */ + alpha: (a, b) => { + let left = a.text('clean') + let right = b.text('clean') + if (left < right) { + return -1 + } + if (left > right) { + return 1 + } + return 0 + }, + + /** count the # of characters of each match */ + length: (a, b) => { + let left = a.text().trim().length + let right = b.text().trim().length + if (left < right) { + return 1 + } + if (left > right) { + return -1 + } + return 0 + }, + + /** count the # of terms in each match */ + wordCount: (a, b) => { + let left = a.wordCount() + let right = b.wordCount() + if (left < right) { + return 1 + } + if (left > right) { + return -1 + } + return 0 + }, +} + +/** sort by # of duplicates in the document*/ +const byFreq = function(doc) { + let counts = {} + const options = { + case: true, + punctuation: false, + whitespace: true, + unicode: true, + } + doc.list.forEach(p => { + let str = p.text(options) + counts[str] = counts[str] || 0 + counts[str] += 1 + }) + // sort by freq + doc.list.sort((a, b) => { + let left = counts[a.text(options)] + let right = counts[b.text(options)] + if (left < right) { + return 1 + } + if (left > right) { + return -1 + } + return 0 + }) + return doc +} + +// order results 'chronologically', or document-order +const sortSequential = function(doc) { + let order = {} + doc.json({ terms: { offset: true } }).forEach(o => { + order[o.terms[0].id] = o.terms[0].offset.start + }) + doc.list = doc.list.sort((a, b) => { + if (order[a.start] > order[b.start]) { + return 1 + } else if (order[a.start] < order[b.start]) { + return -1 + } + return 0 + }) + return doc +} + +//aliases +methods.alphabetical = methods.alpha +methods.wordcount = methods.wordCount + +// aliases for sequential ordering +const seqNames = { + index: true, + sequence: true, + seq: true, + sequential: true, + chron: true, + chronological: true, +} + +/** re-arrange the order of the matches (in place) */ +exports.sort = function(input) { + input = input || 'alpha' + //do this one up-front + if (input === 'freq' || input === 'frequency' || input === 'topk') { + return byFreq(this) + } + if (seqNames.hasOwnProperty(input)) { + return sortSequential(this) + } + + input = methods[input] || input + // apply sort method on each phrase + if (typeof input === 'function') { + this.list = this.list.sort(input) + return this + } + return this +} + +/** reverse the order of the matches, but not the words */ +exports.reverse = function() { + let list = [].concat(this.list) + list = list.reverse() + return this.buildFrom(list) +} + +/** remove any duplicate matches */ +exports.unique = function() { + let list = [].concat(this.list) + let obj = {} + list = list.filter(p => { + let str = p.text('reduced').trim() + if (obj.hasOwnProperty(str) === true) { + return false + } + obj[str] = true + return true + }) + return this.buildFrom(list) +} diff --git a/src/Doc/methods/transform/02-normalize.js b/src/Doc/methods/transform/02-normalize.js new file mode 100644 index 000000000..085d80549 --- /dev/null +++ b/src/Doc/methods/transform/02-normalize.js @@ -0,0 +1,123 @@ +const methods = require('./_methods') + +const defaults = { + // light + whitespace: true, + unicode: true, + punctuation: true, + emoji: true, + acronyms: true, + abbreviations: true, + + // medium + case: false, + contractions: false, + parentheses: false, + quotations: false, + adverbs: false, + + // heavy (loose legibility) + possessives: false, + verbs: false, + nouns: false, + honorifics: false, + + // pronouns: true, +} +const mapping = { + light: {}, + medium: { case: true, contractions: true, parentheses: true, quotations: true, adverbs: true }, +} +mapping.heavy = Object.assign({}, mapping.medium, { possessives: true, verbs: true, nouns: true, honorifics: true }) + +/** common ways to clean-up the document, and reduce noise */ +exports.normalize = function(options) { + options = options || {} + // support named forms + if (typeof options === 'string') { + options = mapping[options] || {} + } + // set defaults + options = Object.assign({}, defaults, options) + // clear the cache + this.uncache() + + let termList = this.termList() + + // lowercase things + if (options.case) { + this.toLowerCase() + } + + //whitespace + if (options.whitespace) { + methods.whitespace(this) + } + + // unicode: é -> e + if (options.unicode) { + methods.unicode(termList) + } + + //punctuation - keep sentence punctation, quotes, parenths + if (options.punctuation) { + methods.punctuation(termList) + } + + // remove ':)' + if (options.emoji) { + this.remove('(#Emoji|#Emoticon)') + } + + // 'f.b.i.' -> 'FBI' + if (options.acronyms) { + this.acronyms().strip() + // .toUpperCase() + } + // remove period from abbreviations + if (options.abbreviations) { + methods.abbreviations(this) + } + + // --Medium methods-- + + // `isn't` -> 'is not' + if (options.contraction || options.contractions) { + this.contractions().expand() + } + + // '(word)' -> 'word' + if (options.parentheses) { + this.parentheses().unwrap() + } + // remove "" punctuation + if (options.quotations || options.quotes) { + methods.quotations(termList) + } + + // remove any un-necessary adverbs + if (options.adverbs) { + methods.adverbs(this) + } + + // --Heavy methods-- + + // `cory hart's -> cory hart' + if (options.possessive || options.possessives) { + this.possessives().strip() + } + // 'he walked' -> 'he walk' + if (options.verbs) { + this.verbs().toInfinitive() + } + // 'three dogs' -> 'three dog' + if (options.nouns || options.plurals) { + this.nouns().toSingular() + } + // remove 'Mr.' from 'Mr John Smith' + if (options.honorifics) { + this.remove('#Honorific') + } + + return this +} diff --git a/src/Doc/methods/transform/03-split.js b/src/Doc/methods/transform/03-split.js new file mode 100644 index 000000000..0508f3453 --- /dev/null +++ b/src/Doc/methods/transform/03-split.js @@ -0,0 +1,151 @@ +const parseSyntax = require('../../match/syntax') + +/** return a Document with three parts for every match + * seperate everything before the word, as a new phrase + */ +exports.splitOn = function(reg) { + // if there's no match, split parent, instead + if (!reg) { + let parent = this.parent() + return parent.splitOn(this) + } + //start looking for a match.. + let regs = parseSyntax(reg) + let matches = [] + this.list.forEach(p => { + let foundEm = p.match(regs) + //no match here, add full sentence + if (foundEm.length === 0) { + matches.push(p) + return + } + // we found something here. + let carry = p + foundEm.forEach(found => { + let parts = carry.splitOn(found) + // add em in + if (parts.before) { + matches.push(parts.before) + } + if (parts.match) { + matches.push(parts.match) + } + // start matching now on the end + carry = parts.after + }) + // add that last part + if (carry) { + matches.push(carry) + } + }) + return this.buildFrom(matches) +} + +/** return a Document with two parts for every match + * seperate everything after the word, as a new phrase + */ +exports.splitAfter = function(reg) { + // if there's no match, split parent, instead + if (!reg) { + let parent = this.parent() + return parent.splitAfter(this) + } + // start looking for our matches + let regs = parseSyntax(reg) + let matches = [] + this.list.forEach(p => { + let foundEm = p.match(regs) + //no match here, add full sentence + if (foundEm.length === 0) { + matches.push(p) + return + } + // we found something here. + let carry = p + foundEm.forEach(found => { + let parts = carry.splitOn(found) + // add em in + if (parts.before && parts.match) { + // merge these two together + parts.before.length += parts.match.length + matches.push(parts.before) + } else if (parts.match) { + matches.push(parts.match) + } + // start matching now on the end + carry = parts.after + }) + // add that last part + if (carry) { + matches.push(carry) + } + }) + return this.buildFrom(matches) +} +exports.split = exports.splitAfter //i guess? + +/** return a Document with two parts for every match */ +exports.splitBefore = function(reg) { + // if there's no match, split parent, instead + if (!reg) { + let parent = this.parent() + return parent.splitBefore(this) + } + //start looking for a match.. + let regs = parseSyntax(reg) + let matches = [] + this.list.forEach(p => { + let foundEm = p.match(regs) + //no match here, add full sentence + if (foundEm.length === 0) { + matches.push(p) + return + } + // we found something here. + let carry = p + foundEm.forEach(found => { + let parts = carry.splitOn(found) + // add before part in + if (parts.before) { + matches.push(parts.before) + } + // merge match+after + if (parts.match && parts.after) { + parts.match.length += parts.after.length + } + // start matching now on the end + carry = parts.match + }) + // add that last part + if (carry) { + matches.push(carry) + } + }) + return this.buildFrom(matches) +} + +/** split a document into labeled sections */ +exports.segment = function(regs, options) { + regs = regs || {} + options = options || { text: true } + let doc = this + let keys = Object.keys(regs) + // split em + keys.forEach(k => { + doc = doc.splitOn(k) + }) + //add labels for each section + doc.list.forEach(p => { + for (let i = 0; i < keys.length; i += 1) { + if (p.has(keys[i])) { + p.segment = regs[keys[i]] + return + } + } + }) + return doc.list.map(p => { + let res = p.json(options) + res.segment = p.segment || null + return res + }) +} diff --git a/src/Doc/methods/transform/04-case.js b/src/Doc/methods/transform/04-case.js new file mode 100644 index 000000000..3e32b546f --- /dev/null +++ b/src/Doc/methods/transform/04-case.js @@ -0,0 +1,40 @@ +const eachTerm = function(doc, fn) { + let world = doc.world + doc.list.forEach(p => { + p.terms().forEach(t => t[fn](world)) + }) + return doc +} + +/** turn every letter of every term to lower-cse */ +exports.toLowerCase = function() { + return eachTerm(this, 'toLowerCase') +} + +/** turn every letter of every term to upper case */ +exports.toUpperCase = function() { + return eachTerm(this, 'toUpperCase') +} + +/** upper-case the first letter of each term */ +exports.toTitleCase = function() { + this.tag('TitleCase') + return eachTerm(this, 'toTitleCase') +} +/** remove whitespace and title-case each term */ +exports.toCamelCase = function() { + this.list.forEach(p => { + //remove whitespace + let terms = p.terms() + terms.forEach((t, i) => { + if (i !== 0) { + t.toTitleCase() + } + if (i !== terms.length - 1) { + t.post = '' + } + }) + }) + // this.tag('#CamelCase', 'toCamelCase') + return this +} diff --git a/src/Doc/methods/transform/05-whitespace.js b/src/Doc/methods/transform/05-whitespace.js new file mode 100644 index 000000000..91a99e814 --- /dev/null +++ b/src/Doc/methods/transform/05-whitespace.js @@ -0,0 +1,96 @@ +/** add this punctuation or whitespace before each match: */ +exports.pre = function(str) { + if (str === undefined) { + return this.list[0].terms(0).pre + } + this.list.forEach(p => { + let term = p.terms(0) + term.pre = str + }) + return this +} + +/** add this punctuation or whitespace after each match: */ +exports.post = function(str) { + // return array of post strings + if (str === undefined) { + return this.list.map(p => { + let terms = p.terms() + let term = terms[terms.length - 1] + return term.post + }) + } + // set post string on all ends + this.list.forEach(p => { + let terms = p.terms() + let term = terms[terms.length - 1] + term.post = str + }) + return this +} + +/** remove start and end whitespace */ +exports.trim = function() { + this.list = this.list.map(p => p.trim()) + return this +} + +/** connect words with hyphen, and remove whitespace */ +exports.hyphenate = function() { + this.list.forEach(p => { + let terms = p.terms() + //remove whitespace + terms.forEach((t, i) => { + if (i !== 0) { + t.pre = '' + } + if (terms[i + 1]) { + t.post = '-' + } + }) + }) + return this +} + +/** remove hyphens between words, and set whitespace */ +exports.dehyphenate = function() { + const hasHyphen = /(-|–|—)/ + this.list.forEach(p => { + let terms = p.terms() + //remove whitespace + terms.forEach(t => { + if (hasHyphen.test(t.post)) { + t.post = ' ' + } + }) + }) + return this +} +exports.deHyphenate = exports.dehyphenate + +/** add quotations around these matches */ +exports.toQuotations = function(start, end) { + start = start || `"` + end = end || `"` + this.list.forEach(p => { + let terms = p.terms() + terms[0].pre = start + terms[0].pre + let last = terms[terms.length - 1] + last.post = end + last.post + }) + return this +} +exports.toQuotation = exports.toQuotations + +/** add brackets around these matches */ +exports.toParentheses = function(start, end) { + start = start || `(` + end = end || `)` + this.list.forEach(p => { + let terms = p.terms() + terms[0].pre = start + terms[0].pre + let last = terms[terms.length - 1] + last.post = end + last.post + }) + return this +} diff --git a/src/Doc/methods/transform/06-join.js b/src/Doc/methods/transform/06-join.js new file mode 100644 index 000000000..00f25aa13 --- /dev/null +++ b/src/Doc/methods/transform/06-join.js @@ -0,0 +1,43 @@ +/** make all phrases into one phrase */ +exports.join = function(str) { + // clear the cache + this.uncache() + // make one large phrase - 'main' + let main = this.list[0] + let before = main.length + let removed = {} + for (let i = 1; i < this.list.length; i++) { + const p = this.list[i] + removed[p.start] = true + let term = main.lastTerm() + // add whitespace between them + if (str) { + term.post += str + } + // main -> p + term.next = p.start + // main <- p + p.terms(0).prev = term.id + main.length += p.length + } + + // parents are bigger than than their children. + // when we increase a child, we increase their parent too. + let increase = main.length - before + this.parents().forEach(doc => { + // increase length on each effected phrase + doc.list.forEach(p => { + let terms = p.terms() + for (let i = 0; i < terms.length; i++) { + if (terms[i].id === main.start) { + p.length += increase + break + } + } + }) + // remove redundant phrases now + doc.list = doc.list.filter(p => removed[p.start] !== true) + }) + // return one major phrase + return this.buildFrom([main]) +} diff --git a/src/Doc/methods/transform/07-contract.js b/src/Doc/methods/transform/07-contract.js new file mode 100644 index 000000000..3e5997a74 --- /dev/null +++ b/src/Doc/methods/transform/07-contract.js @@ -0,0 +1,69 @@ +const postPunct = /[,\)"';:\-–—\.…]/ +// const irregulars = { +// 'will not': `won't`, +// 'i am': `i'm`, +// } + +const setContraction = function(m, suffix) { + if (!m.found) { + return + } + let terms = m.termList() + //avoid any problematic punctuation + for (let i = 0; i < terms.length - 1; i++) { + const t = terms[i] + if (postPunct.test(t.post)) { + return + } + } + + // set them as implict + terms.forEach(t => { + t.implicit = t.clean + }) + // perform the contraction + terms[0].text += suffix + // clean-up the others + terms.slice(1).forEach(t => { + t.text = '' + }) + for (let i = 0; i < terms.length - 1; i++) { + const t = terms[i] + t.post = t.post.replace(/ /, '') + } +} + +/** turn 'i am' into i'm */ +exports.contract = function() { + let doc = this.not('@hasContraction') + // we are -> we're + let m = doc.match('(we|they|you) are') + setContraction(m, `'re`) + // they will -> they'll + m = doc.match('(he|she|they|it|we|you) will') + setContraction(m, `'ll`) + // she is -> she's + m = doc.match('(he|she|they|it|we) is') + setContraction(m, `'s`) + // spencer is -> spencer's + m = doc.match('#Person is') + setContraction(m, `'s`) + // spencer would -> spencer'd + m = doc.match('#Person would') + setContraction(m, `'d`) + // would not -> wouldn't + m = doc.match('(is|was|had|would|should|could|do|does|have|has|can) not') + setContraction(m, `n't`) + // i have -> i've + m = doc.match('(i|we|they) have') + setContraction(m, `'ve`) + // would have -> would've + m = doc.match('(would|should|could) have') + setContraction(m, `'ve`) + // i am -> i'm + m = doc.match('i am') + setContraction(m, `'m`) + // going to -> gonna + m = doc.match('going to') + return this +} diff --git a/src/Doc/methods/transform/_methods.js b/src/Doc/methods/transform/_methods.js new file mode 100644 index 000000000..e14583f50 --- /dev/null +++ b/src/Doc/methods/transform/_methods.js @@ -0,0 +1,95 @@ +const killUnicode = require('../../../Term/normalize/unicode') +const isPunct = /[\[\]{}⟨⟩:,،、‒–—―…‹›«»‐\-;\/⁄·*\•^†‡°¡¿※№÷׺ª%‰=‱¶§~|‖¦©℗®℠™¤₳฿]/g +const quotes = /['‘’“”"′″‴]+/g + +const methods = { + // cleanup newlines and extra spaces + whitespace: function(doc) { + let termArr = doc.list.map(ts => ts.terms()) + termArr.forEach((terms, o) => { + terms.forEach((t, i) => { + // keep dashes between words + if (t.hasDash() === true) { + t.post = ' - ' + return + } + // remove existing spaces + t.pre = t.pre.replace(/\s/g, '') + t.post = t.post.replace(/\s/g, '') + //last word? ensure there's a next sentence. + if (terms.length - 1 === i && !termArr[o + 1]) { + return + } + // no extra spaces for contractions + if (t.implicit && Boolean(t.text) === true) { + return + } + // no extra spaces for hyphenated words + if (t.hasHyphen() === true) { + return + } + + t.post += ' ' + }) + }) + }, + + punctuation: function(termList) { + termList.forEach(t => { + // space between hyphenated words + if (t.hasHyphen() === true) { + t.post = ' ' + } + t.pre = t.pre.replace(isPunct, '') + t.post = t.post.replace(isPunct, '') + // elipses + t.post = t.post.replace(/\.\.\./, '') + // only allow one exclamation + if (/!/.test(t.post) === true) { + t.post = t.post.replace(/!/g, '') + t.post = '!' + t.post + } + // only allow one question mark + if (/\?/.test(t.post) === true) { + t.post = t.post.replace(/[\?!]*/, '') + t.post = '?' + t.post + } + }) + }, + + unicode: function(termList) { + termList.forEach(t => { + if (t.isImplicit() === true) { + return + } + t.text = killUnicode(t.text) + }) + }, + + quotations: function(termList) { + termList.forEach(t => { + t.post = t.post.replace(quotes, '') + t.pre = t.pre.replace(quotes, '') + }) + }, + + adverbs: function(doc) { + doc + .match('#Adverb') + .not('(not|nary|seldom|never|barely|almost|basically|so)') + .remove() + }, + + // remove the '.' from 'Mrs.' (safely) + abbreviations: function(doc) { + doc.list.forEach(ts => { + let terms = ts.terms() + terms.forEach((t, i) => { + if (t.tags.Abbreviation === true && terms[i + 1]) { + t.post = t.post.replace(/^\./, '') + } + }) + }) + }, +} +module.exports = methods diff --git a/src/Phrase/Phrase.js b/src/Phrase/Phrase.js new file mode 100644 index 000000000..88c0afa6a --- /dev/null +++ b/src/Phrase/Phrase.js @@ -0,0 +1,47 @@ +const methods = require('./methods') +const matchMethods = require('./match') +// const tokenize = require('../01-tokenizer') + +class Phrase { + constructor(id, length, pool) { + this.start = id + this.length = length + this.isA = 'Phrase' // easier than .constructor... + Object.defineProperty(this, 'pool', { + enumerable: false, + writable: true, + value: pool, + }) + Object.defineProperty(this, 'cache', { + enumerable: false, + writable: true, + value: {}, + }) + } +} + +/** create a new Phrase object from an id and length */ +Phrase.prototype.buildFrom = function(id, length) { + let p = new Phrase(id, length, this.pool) + if (this.cache) { + p.cache = this.cache + p.cache.terms = null + } + return p +} +// Phrase.prototype.fromString = function(str) { +// console.log(tokenize) +// return tokenize.fromText(str) +// } + +//apply methods +Object.assign(Phrase.prototype, matchMethods) +Object.assign(Phrase.prototype, methods) + +//apply aliases +const aliases = { + term: 'terms', +} +Object.keys(aliases).forEach(k => (Phrase.prototype[k] = Phrase.prototype[aliases[k]])) + +module.exports = Phrase diff --git a/src/Phrase/insert/append.js b/src/Phrase/insert/append.js new file mode 100644 index 000000000..f39be194e --- /dev/null +++ b/src/Phrase/insert/append.js @@ -0,0 +1,91 @@ +const endOfSentence = /[.?!]\s*$/ + +// replacing a 'word.' with a 'word!' +const combinePost = function(before, after) { + //only transfer the whitespace + if (endOfSentence.test(after)) { + let whitespace = before.match(/\s*$/) + return after + whitespace + } + return before +} + +//add whitespace to the start of the second bit +const addWhitespace = function(beforeTerms, newTerms) { + // add any existing pre-whitespace to beginning + newTerms[0].pre = beforeTerms[0].pre + let lastTerm = beforeTerms[beforeTerms.length - 1] + + //add any existing punctuation to end of our new terms + let newTerm = newTerms[newTerms.length - 1] + newTerm.post = combinePost(lastTerm.post, newTerm.post) + // remove existing punctuation + lastTerm.post = '' + + //before ←[space] - after + if (lastTerm.post === '') { + lastTerm.post += ' ' + } +} + +//insert this segment into the linked-list +const stitchIn = function(main, newPhrase) { + // console.log(main.text(), newPhrase.text()) + let afterId = main.lastTerm().next + //connect ours in (main → newPhrase) + main.lastTerm().next = newPhrase.start + //stich the end in (newPhrase → after) + newPhrase.lastTerm().next = afterId + //do it backwards, too + if (afterId) { + // newPhrase ← after + let afterTerm = main.pool.get(afterId) + afterTerm.prev = newPhrase.lastTerm().id + } + // before ← newPhrase + let beforeId = main.terms(0).id + if (beforeId) { + let newTerm = newPhrase.terms(0) + newTerm.prev = beforeId + } +} + +// avoid stretching a phrase twice. +const unique = function(list) { + return list.filter((o, i) => { + return list.indexOf(o) === i + }) +} + +//append one phrase onto another. +const appendPhrase = function(before, newPhrase, doc) { + let beforeTerms = before.terms() + //spruce-up the whitespace issues + addWhitespace(beforeTerms, newPhrase.terms()) + //insert this segment into the linked-list + stitchIn(before, newPhrase) + + // stretch! + // make each effected phrase longer + let toStretch = [before] + let hasId = before.start + let docs = [doc] + + docs = docs.concat(doc.parents()) // find them all! + + docs.forEach(parent => { + // only the phrases that should change + let shouldChange = parent.list.filter(p => { + return p.hasId(hasId) + }) + toStretch = toStretch.concat(shouldChange) + }) + // don't double-count a phrase + toStretch = unique(toStretch) + // console.log(toStretch) + toStretch.forEach(p => { + p.length += newPhrase.length + }) + return before +} +module.exports = appendPhrase diff --git a/src/Phrase/insert/delete.js b/src/Phrase/insert/delete.js new file mode 100644 index 000000000..efe814531 --- /dev/null +++ b/src/Phrase/insert/delete.js @@ -0,0 +1,60 @@ +//recursively decrease the length of all the parent phrases +const shrinkAll = function(doc, id, deleteLength, after) { + let arr = doc.parents() + arr.push(doc) + + arr.forEach(d => { + //find our phrase to shrink + let phrase = d.list.find(p => p.hasId(id)) + if (!phrase) { + return + } + phrase.length -= deleteLength + // does it start with this soon-removed word? + if (phrase.start === id) { + phrase.start = after.id + } + }) + // cleanup empty phrase objects + doc.list = doc.list.filter(p => { + if (!p.start || !p.length) { + return false + } + return true + }) +} + +/** wrap the linked-list around these terms + * so they don't appear any more + */ +const deletePhrase = function(phrase, doc) { + let pool = doc.pool() + let terms = phrase.terms() + + //grab both sides of the chain, + let prev = pool.get(terms[0].prev) || {} + let after = pool.get(terms[terms.length - 1].next) || {} + + if (terms[0].implicit && prev.implicit) { + prev.set(prev.implicit) + prev.post += ' ' + } + + // //first, change phrase lengths + shrinkAll(doc, phrase.start, phrase.length, after) + + // connect [prev]->[after] + if (prev) { + prev.next = after.id + } + // connect [prev]<-[after] + if (after) { + after.prev = prev.id + } + + // lastly, actually delete the terms from the pool? + // for (let i = 0; i < terms.length; i++) { + // pool.remove(terms[i].id) + // } +} +module.exports = deletePhrase diff --git a/src/Phrase/insert/prepend.js b/src/Phrase/insert/prepend.js new file mode 100644 index 000000000..95cdd53ef --- /dev/null +++ b/src/Phrase/insert/prepend.js @@ -0,0 +1,105 @@ +const hasSpace = / / + +//a new space needs to be added, either on the new phrase, or the old one +// '[new] [◻old]' -or- '[old] [◻new] [old]' +const addWhitespace = function(newTerms) { + //add a space before our new text? + + // add a space after our text + let lastTerm = newTerms[newTerms.length - 1] + if (hasSpace.test(lastTerm.post) === false) { + lastTerm.post += ' ' + } + + // let term = original.pool.get(original.start) + // if (term.prev) { + // //add our space ahead of our new terms + // let firstWord = newTerms[0] + // if (hasSpace.test(firstWord.post) === false) { + // firstWord.post += ' ' + // } + // return + // } + + //otherwise, add our space to the start of original + // if (hasSpace.test(term.pre) === false) { + // term.pre = ' ' + term.pre + // } + return +} + +//insert this segment into the linked-list +const stitchIn = function(main, newPhrase, newTerms) { + // [newPhrase] → [main] + let lastTerm = newTerms[newTerms.length - 1] + lastTerm.next = main.start + // [before] → [main] + let pool = main.pool + let start = pool.get(main.start) + if (start.prev) { + let before = pool.get(start.prev) + before.next = newPhrase.start + } + //do it backwards, too + // before ← newPhrase + newTerms[0].prev = main.terms(0).prev + // newPhrase ← main + main.terms(0).prev = lastTerm.id +} + +//recursively increase the length of all parent phrases +// const stretchAll = function(doc, oldStart, newPhrase) { +// //find our phrase to stretch +// let phrase = doc.list.find(p => p.hasId(oldStart) || p.hasId(newPhrase.start)) +// if (phrase === undefined) { +// console.error('compromise error: Prepend missing start - ' + oldStart) +// return +// } +// //should we update the phrase's starting? +// if (phrase.start === oldStart) { +// phrase.start = newPhrase.start +// } +// // console.log(newPhrase) +// phrase.length += newPhrase.length +// if (doc.from) { +// stretchAll(doc.from, oldStart, newPhrase) +// } +// } +const unique = function(list) { + return list.filter((o, i) => { + return list.indexOf(o) === i + }) +} + +//append one phrase onto another +const joinPhrase = function(original, newPhrase, doc) { + const starterId = original.start + let newTerms = newPhrase.terms() + //spruce-up the whitespace issues + addWhitespace(newTerms, original) + //insert this segment into the linked-list + stitchIn(original, newPhrase, newTerms) + //increase the length of our phrases + let toStretch = [original] + let docs = [doc] + docs = docs.concat(doc.parents()) + docs.forEach(d => { + // only the phrases that should change + let shouldChange = d.list.filter(p => { + return p.hasId(starterId) || p.hasId(newPhrase.start) + }) + toStretch = toStretch.concat(shouldChange) + }) + // don't double-count + toStretch = unique(toStretch) + // stretch these phrases + toStretch.forEach(p => { + p.length += newPhrase.length + // change the start too, if necessary + if (p.start === starterId) { + p.start = newPhrase.start + } + }) + return original +} +module.exports = joinPhrase diff --git a/src/Phrase/match/01-matchAll.js b/src/Phrase/match/01-matchAll.js new file mode 100644 index 000000000..7ff8e011c --- /dev/null +++ b/src/Phrase/match/01-matchAll.js @@ -0,0 +1,56 @@ +const failFast = require('./02-failFast') +const tryMatch = require('./03-tryMatch') +const syntax = require('../../Doc/match/syntax') + +/** returns a simple array of arrays */ +const matchAll = function(p, regs, matchOne = false) { + //if we forgot to parse it.. + if (typeof regs === 'string') { + regs = syntax(regs) + } + //try to dismiss it, at-once + if (failFast(p, regs) === true) { + return [] + } + + //any match needs to be this long, at least + const minLength = regs.filter(r => r.optional !== true).length + let terms = p.cache.terms || p.terms() + let matches = [] + + //optimisation for '^' start logic + if (regs[0].start === true) { + let match = tryMatch(terms, regs, 0, terms.length) + if (match !== false && match.length > 0) { + matches.push(match) + } + // remove (intentional) null results + matches = matches.map(arr => { + return arr.filter(t => t) + }) + return matches + } + //try starting, from every term + for (let i = 0; i < terms.length; i += 1) { + // slice may be too short + if (i + minLength > terms.length) { + break + } + //try it! + + let match = tryMatch(terms.slice(i), regs, i, terms.length) + if (match !== false && match.length > 0) { + //zoom forward! + i += match.length - 1 + //[capture-groups] return some null responses + match = match.filter(m => m) + matches.push(match) + //ok, maybe that's enough? + if (matchOne === true) { + return matches + } + } + } + return matches +} +module.exports = matchAll diff --git a/src/Phrase/match/02-failFast.js b/src/Phrase/match/02-failFast.js new file mode 100644 index 000000000..c4b655098 --- /dev/null +++ b/src/Phrase/match/02-failFast.js @@ -0,0 +1,28 @@ +// try to avoid doing the match +const failFast = function(p, regs) { + if (regs.length === 0) { + return true + } + for (let i = 0; i < regs.length; i += 1) { + let reg = regs[i] + + // //logical quick-ones + if (reg.optional !== true && reg.negative !== true) { + //start/end impossibilites + if (reg.start === true && i > 0) { + return true + } + // has almost no effect + if (p.cache.words !== undefined && reg.word !== undefined && p.cache.words.hasOwnProperty(reg.word) !== true) { + // console.log('skip') + return true + } + } + //this is not possible + if (reg.anything === true && reg.negative === true) { + return true + } + } + return false +} +module.exports = failFast diff --git a/src/Phrase/match/03-tryMatch.js b/src/Phrase/match/03-tryMatch.js new file mode 100644 index 000000000..8da9f2206 --- /dev/null +++ b/src/Phrase/match/03-tryMatch.js @@ -0,0 +1,154 @@ +// i formally apologize for how complicated this is. + +//found a match? it's greedy? keep going! +const getGreedy = function(terms, t, reg, until, index, length) { + let start = t + for (; t < terms.length; t += 1) { + //stop for next-reg match + if (until && terms[t].doesMatch(until, index + t, length)) { + return t + } + let count = t - start + 1 + // is it max-length now? + if (reg.max !== undefined && count === reg.max) { + return t + } + //stop here + if (terms[t].doesMatch(reg, index + t, length) === false) { + // is it too short? + if (reg.min !== undefined && count < reg.min) { + return null + } + return t + } + } + return t +} + +//'unspecific greedy' is a weird situation. +const greedyTo = function(terms, t, nextReg, index, length) { + //if there's no next one, just go off the end! + if (!nextReg) { + return terms.length + } + //otherwise, we're looking for the next one + for (; t < terms.length; t += 1) { + if (terms[t].doesMatch(nextReg, index + t, length) === true) { + return t + } + } + //guess it doesn't exist, then. + return null +} + +/** tries to match a sequence of terms, starting from here */ +const tryHere = function(terms, regs, index, length) { + let captures = [] + let t = 0 + // we must satisfy each rule in 'regs' + for (let r = 0; r < regs.length; r += 1) { + let reg = regs[r] + + //should we fail here? + if (!terms[t]) { + //are all remaining regs optional? + const hasNeeds = regs.slice(r).some(remain => !remain.optional) + if (hasNeeds === false) { + break + } + // have unmet needs + return false + } + + //support 'unspecific greedy' .* properly + if (reg.anything === true && reg.greedy === true) { + let skipto = greedyTo(terms, t, regs[r + 1], reg, index, length) + // ensure it's long enough + if (reg.min !== undefined && skipto - t < reg.min) { + return false + } + // reduce it back, if it's too long + if (reg.max !== undefined && skipto - t > reg.max) { + t = t + reg.max + continue + } + //TODO: support [*] properly + if (skipto === null) { + return false //couldn't find it + } + t = skipto + continue + } + + //if it looks like a match, continue + if (reg.anything === true || terms[t].doesMatch(reg, index + t, length) === true) { + let startAt = t + // okay, it was a match, but if it optional too, + // we should check the next reg too, to skip it? + if (reg.optional && regs[r + 1]) { + // does the next reg match it too? + if (terms[t].doesMatch(regs[r + 1], index + t, length) === true) { + // but does the next reg match the next term?? + // only skip if it doesn't + if (!terms[t + 1] || terms[t + 1].doesMatch(regs[r + 1], index + t, length) === false) { + r += 1 + } + } + } + //advance to the next term! + t += 1 + //check any ending '$' flags + if (reg.end === true) { + //if this isn't the last term, refuse the match + if (t !== terms.length && reg.greedy !== true) { + return false + } + } + //try keep it going! + if (reg.greedy === true) { + t = getGreedy(terms, t, reg, regs[r + 1], index, length) + if (t === null) { + return false //greedy was too short + } + } + if (reg.capture) { + captures.push(startAt) + //add greedy-end to capture + if (t > 1 && reg.greedy) { + captures.push(t - 1) + } + } + continue + } + + //bah, who cares, keep going + if (reg.optional === true) { + continue + } + // should we skip-over an implicit word? + if (terms[t].isImplicit() && regs[r - 1] && terms[t + 1]) { + // does the next one match? + if (terms[t + 1].doesMatch(reg, index + t, length)) { + t += 2 + continue + } + } + // console.log(' ❌\n\n') + return false + } + + //we got to the end of the regs, and haven't failed! + //try to only return our [captured] segment + if (captures.length > 0) { + //make sure the array is the full-length we'd return anyways + let arr = terms.slice(captures[0], captures[captures.length - 1] + 1) + //make sure the array is t-length (so we skip ahead full-length) + for (let tmp = 0; tmp < t; tmp++) { + arr[tmp] = arr[tmp] || null //these get cleaned-up after + } + return arr + } + //return our result + return terms.slice(0, t) +} +module.exports = tryHere diff --git a/src/Phrase/match/index.js b/src/Phrase/match/index.js new file mode 100644 index 000000000..885404682 --- /dev/null +++ b/src/Phrase/match/index.js @@ -0,0 +1,54 @@ +const matchAll = require('./01-matchAll') +const notMatch = require('./not') + +/** return an array of matching phrases */ +exports.match = function(str) { + let matches = matchAll(this, str) + //make them phrase objects + matches = matches.map(list => { + return this.buildFrom(list[0].id, list.length) + }) + return matches +} + +/** return boolean if one match is found */ +exports.has = function(str) { + let matches = matchAll(this, str, true) + return matches.length > 0 +} + +/** remove all matches from the result */ +exports.not = function(str) { + let matches = notMatch(this, str) + //make them phrase objects + matches = matches.map(list => { + return this.buildFrom(list[0].id, list.length) + }) + return matches +} + +/** return a list of phrases that can have this tag */ +exports.canBe = function(tag, world) { + let results = [] + let terms = this.terms() + let previous = false + for (let i = 0; i < terms.length; i += 1) { + let can = terms[i].canBe(tag, world) + if (can === true) { + if (previous === true) { + //add it to the end + results[results.length - 1].push(terms[i]) + } else { + results.push([terms[i]]) //make a new one + } + previous = can + } + } + //turn them into Phrase objects + results = results + .filter(a => a.length > 0) + .map(arr => { + return this.buildFrom(arr[0].id, arr.length) + }) + return results +} diff --git a/src/Phrase/match/not.js b/src/Phrase/match/not.js new file mode 100644 index 000000000..880b9478e --- /dev/null +++ b/src/Phrase/match/not.js @@ -0,0 +1,33 @@ +const matchAll = require('./01-matchAll') + +/** return anything that doesn't match. + * returns a simple array of arrays + */ +const notMatch = function(p, regs) { + let found = {} + let arr = matchAll(p, regs) + arr.forEach(ts => { + ts.forEach(t => { + found[t.id] = true + }) + }) + //return anything not found + let terms = p.terms() + let result = [] + let current = [] + terms.forEach(t => { + if (found[t.id] === true) { + if (current.length > 0) { + result.push(current) + current = [] + } + return + } + current.push(t) + }) + if (current.length > 0) { + result.push(current) + } + return result +} +module.exports = notMatch diff --git a/src/Phrase/methods/01-utils.js b/src/Phrase/methods/01-utils.js new file mode 100644 index 000000000..06c9656fd --- /dev/null +++ b/src/Phrase/methods/01-utils.js @@ -0,0 +1,82 @@ +/** return a flat array of Term objects */ +exports.terms = function(n) { + let terms = [this.pool.get(this.start)] + if (this.length === 0) { + return [] + } + for (let i = 0; i < this.length - 1; i += 1) { + let id = terms[terms.length - 1].next + if (id === null) { + // throw new Error('linked-list broken') + console.error("Compromise error: Linked list broken in phrase '" + this.start + "'") + break + } + let term = this.pool.get(id) + terms.push(term) + //return this one? + if (n !== undefined && n === i) { + return terms[n] + } + } + if (n !== undefined) { + return terms[n] + } + return terms +} + +/** return a shallow or deep copy of this phrase */ +exports.clone = function(isShallow) { + if (isShallow) { + return this.buildFrom(this.start, this.length) + } + //how do we clone part of the pool? + let terms = this.terms() + let newTerms = terms.map(t => t.clone()) + //connect these new ids up + newTerms.forEach((t, i) => { + //add it to the pool.. + this.pool.add(t) + if (newTerms[i + 1]) { + t.next = newTerms[i + 1].id + } + if (newTerms[i - 1]) { + t.prev = newTerms[i - 1].id + } + }) + return this.buildFrom(newTerms[0].id, newTerms.length) +} + +/** return last term object */ +exports.lastTerm = function() { + let terms = this.terms() + return terms[terms.length - 1] +} + +/** quick lookup for a term id */ +exports.hasId = function(wantId) { + if (this.length === 0 || !wantId) { + return false + } + if (this.start === wantId) { + return true + } + let lastId = this.start + for (let i = 0; i < this.length - 1; i += 1) { + let term = this.pool.get(lastId) + if (term === undefined) { + console.error(`Compromise error: Linked list broken. Missing term '${lastId}' in phrase '${this.start}'\n`) + // throw new Error('linked List error') + return false + } + if (term.next === wantId) { + return true + } + lastId = term.next + } + return false +} + +/** how many seperate, non-empty words is it? */ +exports.wordCount = function() { + return this.terms().filter(t => t.text !== '').length +} diff --git a/src/Phrase/methods/02-text.js b/src/Phrase/methods/02-text.js new file mode 100644 index 000000000..8183ac822 --- /dev/null +++ b/src/Phrase/methods/02-text.js @@ -0,0 +1,86 @@ +const trimEnd = function(str) { + return str.replace(/ +$/, '') +} + +/** produce output in the given format */ +exports.text = function(options = {}, isFirst, isLast) { + if (typeof options === 'string') { + if (options === 'normal') { + options = { + whitespace: true, + unicode: true, + lowercase: true, + punctuation: true, + acronyms: true, + abbreviations: true, + implicit: true, + normal: true, + } + } else if (options === 'clean') { + options = { + titlecase: false, + lowercase: true, + punctuation: true, + whitespace: true, + unicode: true, + implicit: true, + } + } else if (options === 'reduced') { + options = { + titlecase: false, + lowercase: true, + punctuation: false, //FIXME: reversed + whitespace: true, + unicode: true, + implicit: true, + reduced: true, + } + } else if (options === 'root') { + options = { + titlecase: false, + lowercase: true, + punctuation: true, + whitespace: true, + unicode: true, + implicit: true, + root: true, + } + } else { + options = {} + } + } + let terms = this.terms() + //this this phrase a complete sentence? + let isFull = false + if (terms[0] && terms[0].prev === null && terms[terms.length - 1].next === null) { + isFull = true + } + let text = terms.reduce((str, t, i) => { + options.last = isLast && i === terms.length - 1 + let showPre = true + let showPost = true + if (isFull === false) { + // dont show beginning whitespace + if (i === 0 && isFirst) { + showPre = false + } + // dont show end-whitespace + if (i === terms.length - 1 && isLast) { + showPost = false + } + } + let txt = t.textOut(options, showPre, showPost) + // if (options.titlecase && i === 0) { + // txt = titleCase(txt) + // } + return str + txt + }, '') + //full-phrases show punctuation, but not whitespace + if (isFull === true && isLast) { + text = trimEnd(text) + } + if (options.trim) { + text = text.trim() + } + return text +} diff --git a/src/Phrase/methods/03-change.js b/src/Phrase/methods/03-change.js new file mode 100644 index 000000000..74c176772 --- /dev/null +++ b/src/Phrase/methods/03-change.js @@ -0,0 +1,12 @@ +/** remove start and end whitespace */ +exports.trim = function() { + let terms = this.terms() + if (terms.length > 0) { + //trim starting + terms[0].pre = terms[0].pre.replace(/^\s+/, '') + //trim ending + let lastTerm = terms[terms.length - 1] + lastTerm.post = lastTerm.post.replace(/\s+$/, '') + } + return this +} diff --git a/src/Phrase/methods/04-insert.js b/src/Phrase/methods/04-insert.js new file mode 100644 index 000000000..34d52f807 --- /dev/null +++ b/src/Phrase/methods/04-insert.js @@ -0,0 +1,66 @@ +const append = require('../insert/append') +const prepend = require('../insert/prepend') +const deletePhrase = require('../insert/delete') +// const tokenize = require('../../01-tokenizer') + +/** put this text at the end */ +exports.append = function(newPhrase, doc) { + append(this, newPhrase, doc) + return this +} + +/** add this text to the beginning */ +exports.prepend = function(newPhrase, doc) { + prepend(this, newPhrase, doc) + return this +} + +exports.delete = function(doc) { + deletePhrase(this, doc) + return this +} + +// stich-in newPhrase, stretch 'doc' + parents +exports.replace = function(newPhrase, doc) { + // doc.debug() + //add it do the end + let firstLength = this.length + append(this, newPhrase, doc) + + //delete original terms + let tmp = this.buildFrom(this.start, this.length) + tmp.length = firstLength + // console.log(tmp) + deletePhrase(tmp, doc) + // return doc +} + +/** + * Turn this phrase object into 3 phrase objects + */ +exports.splitOn = function(p) { + let terms = this.terms() + let result = { + before: null, + match: null, + after: null, + } + let index = terms.findIndex(t => t.id === p.start) + if (index === -1) { + return result + } + //make all three sections into phrase-objects + let start = terms.slice(0, index) + if (start.length > 0) { + result.before = this.buildFrom(start[0].id, start.length) + } + let match = terms.slice(index, index + p.length) + if (match.length > 0) { + result.match = this.buildFrom(match[0].id, match.length) + } + let end = terms.slice(index + p.length, terms.length) + if (end.length > 0) { + result.after = this.buildFrom(end[0].id, end.length, this.pool) + } + return result +} diff --git a/src/Phrase/methods/05-json.js b/src/Phrase/methods/05-json.js new file mode 100644 index 000000000..bebb1c62b --- /dev/null +++ b/src/Phrase/methods/05-json.js @@ -0,0 +1,39 @@ +/** return json metadata for this phrase */ +exports.json = function(options = {}, world) { + let res = {} + // text data + if (options.text) { + res.text = this.text() + } + if (options.normal) { + res.normal = this.text('normal') + } + if (options.clean) { + res.clean = this.text('clean') + } + if (options.reduced) { + res.reduced = this.text('reduced') + } + if (options.root) { + res.root = this.text('root') + } + if (options.trim) { + if (res.text) { + res.text = res.text.trim() + } + if (res.normal) { + res.normal = res.normal.trim() + } + if (res.reduced) { + res.reduced = res.reduced.trim() + } + } + // terms data + if (options.terms) { + if (options.terms === true) { + options.terms = {} + } + res.terms = this.terms().map(t => t.json(options.terms, world)) + } + return res +} diff --git a/src/Phrase/methods/06-lookahead.js b/src/Phrase/methods/06-lookahead.js new file mode 100644 index 000000000..6efbb6a0d --- /dev/null +++ b/src/Phrase/methods/06-lookahead.js @@ -0,0 +1,58 @@ +/** match any terms after this phrase */ +exports.lookAhead = function(regs) { + // if empty match string, return everything after + if (!regs) { + regs = '.*' + } + let pool = this.pool + // get a list of all terms preceding our start + let terms = [] + const getAfter = function(id) { + let term = pool.get(id) + if (!term) { + return + } + terms.push(term) + if (term.prev) { + getAfter(term.next) //recursion + } + } + let all = this.terms() + let lastTerm = all[all.length - 1] + getAfter(lastTerm.next) + if (terms.length === 0) { + return [] + } + // got the terms, make a phrase from them + let p = this.buildFrom(terms[0].id, terms.length) + return p.match(regs) +} + +/** match any terms before this phrase */ +exports.lookBehind = function(regs) { + // if empty match string, return everything before + if (!regs) { + regs = '.*' + } + let pool = this.pool + // get a list of all terms preceding our start + let terms = [] + const getBefore = function(id) { + let term = pool.get(id) + if (!term) { + return + } + terms.push(term) + if (term.prev) { + getBefore(term.prev) //recursion + } + } + let term = pool.get(this.start) + getBefore(term.prev) + if (terms.length === 0) { + return [] + } + // got the terms, make a phrase from them + let p = this.buildFrom(terms[terms.length - 1].id, terms.length) + return p.match(regs) +} diff --git a/src/Phrase/methods/index.js b/src/Phrase/methods/index.js new file mode 100644 index 000000000..49b0f5d43 --- /dev/null +++ b/src/Phrase/methods/index.js @@ -0,0 +1,9 @@ +module.exports = Object.assign( + {}, + require('./01-utils'), + require('./02-text'), + require('./03-change'), + require('./04-insert'), + require('./05-json'), + require('./06-lookahead') +) diff --git a/src/Subset/Abbreviations.js b/src/Subset/Abbreviations.js new file mode 100644 index 000000000..ca29863ec --- /dev/null +++ b/src/Subset/Abbreviations.js @@ -0,0 +1,33 @@ +const addMethod = function(Doc) { + /** */ + class Abbreviations extends Doc { + stripPeriods() { + this.termList().forEach(t => { + if (t.tags.Abbreviation === true && t.next) { + t.post = t.post.replace(/^\./, '') + } + let str = t.text.replace(/\./, '') + t.set(str) + }) + return this + } + addPeriods() { + this.termList().forEach(t => { + t.post = t.post.replace(/^\./, '') + t.post = '.' + t.post + }) + return this + } + } + Abbreviations.prototype.unwrap = Abbreviations.prototype.stripPeriods + + Doc.prototype.abbreviations = function(n) { + let match = this.match('#Abbreviation') + if (typeof n === 'number') { + match = match.get(n) + } + return new Abbreviations(match.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/Clauses.js b/src/Subset/Clauses.js new file mode 100644 index 000000000..e1afc2d55 --- /dev/null +++ b/src/Subset/Clauses.js @@ -0,0 +1,51 @@ +const addMethod = function(Doc) { + /** split into approximate sub-sentence phrases */ + Doc.prototype.clauses = function(n) { + // an awkward way to disambiguate a comma use + let commas = this.if('@hasComma') + .notIf('@hasComma @hasComma') //fun, cool... + .notIf('@hasComma . .? (and|or) .') //cool, and fun + .notIf('(#City && @hasComma) #Country') //'toronto, canada' + .notIf('(#Date && @hasComma) #Year') //'july 6, 1992' + .notIf('@hasComma (too|also)$') //at end of sentence + .match('@hasComma') + let found = this.splitAfter(commas) + + let quotes = found.quotations() + found = found.splitOn(quotes) + + let parentheses = found.parentheses() + found = found.splitOn(parentheses) + + // it is cool and it is .. + let conjunctions = found.if('#Copula #Adjective #Conjunction (#Pronoun|#Determiner) #Verb').match('#Conjunction') + found = found.splitBefore(conjunctions) + + // if it is this then that + let condition = found.if('if .{2,9} then .').match('then') + found = found.splitBefore(condition) + + // misc clause partitions + found = found.splitBefore('as well as .') + found = found.splitBefore('such as .') + found = found.splitBefore('in addition to .') + + // semicolons, dashes + found = found.splitAfter('@hasSemicolon') + found = found.splitAfter('@hasDash') + + // does there appear to have relative/subordinate clause still? + let tooLong = found.filter(d => d.wordCount() > 5 && d.match('#Verb+').length >= 2) + if (tooLong.found) { + let m = tooLong.splitAfter('#Noun .* #Verb .* #Noun+') + found = found.splitOn(m.eq(0)) + } + + if (typeof n === 'number') { + found = found.get(n) + } + return new Doc(found.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/People.js b/src/Subset/People.js new file mode 100644 index 000000000..c14e4c9bf --- /dev/null +++ b/src/Subset/People.js @@ -0,0 +1,24 @@ +const addMethod = function(Doc) { + /** */ + class People extends Doc { + // honorifics(){} + // firstNames(){} + // lastNames(){} + // pronouns(){} + // toPronoun(){} + // fromPronoun(){} + } + + Doc.prototype.people = function(n) { + let match = this.splitAfter('@hasComma') + match = match.match('#Person+') + + //grab (n)th result + if (typeof n === 'number') { + match = match.get(n) + } + return new People(match.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/Quotations.js b/src/Subset/Quotations.js new file mode 100644 index 000000000..ab4b4fd3f --- /dev/null +++ b/src/Subset/Quotations.js @@ -0,0 +1,76 @@ +const pairs = { + '\u0022': '\u0022', // 'StraightDoubleQuotes' + '\uFF02': '\uFF02', // 'StraightDoubleQuotesWide' + '\u0027': '\u0027', // 'StraightSingleQuotes' + '\u201C': '\u201D', // 'CommaDoubleQuotes' + '\u2018': '\u2019', // 'CommaSingleQuotes' + '\u201F': '\u201D', // 'CurlyDoubleQuotesReversed' + '\u201B': '\u2019', // 'CurlySingleQuotesReversed' + '\u201E': '\u201D', // 'LowCurlyDoubleQuotes' + '\u2E42': '\u201D', // 'LowCurlyDoubleQuotesReversed' + '\u201A': '\u2019', // 'LowCurlySingleQuotes' + '\u00AB': '\u00BB', // 'AngleDoubleQuotes' + '\u2039': '\u203A', // 'AngleSingleQuotes' + // Prime 'non quotation' + '\u2035': '\u2032', // 'PrimeSingleQuotes' + '\u2036': '\u2033', // 'PrimeDoubleQuotes' + '\u2037': '\u2034', // 'PrimeTripleQuotes' + // Prime 'quotation' variation + '\u301D': '\u301E', // 'PrimeDoubleQuotes' + '\u0060': '\u00B4', // 'PrimeSingleQuotes' + '\u301F': '\u301E', // 'LowPrimeDoubleQuotesReversed' +} + +const hasOpen = RegExp('(' + Object.keys(pairs).join('|') + ')') + +const addMethod = function(Doc) { + /** "these things" */ + class Quotations extends Doc { + /** remove the quote characters */ + unwrap() { + return this + } + } + + Doc.prototype.quotations = function(n) { + let list = [] + this.list.forEach(p => { + let terms = p.terms() + //look for opening quotes + for (let i = 0; i < terms.length; i += 1) { + const t = terms[i] + if (hasOpen.test(t.pre)) { + let char = (t.pre.match(hasOpen) || [])[0] + let want = pairs[char] + // if (!want) { + // console.warn('missing quote char ' + char) + // } + //look for the closing bracket.. + for (let o = i; o < terms.length; o += 1) { + if (terms[o].post.indexOf(want) !== -1) { + let len = o - i + 1 + list.push(p.buildFrom(t.id, len)) + i = o + break + } + } + } + } + }) + //support nth result + if (typeof n === 'number') { + if (list[n]) { + list = [list[n]] + } else { + list = [] + } + return new Quotations(list, this, this.world) + } + return new Quotations(list, this, this.world) + } + // alias + Doc.prototype.quotes = Doc.prototype.quotations + + return Doc +} +module.exports = addMethod diff --git a/src/Subset/_simple.js b/src/Subset/_simple.js new file mode 100644 index 000000000..876e95955 --- /dev/null +++ b/src/Subset/_simple.js @@ -0,0 +1,104 @@ +let methods = {} + +// allow helper methods like .adjectives() and .adverbs() +const arr = [ + ['terms', '.'], + ['hyphenated', '@hasHyphen .'], + ['adjectives', '#Adjective'], + ['hashTags', '#HashTag'], + ['emails', '#Email'], + ['emoji', '#Emoji'], + ['emoticons', '#Emoticon'], + ['atMentions', '#AtMention'], + ['urls', '#Url'], + ['adverbs', '#Adverb'], + ['pronouns', '#Pronoun'], + ['conjunctions', '#Conjunction'], + ['prepositions', '#Preposition'], +] +arr.forEach(a => { + methods[a[0]] = function(n) { + let m = this.match(a[1]) + if (typeof n === 'number') { + m = m.get(n) + } + return m + } +}) +// aliases +methods.emojis = methods.emoji +methods.atmentions = methods.atMentions +methods.words = methods.terms + +/** return anything tagged as a phone number */ +methods.phoneNumbers = function(n) { + let m = this.splitAfter('@hasComma') + m = m.match('#PhoneNumber+') + if (typeof n === 'number') { + m = m.get(n) + } + return m +} + +/** money + currency pair */ +methods.money = function(n) { + let m = this.match('#Money #Currency?') + if (typeof n === 'number') { + m = m.get(n) + } + return m +} + +/** return all cities, countries, addresses, and regions */ +methods.places = function(n) { + // don't split 'paris, france' + let keep = this.match('(#City && @hasComma) (#Region|#Country)') + // but split the other commas + let m = this.not(keep).splitAfter('@hasComma') + // combine them back together + m = m.concat(keep) + m.sort('index') + m = m.match('#Place+') + if (typeof n === 'number') { + m = m.get(n) + } + return m +} + +/** return all schools, businesses and institutions */ +methods.organizations = function(n) { + let m = this.clauses() + m = m.match('#Organization+') + if (typeof n === 'number') { + m = m.get(n) + } + return m +} + +//combine them with .topics() method +methods.entities = function(n) { + let r = this.clauses() + // Find people, places, and organizations + let yup = r.people() + yup = yup.concat(r.places()) + yup = yup.concat(r.organizations()) + let ignore = ['someone', 'man', 'woman', 'mother', 'brother', 'sister', 'father'] + yup = yup.not(ignore) + //return them to normal ordering + yup.sort('sequence') + // yup.unique() //? not sure + if (typeof n === 'number') { + yup = yup.get(n) + } + return yup +} +//aliases +methods.things = methods.entities +methods.topics = methods.entities + +/** alias for .all() until it gets overloaded by plugin */ +methods.sentences = function() { + return this.all() +} + +module.exports = methods diff --git a/src/Subset/acronyms.js b/src/Subset/acronyms.js new file mode 100644 index 000000000..77eda980e --- /dev/null +++ b/src/Subset/acronyms.js @@ -0,0 +1,32 @@ +const addMethod = function(Doc) { + /** */ + class Acronyms extends Doc { + stripPeriods() { + this.termList().forEach(t => { + let str = t.text.replace(/\./g, '') + t.set(str) + }) + return this + } + addPeriods() { + this.termList().forEach(t => { + let str = t.text.replace(/\./g, '') + str = str.split('').join('.') + t.set(str) + }) + return this + } + } + Acronyms.prototype.unwrap = Acronyms.prototype.stripPeriods + Acronyms.prototype.strip = Acronyms.prototype.stripPeriods + + Doc.prototype.acronyms = function(n) { + let match = this.match('#Acronym') + if (typeof n === 'number') { + match = match.get(n) + } + return new Acronyms(match.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/contractions.js b/src/Subset/contractions.js new file mode 100644 index 000000000..be9a5f43c --- /dev/null +++ b/src/Subset/contractions.js @@ -0,0 +1,60 @@ +const addMethod = function(Doc) { + /** */ + class Contractions extends Doc { + constructor(list, from, world) { + super(list, from, world) + this.contracted = null + } + /** turn didn't into 'did not' */ + expand() { + this.list.forEach(p => { + let terms = p.terms() + //change the case? + let isTitlecase = terms[0].isTitleCase() + + terms.forEach((t, i) => { + //use the implicit text + // console.log(t.clean) + t.set(t.implicit || t.text) + t.implicit = undefined + + //add whitespace + if (i < terms.length - 1 && t.post === '') { + t.post += ' ' + } + }) + //set titlecase + if (isTitlecase) { + terms[0].toTitleCase() + } + }) + return this + } + } + + //find contractable, expanded-contractions + // const findExpanded = r => { + // let remain = r.not('#Contraction') + // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)') + // m.concat(remain.match('(they|we|you|i) have')) + // m.concat(remain.match('i am')) + // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')) + // return m + // } + + Doc.prototype.contractions = function(n) { + //find currently-contracted + let found = this.match('@hasContraction+') //(may want to split these up) + //todo: split consecutive contractions + if (typeof n === 'number') { + found = found.get(n) + } + return new Contractions(found.list, this, this.world) + } + + //aliases + Doc.prototype.expanded = Doc.prototype.isExpanded + Doc.prototype.contracted = Doc.prototype.isContracted + return Doc +} +module.exports = addMethod diff --git a/src/Subset/index.js b/src/Subset/index.js new file mode 100644 index 000000000..aabeaa972 --- /dev/null +++ b/src/Subset/index.js @@ -0,0 +1,23 @@ +const subsets = require('./_simple') +const subclass = [ + require('./Abbreviations'), + require('./Acronyms'), + require('./Clauses'), + require('./Contractions'), + require('./Lists'), + require('./Nouns'), + require('./Parentheses'), + require('./Possessives'), + require('./Quotations'), + require('./Verbs'), + require('./People'), +] + +const extend = function(Doc) { + // add basic methods + Object.keys(subsets).forEach(k => (Doc.prototype[k] = subsets[k])) + // add subclassed methods + subclass.forEach(addFn => addFn(Doc)) + return Doc +} +module.exports = extend diff --git a/src/Subset/lists.js b/src/Subset/lists.js new file mode 100644 index 000000000..4ba3590d4 --- /dev/null +++ b/src/Subset/lists.js @@ -0,0 +1,75 @@ +const addMethod = function(Doc) { + //pull it apart.. + const parse = function(doc) { + let things = doc.splitAfter('@hasComma').not('(and|or) not?') + let beforeLast = doc.match('[.] (and|or)') + return { + things: things, + conjunction: doc.match('(and|or) not?'), + beforeLast: beforeLast, + hasOxford: beforeLast.has('@hasComma'), + } + } + + /** cool, fun, and nice */ + class Lists extends Doc { + /** coordinating conjunction */ + conjunctions() { + return this.match('(and|or)') + } + /** split-up by list object */ + parts() { + return this.splitAfter('(@hasComma|#Conjunction)') + } + /** remove the conjunction */ + items() { + return this.parts().notIf('#Conjunction') + } + /** add a new unit to the list */ + add(str) { + this.forEach(p => { + let beforeLast = parse(p).beforeLast + beforeLast.append(str) + //add a comma to it + beforeLast.termList(0).addPunctuation(',') + }) + return this + } + /** remove any matching unit from the list */ + remove() { + return this + } + + /** return only lists that use a serial comma */ + hasOxfordComma() { + return this.filter(doc => parse(doc).hasOxford) + } + addOxfordComma() { + return this + } + removeOxfordComma() { + return this + } + } + // aliases + Lists.prototype.things = Lists.prototype.items + + Doc.prototype.lists = function(n) { + let m = this.if('@hasComma+ .? (and|or) not? .') + + // person-list + let nounList = m.match('(#Noun|#Adjective)+ #Conjunction not? #Adjective? #Noun+') + let adjList = m.match('(#Adjective|#Adverb)+ #Conjunction not? #Adverb? #Adjective+') + let verbList = m.match('(#Verb|#Adverb)+ #Conjunction not? #Adverb? #Verb+') + let result = nounList.concat(adjList) + result = result.concat(verbList) + result = result.if('@hasComma') + + if (typeof n === 'number') { + result = m.get(n) + } + return new Lists(result.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/nouns/getArticle.js b/src/Subset/nouns/getArticle.js new file mode 100644 index 000000000..cc30a76de --- /dev/null +++ b/src/Subset/nouns/getArticle.js @@ -0,0 +1,67 @@ +'use strict' + +//chooses an indefinite aricle 'a/an' for a word +const irregulars = { + hour: 'an', + heir: 'an', + heirloom: 'an', + honest: 'an', + honour: 'an', + honor: 'an', + uber: 'an', //german u +} +//pronounced letters of acronyms that get a 'an' +const an_acronyms = { + a: true, + e: true, + f: true, + h: true, + i: true, + l: true, + m: true, + n: true, + o: true, + r: true, + s: true, + x: true, +} +//'a' regexes +const a_regexs = [ + /^onc?e/i, //'wu' sound of 'o' + /^u[bcfhjkqrstn][aeiou]/i, // 'yu' sound for hard 'u' + /^eul/i, +] + +const makeArticle = function(doc) { + //no 'the john smith', but 'a london hotel' + if (doc.has('#Person') || doc.has('#Place')) { + return '' + } + //no a/an if it's plural + if (doc.has('#Plural')) { + return 'the' + } + let str = doc.text('normal').trim() + //explicit irregular forms + if (irregulars.hasOwnProperty(str)) { + return irregulars[str] + } + //spelled-out acronyms + let firstLetter = str.substr(0, 1) + if (doc.has('^@isAcronym') && an_acronyms.hasOwnProperty(firstLetter)) { + return 'an' + } + //'a' regexes + for (let i = 0; i < a_regexs.length; i++) { + if (a_regexs[i].test(str)) { + return 'a' + } + } + //basic vowel-startings + if (/^[aeiou]/i.test(str)) { + return 'an' + } + return 'a' +} + +module.exports = makeArticle diff --git a/src/Subset/nouns/index.js b/src/Subset/nouns/index.js new file mode 100644 index 000000000..cbb76184b --- /dev/null +++ b/src/Subset/nouns/index.js @@ -0,0 +1,27 @@ +const methods = require('./methods') + +const addMethod = function(Doc) { + /** */ + class Nouns extends Doc {} + // add-in our methods + Object.assign(Nouns.prototype, methods) + + Doc.prototype.nouns = function(n) { + let match = this.clauses() + match = match.match('#Noun+ (of|by)? the? #Noun+?') + //nouns that we don't want in these results, for weird reasons + match = match.not('#Pronoun') + match = match.not('(there|these)') + match = match.not('(#Month|#WeekDay)') //allow Durations, Holidays + // //allow possessives like "spencer's", but not generic ones like, + match = match.not('(my|our|your|their|her|his)') + match = match.not('(of|for|by|the)$') + + if (typeof n === 'number') { + match = match.get(n) + } + return new Nouns(match.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/nouns/methods.js b/src/Subset/nouns/methods.js new file mode 100644 index 000000000..fd9610056 --- /dev/null +++ b/src/Subset/nouns/methods.js @@ -0,0 +1,75 @@ +const hasPlural = require('./plural/hasPlural') +const getArticle = require('./getArticle') +const isPlural = require('./plural/isPlural') +const toPossessive = require('./toPossessive') +const parse = require('./parse') + +const methods = { + /** overload the original json with noun information */ + json: function(options) { + let n = null + if (typeof options === 'number') { + n = options + options = null + } + options = options || { text: true, normal: true, trim: true, terms: true } + let res = [] + this.forEach(doc => { + let json = doc.json(options)[0] + json.article = getArticle(doc) + res.push(json) + }) + if (n !== null) { + return res[n] + } + return res + }, + + isPlural: function() { + return this.if('#Plural') //assume tagger has run? + }, + hasPlural: function() { + return this.filter(d => hasPlural(d)) + }, + toPlural: function() { + let toPlural = this.world.transforms.toPlural + this.forEach(doc => { + if (doc.has('#Plural') || hasPlural(doc) === false) { + return + } + // double-check it isn't an un-tagged plural + let main = parse(doc).main + let str = main.text() + if (!main.has('#Singular') && isPlural(str) === true) { + return + } + str = toPlural(str, this.world) + main.replace(str).tag('#Plural') + }) + return this + }, + toSingular: function() { + let toSingular = this.world.transforms.toSingular + this.forEach(doc => { + if (doc.has('#Singular') || hasPlural(doc) === false) { + return + } + // double-check it isn't an un-tagged plural + let main = parse(doc).main + let str = main.text() + if (!main.has('#Plural') && isPlural(str) !== true) { + return + } + str = toSingular(str, this.world) + main.replace(str).tag('#Singular') + }) + return this + }, + toPossessive: function() { + this.forEach(d => { + toPossessive(d) + }) + return this + }, +} +module.exports = methods diff --git a/src/Subset/nouns/parse.js b/src/Subset/nouns/parse.js new file mode 100644 index 000000000..6f9ea0419 --- /dev/null +++ b/src/Subset/nouns/parse.js @@ -0,0 +1,15 @@ +// .nouns() supports some noun-phrase-ish groupings +// pull these apart, if necessary +const parse = function(doc) { + let res = { + main: doc, + } + //support 'mayor of chicago' as one noun-phrase + if (doc.has('#Noun (of|by|for) .')) { + let m = doc.splitAfter('[#Noun+]') + res.main = m.eq(0) + res.post = m.eq(1) + } + return res +} +module.exports = parse diff --git a/src/Subset/nouns/plural/hasPlural.js b/src/Subset/nouns/plural/hasPlural.js new file mode 100644 index 000000000..d5d6cdc42 --- /dev/null +++ b/src/Subset/nouns/plural/hasPlural.js @@ -0,0 +1,16 @@ +const noPlural = + '(#Pronoun|#Place|#Value|#Person|#Uncountable|#Month|#WeekDay|#Holiday|#Possessive)' + +//certain words can't be plural, like 'peace' +const hasPlural = function(doc) { + if (doc.has('#Plural') === true) { + return true + } + // these can't be plural + if (doc.has(noPlural) === true) { + return false + } + return true +} + +module.exports = hasPlural diff --git a/src/Subset/nouns/plural/isPlural/_rules.js b/src/Subset/nouns/plural/isPlural/_rules.js new file mode 100644 index 000000000..5933e1824 --- /dev/null +++ b/src/Subset/nouns/plural/isPlural/_rules.js @@ -0,0 +1,36 @@ +//similar to plural/singularize rules, but not the same +const isPlural = [ + /(antenn|formul|nebul|vertebr|vit)ae$/i, + /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, + /men$/i, + /.tia$/i, + /(m|l)ice$/i, +] + +//similar to plural/singularize rules, but not the same +const isSingular = [ + /(ax|test)is$/i, + /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, + /(octop|vir)i$/i, + /(rl)f$/i, + /(alias|status)$/i, + /(bu)s$/i, + /(al|ad|at|er|et|ed|ad)o$/i, + /(ti)um$/i, + /(ti)a$/i, + /sis$/i, + /(?:(^f)fe|(lr)f)$/i, + /hive$/i, + /(^aeiouy|qu)y$/i, + /(x|ch|ss|sh|z)$/i, + /(matr|vert|ind|cort)(ix|ex)$/i, + /(m|l)ouse$/i, + /(m|l)ice$/i, + /(antenn|formul|nebul|vertebr|vit)a$/i, + /.sis$/i, + /^(?!talis|.*hu)(.*)man$/i, +] +module.exports = { + isSingular: isSingular, + isPlural: isPlural, +} diff --git a/src/Subset/nouns/plural/isPlural/index.js b/src/Subset/nouns/plural/isPlural/index.js new file mode 100644 index 000000000..a68b56496 --- /dev/null +++ b/src/Subset/nouns/plural/isPlural/index.js @@ -0,0 +1,21 @@ +const rules = require('./_rules') +const endS = /s$/ +// double-check this term, if it is not plural, or singular. +// (this is a partial copy of ./tagger/fallbacks/plural) +// fallback plural if it ends in an 's'. +const isPlural = function(str) { + // isSingular suffix rules + if (rules.isSingular.find(reg => reg.test(str))) { + return false + } + // does it end in an s? + if (endS.test(str) === true) { + return true + } + // is it a plural like 'fungi'? + if (rules.isPlural.find(reg => reg.test(str))) { + return true + } + return null +} +module.exports = isPlural diff --git a/src/Subset/nouns/toPossessive.js b/src/Subset/nouns/toPossessive.js new file mode 100644 index 000000000..e515faf84 --- /dev/null +++ b/src/Subset/nouns/toPossessive.js @@ -0,0 +1,38 @@ +const exceptions = { + he: 'his', + she: 'hers', + they: 'theirs', + we: 'ours', + i: 'mine', + you: 'yours', + + her: 'hers', + their: 'theirs', + our: 'ours', + my: 'mine', + your: 'yours', +} + +// turn "David" to "David's" +const toPossessive = function(doc) { + let str = doc.text('text').trim() + // exceptions + if (exceptions.hasOwnProperty(str)) { + doc.replaceWith(exceptions[str], true, true) + doc.tag('Possessive', 'toPossessive') + return + } + // flanders' + if (/s$/.test(str)) { + str += "'" + doc.replaceWith(str, true, true) + doc.tag('Possessive', 'toPossessive') + return + } + //normal form: + str += "'s" + doc.replaceWith(str, true, true) + doc.tag('Possessive', 'toPossessive') + return +} +module.exports = toPossessive diff --git a/src/Subset/parentheses.js b/src/Subset/parentheses.js new file mode 100644 index 000000000..efd3249be --- /dev/null +++ b/src/Subset/parentheses.js @@ -0,0 +1,53 @@ +const open = /\(/ +const close = /\)/ + +const addMethod = function(Doc) { + /** anything between (these things) */ + class Parentheses extends Doc { + /** remove the parentheses characters */ + unwrap() { + this.list.forEach(p => { + let first = p.terms(0) + first.pre = first.pre.replace(open, '') + let last = p.lastTerm() + last.post = last.post.replace(close, '') + }) + return this + } + } + + Doc.prototype.parentheses = function(n) { + let list = [] + this.list.forEach(p => { + let terms = p.terms() + //look for opening brackets + for (let i = 0; i < terms.length; i += 1) { + const t = terms[i] + if (open.test(t.pre)) { + //look for the closing bracket.. + for (let o = i; o < terms.length; o += 1) { + if (close.test(terms[o].post)) { + let len = o - i + 1 + list.push(p.buildFrom(t.id, len)) + i = o + break + } + } + } + } + }) + //support nth result + if (typeof n === 'number') { + if (list[n]) { + list = [list[n]] + } else { + list = [] + } + return new Parentheses(list, this, this.world) + } + return new Parentheses(list, this, this.world) + } + + return Doc +} +module.exports = addMethod diff --git a/src/Subset/possessives.js b/src/Subset/possessives.js new file mode 100644 index 000000000..5eeab8866 --- /dev/null +++ b/src/Subset/possessives.js @@ -0,0 +1,42 @@ +const addMethod = function(Doc) { + /** */ + class Possessives extends Doc { + constructor(list, from, world) { + super(list, from, world) + this.contracted = null + } + /** turn didn't into 'did not' */ + strip() { + this.list.forEach(p => { + let terms = p.terms() + terms.forEach(t => { + let str = t.text.replace(/'s$/, '') + t.set(str || t.text) + }) + }) + return this + } + } + + //find contractable, expanded-contractions + // const findExpanded = r => { + // let remain = r.not('#Contraction') + // let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)') + // m.concat(remain.match('(they|we|you|i) have')) + // m.concat(remain.match('i am')) + // m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')) + // return m + // } + + Doc.prototype.possessives = function(n) { + //find currently-contracted + let found = this.match('#Noun+? #Possessive') + //todo: split consecutive contractions + if (typeof n === 'number') { + found = found.get(n) + } + return new Possessives(found.list, this, this.world) + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/verbs/conjugate/index.js b/src/Subset/verbs/conjugate/index.js new file mode 100644 index 000000000..6df689067 --- /dev/null +++ b/src/Subset/verbs/conjugate/index.js @@ -0,0 +1,55 @@ +const toInfinitive = require('../toInfinitive') +const toBe = require('./toBe') + +const conjugate = function(parsed, world) { + let verb = parsed.verb + + //special handling of 'is', 'will be', etc. + if (verb.has('#Copula') || (verb.out('normal') === 'be' && parsed.auxiliary.has('will'))) { + return toBe(parsed, world) + } + + let infinitive = toInfinitive(parsed, world) + if (!infinitive) { + return {} + } + // console.log(infinitive) + let forms = world.transforms.conjugate(infinitive, world) + forms.Infinitive = infinitive + + // add particle to phrasal verbs ('fall over') + if (parsed.particle.found) { + let particle = parsed.particle.text() + Object.keys(forms).forEach(k => (forms[k] += ' ' + particle)) + } + //put the adverb at the end? + if (parsed.adverb.found) { + let adverb = parsed.adverb.text() + if (parsed.adverbAfter === true) { + Object.keys(forms).forEach(k => (forms[k] += ' ' + adverb)) + } else { + Object.keys(forms).forEach(k => (forms[k] = adverb + ' ' + forms[k])) + } + } + + //apply negative + const isNegative = parsed.negative.found + if (isNegative) { + forms.PastTense = 'did not ' + forms.Infinitive + forms.PresentTense = 'does not ' + forms.Infinitive + forms.Gerund = 'not ' + forms.Gerund + } + //future Tense is pretty straightforward + if (!forms.FutureTense) { + if (isNegative) { + forms.FutureTense = 'will not ' + forms.Infinitive + } else { + forms.FutureTense = 'will ' + forms.Infinitive + } + } + if (isNegative) { + forms.Infinitive = 'not ' + forms.Infinitive + } + return forms +} +module.exports = conjugate diff --git a/src/Subset/verbs/conjugate/toBe.js b/src/Subset/verbs/conjugate/toBe.js new file mode 100644 index 000000000..fe425b318 --- /dev/null +++ b/src/Subset/verbs/conjugate/toBe.js @@ -0,0 +1,49 @@ +const isPlural = require('../isPlural') + +/** too many special cases for is/was/will be*/ +const toBe = parsed => { + let isI = false + let plural = isPlural(parsed) + let isNegative = parsed.negative.found + //account for 'i is' -> 'i am' irregular + // if (vb.parent && vb.parent.has('i #Adverb? #Copula')) { + // isI = true; + // } + + // 'i look', not 'i looks' + if (parsed.verb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) { + isI = true + } + + let obj = { + PastTense: 'was', + PresentTense: 'is', + FutureTense: 'will be', + Infinitive: 'is', + Gerund: 'being', + Actor: '', + PerfectTense: 'been', + Pluperfect: 'been', + } + //"i is" -> "i am" + if (isI === true) { + obj.PresentTense = 'am' + obj.Infinitive = 'am' + } + if (plural) { + obj.PastTense = 'were' + obj.PresentTense = 'are' + obj.Infinitive = 'are' + } + if (isNegative) { + obj.PastTense += ' not' + obj.PresentTense += ' not' + obj.FutureTense = 'will not be' + obj.Infinitive += ' not' + obj.PerfectTense = 'not ' + obj.PerfectTense + obj.Pluperfect = 'not ' + obj.Pluperfect + obj.Gerund = 'not ' + obj.Gerund + } + return obj +} +module.exports = toBe diff --git a/src/Subset/verbs/index.js b/src/Subset/verbs/index.js new file mode 100644 index 000000000..5fb2c688f --- /dev/null +++ b/src/Subset/verbs/index.js @@ -0,0 +1,40 @@ +const methods = require('./methods') + +const addMethod = function(Doc) { + /** */ + class Verbs extends Doc {} + // add-in our methods + Object.assign(Verbs.prototype, methods) + + // aliases + Verbs.prototype.negate = Verbs.prototype.toNegative + + Doc.prototype.verbs = function(n) { + let match = this.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+') + // try to ignore leading and trailing adverbs + match = match.not('^#Adverb+') + match = match.not('#Adverb+$') + // handle commas: + // don't split 'really, really' + let keep = match.match('(#Adverb && @hasComma) #Adverb') + // // but split the other commas + let m = match.not(keep).splitAfter('@hasComma') + // // combine them back together + m = m.concat(keep) + m.sort('index') + + //handle slashes? + + //ensure there's actually a verb + m = m.if('#Verb') + + //grab (n)th result + if (typeof n === 'number') { + m = m.get(n) + } + let vb = new Verbs(m.list, this, this.world) + return vb + } + return Doc +} +module.exports = addMethod diff --git a/src/Subset/verbs/isPlural.js b/src/Subset/verbs/isPlural.js new file mode 100644 index 000000000..f8ccb7f79 --- /dev/null +++ b/src/Subset/verbs/isPlural.js @@ -0,0 +1,34 @@ +// spencer walks -> singular +// we walk -> plural + +// the most-recent noun-phrase, before this verb. +const findNoun = function(vb) { + let noun = vb.lookBehind('#Noun+').last() + return noun +} + +//sometimes you can tell if a verb is plural/singular, just by the verb +// i am / we were +// othertimes you need its subject 'we walk' vs 'i walk' +const isPlural = function(parsed) { + let vb = parsed.verb + if (vb.has('(are|were|does)') || parsed.auxiliary.has('(are|were|does)')) { + return true + } + if (vb.has('(is|am|do|was)') || parsed.auxiliary.has('(is|am|do|was)')) { + return false + } + //consider its prior noun + let noun = findNoun(vb) + if (noun.has('(we|they|you)')) { + return true + } + if (noun.has('#Plural')) { + return true + } + if (noun.has('#Singular')) { + return false + } + return null +} +module.exports = isPlural diff --git a/src/Subset/verbs/methods.js b/src/Subset/verbs/methods.js new file mode 100644 index 000000000..bc2dce248 --- /dev/null +++ b/src/Subset/verbs/methods.js @@ -0,0 +1,180 @@ +const toNegative = require('./toNegative') +const parseVerb = require('./parse') +const isPlural = require('./isPlural') +const conjugate = require('./conjugate') +const toInfinitive = require('./toInfinitive') + +module.exports = { + /** overload the original json with verb information */ + json: function(options) { + let n = null + if (typeof options === 'number') { + n = options + options = null + } + options = options || { text: true, normal: true, trim: true, terms: true } + let res = [] + this.forEach(p => { + let json = p.json(options)[0] + let parsed = parseVerb(p) + json.parts = {} + Object.keys(parsed).forEach(k => { + json.parts[k] = parsed[k].text('normal') + }) + json.isNegative = p.has('#Negative') + json.conjugations = conjugate(parsed, this.world) + res.push(json) + }) + if (n !== null) { + return res[n] + } + return res + }, + + /** grab the adverbs describing these verbs */ + adverbs: function() { + let list = [] + // look at internal adverbs + this.forEach(vb => { + let advb = parseVerb(vb).adverb + if (advb.found) { + list = list.concat(advb.list) + } + }) + // look for leading adverbs + let m = this.lookBehind('#Adverb$') + if (m.found) { + list = m.list.concat(list) + } + // look for trailing adverbs + m = this.lookAhead('^#Adverb') + if (m.found) { + list = list.concat(m.list) + } + return this.buildFrom(list) + }, + /**return verbs like 'we walk' and not 'spencer walks' */ + isPlural: function() { + let list = [] + this.forEach(vb => { + let parsed = parseVerb(vb) + if (isPlural(parsed, this.world) === true) { + list.push(vb.list[0]) + } + }) + return this.buildFrom(list) + }, + /** return verbs like 'spencer walks' and not 'we walk' */ + isSingular: function() { + let list = [] + this.forEach(vb => { + let parsed = parseVerb(vb) + if (isPlural(parsed, this.world) === false) { + list.push(vb.list[0]) + } + }) + return this.buildFrom(list) + }, + + /** */ + conjugate: function() { + let result = [] + this.forEach(vb => { + let parsed = parseVerb(vb) + let forms = conjugate(parsed, this.world) + result.push(forms) + }) + return result + }, + /** */ + toPastTense: function() { + this.forEach(vb => { + let parsed = parseVerb(vb) + let str = conjugate(parsed, this.world).PastTense + if (str) { + vb.replaceWith(str, false, true) + // vb.tag('PastTense') + } + }) + return this + }, + /** */ + toPresentTense: function() { + this.forEach(vb => { + let parsed = parseVerb(vb) + let obj = conjugate(parsed, this.world) + let str = obj.PresentTense + // 'i look', not 'i looks' + if (vb.lookBehind('(i|we) (#Adverb|#Verb)?$').found) { + str = obj.Infinitive + } + if (str) { + vb.replaceWith(str, false, true) + vb.tag('PresentTense') + } + }) + return this + }, + /** */ + toFutureTense: function() { + this.forEach(vb => { + let parsed = parseVerb(vb) + let str = conjugate(parsed, this.world).FutureTense + if (str) { + vb.replaceWith(str, false, true) + vb.tag('FutureTense') + } + }) + return this + }, + /** */ + toInfinitive: function() { + this.forEach(vb => { + let parsed = parseVerb(vb) + let str = toInfinitive(parsed, this.world) + if (str) { + vb.replaceWith(str, false, true) + vb.tag('Infinitive') + } + }) + return this + }, + /** */ + toGerund: function() { + this.forEach(vb => { + let parsed = parseVerb(vb) + let str = conjugate(parsed, this.world).Gerund + if (str) { + vb.replaceWith(str, false, true) + vb.tag('Gerund') + } + }) + return this + }, + + /** return only verbs with 'not'*/ + isNegative: function() { + return this.if('#Negative') + }, + /** return only verbs without 'not'*/ + isPositive: function() { + return this.ifNo('#Negative') + }, + /** add a 'not' to these verbs */ + toNegative: function() { + this.list.forEach(p => { + let doc = this.buildFrom([p]) + let parsed = parseVerb(doc) + toNegative(parsed, doc.world) + }) + return this + }, + /** remove 'not' from these verbs */ + toPositive: function() { + let m = this.match('do not #Verb') + if (m.found) { + m.remove('do not') + } + return this.remove('#Negative') + }, +} diff --git a/src/Subset/verbs/parse.js b/src/Subset/verbs/parse.js new file mode 100644 index 000000000..3b2841d98 --- /dev/null +++ b/src/Subset/verbs/parse.js @@ -0,0 +1,30 @@ +// turn 'would not really walk up' into parts +const parseVerb = function(vb) { + let parsed = { + adverb: vb.match('#Adverb+'), // 'really' + negative: vb.match('#Negative'), // 'not' + auxiliary: vb.match('#Auxiliary').not('(#Negative|#Adverb)'), // 'will' of 'will go' + particle: vb.match('#Particle'), // 'up' of 'pull up' + verb: vb.match('#Verb').not('(#Adverb|#Negative|#Auxiliary|#Particle)'), + } + // fallback, if no verb found + if (!parsed.verb.found) { + // blank-everything + Object.keys(parsed).forEach(k => { + parsed[k] = parsed[k].not('.') + }) + // it's all the verb + parsed.verb = vb + return parsed + } + // + if (parsed.adverb && parsed.adverb.found) { + let match = parsed.adverb.text('reduced') + '$' + if (vb.has(match)) { + parsed.adverbAfter = true + } + } + // console.log(parsed.adverb.json({ index: true })[0]) + return parsed +} +module.exports = parseVerb diff --git a/src/Subset/verbs/toInfinitive/index.js b/src/Subset/verbs/toInfinitive/index.js new file mode 100644 index 000000000..d9145c6db --- /dev/null +++ b/src/Subset/verbs/toInfinitive/index.js @@ -0,0 +1,26 @@ +// walked => walk - turn a verb into it's root form +const toInfinitive = function(parsed, world) { + let verb = parsed.verb + + //1. if it's already infinitive + let str = verb.text('normal') + if (verb.has('#Infinitive')) { + return str + } + + // 2. world transform does the heavy-lifting + let tense = null + if (verb.has('#PastTense')) { + tense = 'PastTense' + } else if (verb.has('#Gerund')) { + tense = 'Gerund' + } else if (verb.has('#PresentTense')) { + tense = 'PresentTense' + } else if (verb.has('#Participle')) { + tense = 'Participle' + } else if (verb.has('#Actor')) { + tense = 'Actor' + } + return world.transforms.toInfinitive(str, world, tense) +} +module.exports = toInfinitive diff --git a/src/Subset/verbs/toNegative.js b/src/Subset/verbs/toNegative.js new file mode 100644 index 000000000..c20a1e7a1 --- /dev/null +++ b/src/Subset/verbs/toNegative.js @@ -0,0 +1,62 @@ +const toInfinitive = require('./toInfinitive') +const isPlural = require('./isPlural') +// #Modal : would walk -> 'would not walk' +// #Copula : is -> 'is not' +// #PastTense : walked -> did not walk +// #PresentTense : walks -> does not walk +// #Gerund : walking: -> not walking +// #Infinitive : walk -> do not walk + +const toNegative = function(parsed, world) { + let vb = parsed.verb + // if it's already negative... + if (parsed.negative.found) { + return + } + + // would walk -> would not walk + if (parsed.auxiliary.found) { + parsed.auxiliary.eq(0).append('not') + return + } + // is walking -> is not walking + if (vb.has('(#Copula|will|has|had|do)')) { + vb.append('not') + return + } + // walked -> did not walk + if (vb.has('#PastTense')) { + let inf = toInfinitive(parsed, world) + vb.replaceWith(inf, true, true) + vb.prepend('did not') + return + } + // walks -> does not walk + if (vb.has('#PresentTense')) { + let inf = toInfinitive(parsed, world) + vb.replaceWith(inf, true, true) + if (isPlural(parsed, world)) { + vb.prepend('do not') + } else { + vb.prepend('does not') + } + return + } + //walking -> not walking + if (vb.has('#Gerund')) { + let inf = toInfinitive(parsed, world) + vb.replaceWith(inf, true, true) + vb.prepend('not') + return + } + + //fallback 1: walk -> does not walk + if (isPlural(parsed, world)) { + vb.prepend('does not') + return + } + //fallback 2: walk -> do not walk + vb.prepend('do not') + return +} +module.exports = toNegative diff --git a/src/Term/Term.js b/src/Term/Term.js new file mode 100644 index 000000000..4e7254e52 --- /dev/null +++ b/src/Term/Term.js @@ -0,0 +1,52 @@ +const makeId = require('./_id') +const parseTerm = require('./parse') +const methods = require('./methods') +const tagMethods = require('./tag') + +class Term { + constructor(text = '') { + text = String(text) + let obj = parseTerm(text) + // the various forms of our text + this.text = obj.text || '' + this.clean = obj.clean + this.reduced = obj.reduced + this.root = obj.root || null + this.implicit = obj.implicit || null + + this.pre = obj.pre || '' + this.post = obj.post || '' + this.tags = {} + this.prev = null + this.next = null + this.id = makeId(obj.clean) + this.isA = 'Term' // easier than .constructor... + // support alternative matches + if (obj.alias) { + this.alias = obj.alias + } + } + /** set the text of the Term to something else*/ + set(str) { + let obj = parseTerm(str) + this.text = obj.text + this.clean = obj.clean + return this + } +} + +/** create a deep-copy of this term */ +Term.prototype.clone = function() { + let term = new Term(this.text) + term.pre = this.pre + term.post = this.post + term.tags = Object.assign({}, this.tags) + //use the old id, so it can be matched with .match(doc) + // term.id = this.id + return term +} + +Object.assign(Term.prototype, methods) +Object.assign(Term.prototype, tagMethods) + +module.exports = Term diff --git a/src/Term/_id.js b/src/Term/_id.js new file mode 100644 index 000000000..f773706bf --- /dev/null +++ b/src/Term/_id.js @@ -0,0 +1,14 @@ +//this is a not-well-thought-out way to reduce our dependence on `object===object` stuff +const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('') + +//generates a unique id for this term +function makeId(str) { + str = str || '_' + let text = str + '-' + for (let i = 0; i < 7; i++) { + text += chars[Math.floor(Math.random() * chars.length)] + } + return text +} + +module.exports = makeId diff --git a/src/Term/methods/01-case.js b/src/Term/methods/01-case.js new file mode 100644 index 000000000..4642bb7aa --- /dev/null +++ b/src/Term/methods/01-case.js @@ -0,0 +1,32 @@ +const titleCase = /^[A-Z][a-z'\u00C0-\u00FF]/ +const upperCase = /^[A-Z]+s?$/ + +/** convert all text to uppercase */ +exports.toUpperCase = function() { + this.text = this.text.toUpperCase() + return this +} + +/** convert all text to lowercase */ +exports.toLowerCase = function() { + this.text = this.text.toLowerCase() + return this +} + +/** only set the first letter to uppercase + * leave any existing uppercase alone + */ +exports.toTitleCase = function() { + this.text = this.text.replace(/^ *[a-z\u00C0-\u00FF]/, x => x.toUpperCase()) //support unicode? + return this +} + +/** if all letters are uppercase */ +exports.isUpperCase = function() { + return upperCase.test(this.text) +} +/** if the first letter is uppercase, and the rest are lowercase */ +exports.isTitleCase = function() { + return titleCase.test(this.text) +} +exports.titleCase = exports.isTitleCase diff --git a/src/Term/methods/02-punctuation.js b/src/Term/methods/02-punctuation.js new file mode 100644 index 000000000..b89661825 --- /dev/null +++ b/src/Term/methods/02-punctuation.js @@ -0,0 +1,81 @@ +// these methods are called with '@hasComma' in the match syntax +// various unicode quotation-mark formats +const startQuote = + '(\u0022|\uFF02|\u0027|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\u00AB|\u2039|\u2035|\u2036|\u2037|\u301D|\u0060|\u301F)' +const endQuote = + '(\u0022|\uFF02|\u0027|\u201D|\u2019|\u201D|\u2019|\u201D|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4|\u301E)' + +/** search the term's 'post' punctuation */ +exports.hasPost = function(punct) { + return this.post.indexOf(punct) !== -1 +} +/** search the term's 'pre' punctuation */ +exports.hasPre = function(punct) { + return this.pre.indexOf(punct) !== -1 +} + +/** does it have a quotation symbol? */ +exports.hasQuote = function() { + return startQuote.test(this.pre) || endQuote.test(this.post) +} + +/** does it have a comma? */ +exports.hasComma = function() { + return this.hasPost(',') +} + +/** does it end in a period? */ +exports.hasPeriod = function() { + return this.hasPost('.') === true && this.hasPost('...') === false +} + +/** does it end in an exclamation */ +exports.hasExclamation = function() { + return this.hasPost('!') +} + +/** does it end with a question mark? */ +exports.hasQuestionMark = function() { + return this.hasPost('?') || this.hasPost('¿') +} + +/** is there a ... at the end? */ +exports.hasEllipses = function() { + return this.hasPost('..') || this.hasPost('…') +} + +/** is there a semicolon after this word? */ +exports.hasSemicolon = function() { + return this.hasPost(';') +} + +/** is there a slash '/' in this word? */ +exports.hasSlash = function() { + return /\//.test(this.text) +} + +/** a hyphen connects two words like-this */ +exports.hasHyphen = function() { + const hyphen = /(-|–|—)/ + return hyphen.test(this.post) || hyphen.test(this.pre) +} +/** a dash separates words - like that */ +exports.hasDash = function() { + const hyphen = / (-|–|—) / + return hyphen.test(this.post) || hyphen.test(this.pre) +} + +/** is it multiple words combinded */ +exports.hasContraction = function() { + return Boolean(this.implicit) +} + +/** try to sensibly put this punctuation mark into the term */ +exports.addPunctuation = function(punct) { + // dont add doubles + if (punct === ',' || punct === ';') { + this.post = this.post.replace(punct, '') + } + this.post = punct + this.post + return this +} diff --git a/src/Term/methods/03-misc.js b/src/Term/methods/03-misc.js new file mode 100644 index 000000000..61b9dd686 --- /dev/null +++ b/src/Term/methods/03-misc.js @@ -0,0 +1,50 @@ +const doesMatch = require('./_doesMatch') +const isAcronym = require('../normalize/isAcronym') + +// these tags aren't juicy-enough +const boring = {} + +/** check a match object against this term */ +exports.doesMatch = function(reg, index, length) { + return doesMatch(this, reg, index, length) +} + +/** does this term look like an acronym? */ +exports.isAcronym = function() { + return isAcronym(this.text) +} + +/** is this term implied by a contraction? */ +exports.isImplicit = function() { + return this.text === '' && Boolean(this.implicit) +} + +/** does the term have at least one good tag? */ +exports.isKnown = function() { + return Object.keys(this.tags).some(t => boring[t] !== true) +} + +/** cache the root property of the term */ +exports.setRoot = function(world) { + let transform = world.transforms + let str = this.implicit || this.clean + if (this.tags.Plural) { + str = transform.toSingular(str, world) + } + if (this.tags.Verb && !this.tags.Negative && !this.tags.Infinitive) { + let tense = null + if (this.tags.PastTense) { + tense = 'PastTense' + } else if (this.tags.Gerund) { + tense = 'Gerund' + } else if (this.tags.PresentTense) { + tense = 'PresentTense' + } else if (this.tags.Participle) { + tense = 'Participle' + } else if (this.tags.Actor) { + tense = 'Actor' + } + str = transform.toInfinitive(str, world, tense) + } + this.root = str +} diff --git a/src/Term/methods/04-text.js b/src/Term/methods/04-text.js new file mode 100644 index 000000000..d8adc6a20 --- /dev/null +++ b/src/Term/methods/04-text.js @@ -0,0 +1,88 @@ +const killUnicode = require('../normalize/unicode') +const hasSpace = /[\s-]/ +const isUpperCase = /^[A-Z-]+$/ + +// const titleCase = str => { +// return str.charAt(0).toUpperCase() + str.substr(1) +// } + +/** return various text formats of this term */ +exports.textOut = function(options, showPre, showPost) { + options = options || {} + let word = this.text + let before = this.pre + let after = this.post + + // -word- + if (options.reduced === true) { + word = this.reduced || '' + } + if (options.root === true) { + word = this.root || '' + } + if (options.implicit === true && this.implicit) { + word = this.implicit || '' + } + if (options.normal === true) { + word = this.clean || this.text || '' + } + if (options.root === true) { + word = this.root || this.reduced || '' + } + if (options.unicode === true) { + word = killUnicode(word) + } + // cleanup case + if (options.titlecase === true) { + if (this.tags.ProperNoun && !this.titleCase()) { + // word = titleCase(word) + } else if (this.tags.Acronym) { + word = word.toUpperCase() //uppercase acronyms + } else if (isUpperCase.test(word) && !this.tags.Acronym) { + // lowercase everything else + word = word.toLowerCase() + } + } + if (options.lowercase === true) { + word = word.toLowerCase() + } + // remove the '.'s from 'F.B.I.' (safely) + if (options.acronyms === true && this.tags.Acronym) { + word = word.replace(/\./g, '') + } + + // -before/after- + if (options.whitespace === true || options.root) { + before = '' + after = ' ' + if ((hasSpace.test(this.post) === false || options.last) && !this.implicit) { + after = '' + } + } + if (options.punctuation === true && !options.root) { + //normalized end punctuation + if (this.hasPost('.') === true) { + after = '.' + after + } else if (this.hasPost('?') === true) { + after = '?' + after + } else if (this.hasPost('!') === true) { + after = '!' + after + } else if (this.hasPost(',') === true) { + after = ',' + after + } else if (this.hasEllipses() === true) { + after = '...' + after + } + } + if (showPre !== true) { + before = '' + } + if (showPost !== true) { + // let keep = after.match(/\)/) || '' + after = '' //keep //after.replace(/[ .?!,]+/, '') + } + // remove the '.' from 'Mrs.' (safely) + if (options.abbreviations === true && this.tags.Abbreviation) { + after = after.replace(/^\./, '') + } + return before + word + after +} diff --git a/src/Term/methods/05-json.js b/src/Term/methods/05-json.js new file mode 100644 index 000000000..7ffd2f83b --- /dev/null +++ b/src/Term/methods/05-json.js @@ -0,0 +1,53 @@ +const rankTags = require('./_bestTag') + +const jsonDefault = { + text: true, + tags: true, + implicit: true, + + clean: false, + id: false, + index: false, + offset: false, + whitespace: false, + bestTag: false, +} + +/** return various metadata for this term */ +exports.json = function(options, world) { + options = options || {} + options = Object.assign({}, jsonDefault, options) + let result = {} + + // default on + if (options.text) { + result.text = this.text + } + if (options.normal) { + result.normal = this.normal + } + + if (options.tags) { + result.tags = Object.keys(this.tags) + } + + // default off + if (options.clean) { + result.clean = this.clean + } + if (options.id || options.offset) { + result.id = this.id + } + if (options.implicit && this.implicit !== null) { + result.implicit = this.implicit + } + if (options.whitespace) { + result.pre = this.pre + result.post = this.post + } + if (options.bestTag) { + result.bestTag = rankTags(this, world)[0] + } + + return result +} diff --git a/src/Term/methods/_bestTag.js b/src/Term/methods/_bestTag.js new file mode 100644 index 000000000..317412c7d --- /dev/null +++ b/src/Term/methods/_bestTag.js @@ -0,0 +1,33 @@ +const boringTags = { + Auxiliary: 1, + Possessive: 1, +} + +/** a subjective ranking of tags kinda tfidf-based */ +const rankTags = function(term, world) { + let tags = Object.keys(term.tags) + const tagSet = world.tags + tags = tags.sort((a, b) => { + //bury the tags we dont want + if (boringTags[b] || !tagSet[b]) { + return -1 + } + // unknown tags are interesting + if (!tagSet[b]) { + return 1 + } + if (!tagSet[a]) { + return 0 + } + // then sort by #of parent tags (most-specific tags first) + if (tagSet[a].lineage.length > tagSet[b].lineage.length) { + return 1 + } + if (tagSet[a].isA.length > tagSet[b].isA.length) { + return -1 + } + return 0 + }) + return tags +} +module.exports = rankTags diff --git a/src/Term/methods/_doesMatch.js b/src/Term/methods/_doesMatch.js new file mode 100644 index 000000000..bdb6796cb --- /dev/null +++ b/src/Term/methods/_doesMatch.js @@ -0,0 +1,76 @@ +//declare it up here +let wrapMatch = function() {} + +/** ignore optional/greedy logic, straight-up term match*/ +const doesMatch = function(t, reg, index, length) { + // support id matches + if (reg.id === t.id) { + return true + } + // support '.' + if (reg.anything === true) { + return true + } + // support '^' (in parentheses) + if (reg.start === true && index !== 0) { + return false + } + // support '$' (in parentheses) + if (reg.end === true && index !== length - 1) { + return false + } + //support a text match + if (reg.word !== undefined) { + //match contractions + if (t.implicit !== null && t.implicit === reg.word) { + return true + } + // term aliases for slashes and things + if (t.alias !== undefined && t.alias.hasOwnProperty(reg.word)) { + return true + } + // support ~ match + if (reg.soft === true && reg.word === t.root) { + return true + } + //match either .clean or .text + return reg.word === t.clean || reg.word === t.text || reg.word === t.reduced + } + //support #Tag + if (reg.tag !== undefined) { + return t.tags[reg.tag] === true + } + //support @method + if (reg.method !== undefined) { + if (typeof t[reg.method] === 'function' && t[reg.method]() === true) { + return true + } + return false + } + //support /reg/ + if (reg.regex !== undefined) { + return reg.regex.test(t.clean) + } + //support (one|two) + if (reg.choices !== undefined) { + // try to support && operator + if (reg.operator === 'and') { + // must match them all + return reg.choices.every(r => wrapMatch(t, r, index, length)) + } + // or must match one + return reg.choices.some(r => wrapMatch(t, r, index, length)) + } + return false +} + +// wrap result for !negative match logic +wrapMatch = function(t, reg, index, length) { + let result = doesMatch(t, reg, index, length) + if (reg.negative === true) { + return !result + } + return result +} + +module.exports = wrapMatch diff --git a/src/Term/methods/index.js b/src/Term/methods/index.js new file mode 100644 index 000000000..2c56f932a --- /dev/null +++ b/src/Term/methods/index.js @@ -0,0 +1,8 @@ +module.exports = Object.assign( + {}, + require('./01-case'), + require('./02-punctuation'), + require('./03-misc'), + require('./04-text'), + require('./05-json') +) diff --git a/src/Term/normalize/clean.js b/src/Term/normalize/clean.js new file mode 100644 index 000000000..636cbc1bf --- /dev/null +++ b/src/Term/normalize/clean.js @@ -0,0 +1,62 @@ +const killUnicode = require('./unicode') +const isAcronym = require('./isAcronym') +const hasSlash = /[a-z\u00C0-\u00FF] ?\/ ?[a-z\u00C0-\u00FF]/ + +/** some basic operations on a string to reduce noise */ +const clean = function(str) { + str = str || '' + str = str.toLowerCase() + str = str.trim() + let original = str + //(very) rough ASCII transliteration - bjŏrk -> bjork + str = killUnicode(str) + //rough handling of slashes - 'see/saw' + if (hasSlash.test(str) === true) { + str = str.replace(/\/.*/, '') + } + //#tags, @mentions + str = str.replace(/^[#@]/, '') + //punctuation + str = str.replace(/[,;.!?]+$/, '') + // coerce single curly quotes + str = str.replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g, "'") + // coerce double curly quotes + str = str.replace( + /[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g, + '"' + ) + //coerce Unicode ellipses + str = str.replace(/\u2026/g, '...') + //en-dash + str = str.replace(/\u2013/g, '-') + //lookin'->looking (make it easier for conjugation) + if (/[a-z][^aeiou]in['’]$/.test(str) === true) { + str = str.replace(/in['’]$/, 'ing') + } + //turn re-enactment to reenactment + if (/^(re|un)-?[^aeiou]./.test(str) === true) { + str = str.replace('-', '') + } + //strip leading & trailing grammatical punctuation + if (/^[:;]/.test(str) === false) { + str = str.replace(/\.{3,}$/g, '') + str = str.replace(/[",\.!:;\?\)]+$/g, '') + str = str.replace(/^['"\(]+/g, '') + } + //do this again.. + str = str.trim() + //oh shucks, + if (str === '') { + str = original + } + //compact acronyms + if (isAcronym(str)) { + str = str.replace(/\./g, '') + } + //nice-numbers + str = str.replace(/([0-9]),([0-9])/g, '$1$2') + return str +} + +module.exports = clean +// console.log(normalize('Dr. V Cooper')); diff --git a/src/Term/normalize/isAcronym.js b/src/Term/normalize/isAcronym.js new file mode 100644 index 000000000..f3d628540 --- /dev/null +++ b/src/Term/normalize/isAcronym.js @@ -0,0 +1,25 @@ +const periodAcronym = /([A-Z]\.)+[A-Z]?,?$/ +const oneLetterAcronym = /^[A-Z]\.,?$/ +const noPeriodAcronym = /[A-Z]{2,}('s|,)?$/ +const lowerCaseAcronym = /([a-z]\.){2,}[a-z]\.?$/ + +const isAcronym = function(str) { + //like N.D.A + if (periodAcronym.test(str) === true) { + return true + } + //like c.e.o + if (lowerCaseAcronym.test(str) === true) { + return true + } + //like 'F.' + if (oneLetterAcronym.test(str) === true) { + return true + } + //like NDA + if (noPeriodAcronym.test(str) === true) { + return true + } + return false +} +module.exports = isAcronym diff --git a/src/Term/normalize/reduce.js b/src/Term/normalize/reduce.js new file mode 100644 index 000000000..67528a301 --- /dev/null +++ b/src/Term/normalize/reduce.js @@ -0,0 +1,8 @@ +/** reduced is one step further than clean */ +const reduced = function(str) { + // remove apostrophes + str = str.replace(/['’]s$/, '') + str = str.replace(/s['’]$/, 's') + return str +} +module.exports = reduced diff --git a/src/Term/normalize/unicode.js b/src/Term/normalize/unicode.js new file mode 100644 index 000000000..7019fcb2f --- /dev/null +++ b/src/Term/normalize/unicode.js @@ -0,0 +1,57 @@ +//a hugely-ignorant, and widely subjective transliteration of latin, cryllic, greek unicode characters to english ascii. +//approximate visual (not semantic or phonetic) relationship between unicode and ascii characters +//http://en.wikipedia.org/wiki/List_of_Unicode_characters +//https://docs.google.com/spreadsheet/ccc?key=0Ah46z755j7cVdFRDM1A2YVpwa1ZYWlpJM2pQZ003M0E +let compact = { + '!': '¡', + '?': '¿Ɂ', + '"': '“”"❝❞', + "'": '‘‛❛❜', + '-': '—–', + a: 'ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАадѦѧӐӑӒӓƛɅæ', + b: 'ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬвъьѢѣҌҍ', + c: '¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾСсєҀҁҪҫ', + d: 'ÐĎďĐđƉƊȡƋƌǷ', + e: 'ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ', + f: 'ƑƒϜϝӺӻҒғſ', + g: 'ĜĝĞğĠġĢģƓǤǥǦǧǴǵ', + h: 'ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ', + I: 'ÌÍÎÏ', + i: 'ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії', + j: 'ĴĵǰȷɈɉϳЈј', + k: 'ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ', + l: 'ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ', + m: 'ΜϺϻМмӍӎ', + n: 'ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ', + o: 'ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ', + p: 'ƤƿΡρϷϸϼРрҎҏÞ', + q: 'Ɋɋ', + r: 'ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ', + s: 'ŚśŜŝŞşŠšƧƨȘșȿЅѕ', + t: 'ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮТт', + u: 'µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύ', + v: 'νѴѵѶѷ', + w: 'ŴŵƜωώϖϢϣШЩшщѡѿ', + x: '×ΧχϗϰХхҲҳӼӽӾӿ', + y: 'ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ', + z: 'ŹźŻżŽžƩƵƶȤȥɀΖζ', +} +//decompress data into two hashes +let unicode = {} +Object.keys(compact).forEach(function(k) { + compact[k].split('').forEach(function(s) { + unicode[s] = k + }) +}) + +const killUnicode = str => { + let chars = str.split('') + chars.forEach((s, i) => { + if (unicode[s]) { + chars[i] = unicode[s] + } + }) + return chars.join('') +} +module.exports = killUnicode +// console.log(killUnicode('bjŏȒk—Ɏó')); diff --git a/src/Term/parse.js b/src/Term/parse.js new file mode 100644 index 000000000..2213ad7b8 --- /dev/null +++ b/src/Term/parse.js @@ -0,0 +1,70 @@ +const normalize = require('./normalize/clean') +const reduce = require('./normalize/reduce') +// basically, tokenize for terms. + +//all punctuation marks, from https://en.wikipedia.org/wiki/Punctuation +//we have slightly different rules for start/end - like #hashtags. +const startings = /^[ \n\t\.’'\[\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\-?‘’;\/⁄·\&*\•^†‡°¡¿※№÷׺ª%‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\u0022|\uFF02|\u0027|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\u00AB|\u2039|\u2035|\u2036|\u2037|\u301D|\u0060|\u301F]+/ +const endings = /[ \n\t\.’'\[\](){}⟨⟩:,،、‒–—―…!.‹›«»‐\-?‘’;\/⁄·\&*@\•^†‡°¡¿※#№÷׺ª‰+−=‱¶′″‴§~|‖¦©℗®℠™¤₳฿\u0022|\uFF02|\u0027|\u201D|\u2019|\u201D|\u2019|\u201D|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4|\u301E]+$/ + +//money = ₵¢₡₢$₫₯֏₠€ƒ₣₲₴₭₺₾ℳ₥₦₧₱₰£៛₽₹₨₪৳₸₮₩¥ +const hasSlash = /\// +const hasApostrophe = /['’]/ +const minusNumber = /^[-+\.][0-9]/ + +/** turn given text into a parsed-up object + * seperate the 'meat' of the word from the whitespace+punctuation + */ +const parseTerm = str => { + let original = str + let pre = '' + let post = '' + str = str.replace(startings, found => { + pre = found + // support '-40' + if ((pre === '-' || pre === '+' || pre === '.') && minusNumber.test(str)) { + pre = '' + return found + } + return '' + }) + str = str.replace(endings, found => { + post = found + // keep s-apostrophe - "flanders'" or "chillin'" + if (hasApostrophe.test(found) && /[sn]['’]$/.test(original) && hasApostrophe.test(pre) === false) { + post = post.replace(hasApostrophe, '') + return `'` + } + return '' + }) + //we went too far.. + if (str === '') { + // do a very mild parse, and hope for the best. + original = original.replace(/ *$/, after => { + post = after || '' + return '' + }) + str = original + pre = '' + post = post + } + + // create the various forms of our text, + let clean = normalize(str) + const parsed = { + text: str, + clean: clean, + reduced: reduce(clean), + pre: pre, + post: post, + } + // support aliases for slashes + if (hasSlash.test(str)) { + str.split(hasSlash).forEach(word => { + parsed.alias = parsed.alias || {} + parsed.alias[word.trim()] = true + }) + } + return parsed +} +module.exports = parseTerm diff --git a/src/Term/tag/add.js b/src/Term/tag/add.js new file mode 100644 index 000000000..7dfa97ec9 --- /dev/null +++ b/src/Term/tag/add.js @@ -0,0 +1,48 @@ +const fns = require('./fns') + +/** add a tag, and its descendents, to a term */ +const addTag = function(t, tag, reason, world) { + let tagset = world.tags + //support '.' or '-' notation for skipping the tag + if (tag === '' || tag === '.' || tag === '-') { + return + } + if (tag[0] === '#') { + tag = tag.replace(/^#/, '') + } + tag = fns.titleCase(tag) + //if we already got this one + if (t.tags[tag] === true) { + return + } + // log it? + const isVerbose = world.isVerbose() + if (isVerbose === true) { + fns.logTag(t, tag, reason) + } + //add tag + t.tags[tag] = true //whee! + + //check tagset for any additional things to do... + if (tagset.hasOwnProperty(tag) === true) { + //add parent Tags + tagset[tag].isA.forEach(down => { + t.tags[down] = true + if (isVerbose === true) { + fns.logTag(t, '→ ' + down) + } + }) + //remove any contrary tags + t.unTag(tagset[tag].notA, '←', world) + } +} + +/** support an array of tags */ +const addTags = function(term, tags, reason, world) { + if (fns.isArray(tags) === true) { + tags.forEach(tag => addTag(term, tag, reason, world)) + } else { + addTag(term, tags, reason, world) + } +} +module.exports = addTags diff --git a/src/Term/tag/canBe.js b/src/Term/tag/canBe.js new file mode 100644 index 000000000..7e8cb96ca --- /dev/null +++ b/src/Term/tag/canBe.js @@ -0,0 +1,27 @@ +'use strict' + +//recursively-check compatibility of this tag and term +const canBe = function(term, tag, world) { + const tagset = world.tags + // cleanup tag + if (tag[0] === '#') { + tag = tag.replace(/^#/, '') + } + //fail-fast + if (tagset[tag] === undefined) { + return true + } + //loop through tag's contradictory tags + let enemies = tagset[tag].notA || [] + for (let i = 0; i < enemies.length; i++) { + if (term.tags[enemies[i]] === true) { + return false + } + } + if (tagset[tag].isA !== undefined) { + return canBe(term, tagset[tag].isA, world) //recursive + } + return true +} + +module.exports = canBe diff --git a/src/Term/tag/fns.js b/src/Term/tag/fns.js new file mode 100644 index 000000000..c167c291b --- /dev/null +++ b/src/Term/tag/fns.js @@ -0,0 +1,34 @@ +/** add spaces at the end */ +const padEnd = function(str, width) { + str = str.toString() + while (str.length < width) { + str += ' ' + } + return str +} + +/** output for verbose-mode */ +exports.logTag = function(t, tag, reason) { + let log = '\x1b[33m' + padEnd(t.clean, 15) + '\x1b[0m + \x1b[32m' + tag + '\x1b[0m ' + if (reason) { + log = padEnd(log, 35) + ' ' + reason + '' + } + console.log(log) +} + +/** output for verbose mode */ +exports.logUntag = function(t, tag, reason) { + let log = '\x1b[33m' + padEnd(t.clean, 3) + ' \x1b[31m - #' + tag + '\x1b[0m ' + if (reason) { + log = padEnd(log, 35) + ' ' + reason + } + console.log(log) +} + +exports.isArray = function(arr) { + return Object.prototype.toString.call(arr) === '[object Array]' +} + +exports.titleCase = str => { + return str.charAt(0).toUpperCase() + str.substr(1) +} diff --git a/src/Term/tag/index.js b/src/Term/tag/index.js new file mode 100644 index 000000000..a24a6ec81 --- /dev/null +++ b/src/Term/tag/index.js @@ -0,0 +1,37 @@ +const add = require('./add') +const unTag = require('./unTag') +const canBe = require('./canBe') + +/** add a tag or tags, and their descendents to this term + * @param {string | string[]} tags - a tag or tags + * @param {string?} [reason] a clue for debugging + */ +exports.tag = function(tags, reason, world) { + add(this, tags, reason, world) + return this +} + +/** only tag this term if it's consistent with it's current tags */ +exports.tagSafe = function(tags, reason, world) { + if (canBe(this, tags, world)) { + add(this, tags, reason, world) + } + return this +} + +/** remove a tag or tags, and their descendents from this term + * @param {string | string[]} tags - a tag or tags + * @param {string?} [reason] a clue for debugging + */ +exports.unTag = function(tags, reason, world) { + unTag(this, tags, reason, world) + return this +} + +/** is this tag consistent with the word's current tags? + * @param {string | string[]} tags - a tag or tags + * @returns {boolean} + */ +exports.canBe = function(tags, world) { + return canBe(this, tags, world) +} diff --git a/src/Term/tag/unTag.js b/src/Term/tag/unTag.js new file mode 100644 index 000000000..835192cab --- /dev/null +++ b/src/Term/tag/unTag.js @@ -0,0 +1,44 @@ +const fns = require('./fns') + +/** remove this tag, and its descentents from the term */ +const unTag = function(t, tag, reason, world) { + const isVerbose = world.isVerbose() + //support '*' for removing all tags + if (tag === '*') { + t.tags = {} + return t + } + // remove the tag + if (t.tags[tag] === true && t.tags.hasOwnProperty(tag) === true) { + delete t.tags[tag] + //log in verbose-mode + if (isVerbose === true) { + fns.logUntag(t, tag, reason) + } + } + //delete downstream tags too + const tagset = world.tags + if (tagset[tag]) { + let lineage = tagset[tag].lineage + for (let i = 0; i < lineage.length; i++) { + // unTag(t, also[i], ' - - - ', world) //recursive + if (t.tags[lineage[i]] === true) { + delete t.tags[lineage[i]] + if (isVerbose === true) { + fns.logUntag(t, ' - ' + lineage[i]) + } + } + } + } + return t +} + +//handle an array of tags +const untagAll = function(term, tags, reason, world) { + if (fns.isArray(tags) === true) { + tags.forEach(tag => unTag(term, tag, reason, world)) + } else { + unTag(term, tags, reason, world) + } +} +module.exports = untagAll diff --git a/src/_version.js b/src/_version.js new file mode 100644 index 000000000..ef80e758f --- /dev/null +++ b/src/_version.js @@ -0,0 +1 @@ +module.exports = '12.0.0' \ No newline at end of file diff --git a/src/fns.js b/src/fns.js deleted file mode 100644 index 5c52e46ae..000000000 --- a/src/fns.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; -const tagset = require('./tags'); - -// https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color -const c = { - reset: '\x1b[0m', - red: '\x1b[31m', - green: '\x1b[32m', - yellow: '\x1b[33m', - blue: '\x1b[34m', - magenta: '\x1b[35m', - cyan: '\x1b[36m', - black: '\x1b[30m' -}; -//dont use colors on client-side -if (typeof module === 'undefined') { - Object.keys(c).forEach(k => { - c[k] = ''; - }); -} - -//coerce any input into a string -exports.ensureString = input => { - if (typeof input === 'string') { - return input; - } else if (typeof input === 'number') { - return String(input); - } - return ''; -}; -//coerce any input into a string -exports.ensureObject = input => { - if (typeof input !== 'object') { - return {}; - } - if (input === null || input instanceof Array) { - return {}; - } - return input; -}; - -exports.titleCase = str => { - return str.charAt(0).toUpperCase() + str.substr(1); -}; - -//shallow-clone an object -exports.copy = o => { - let o2 = {}; - o = exports.ensureObject(o); - Object.keys(o).forEach(k => { - o2[k] = o[k]; - }); - return o2; -}; -exports.extend = (obj, a) => { - obj = exports.copy(obj); - const keys = Object.keys(a); - for (let i = 0; i < keys.length; i++) { - obj[keys[i]] = a[keys[i]]; - } - return obj; -}; - -//colorization -exports.green = function(str) { - return c.green + str + c.reset; -}; -exports.red = function(str) { - return c.red + str + c.reset; -}; -exports.blue = function(str) { - return c.blue + str + c.reset; -}; -exports.magenta = function(str) { - return c.magenta + str + c.reset; -}; -exports.cyan = function(str) { - return c.cyan + str + c.reset; -}; -exports.yellow = function(str) { - return c.yellow + str + c.reset; -}; -exports.black = function(str) { - return c.black + str + c.reset; -}; -exports.printTag = function(tag) { - if (tagset[tag]) { - const color = tagset[tag].color || 'blue'; - return exports[color](tag); - } - return tag; -}; -exports.printTerm = function(t) { - const tags = Object.keys(t.tags); - for (let i = 0; i < tags.length; i++) { - if (tagset[tags[i]]) { - const color = tagset[tags[i]].color || 'black'; - return exports[color](t.out('text')); - } - } - return c.reset + t.plaintext + c.reset; -}; - -exports.leftPad = function(str, width, char) { - char = char || ' '; - str = str.toString(); - while (str.length < width) { - str += char; - } - return str; -}; - -exports.isArray = function(arr) { - return Object.prototype.toString.call(arr) === '[object Array]'; -}; - -exports.isObject = function(obj) { - return obj === Object(obj); -}; diff --git a/src/index.js b/src/index.js index 757c23f3e..0c3e206e1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,112 +1,59 @@ -'use strict'; -const buildText = require('./text/build'); -const pkg = require('../package.json'); -const log = require('./log'); -const unpack = require('./world/unpack'); -let world = require('./world'); -let w = world.w; +const tokenize = require('./01-tokenizer') +const version = require('./_version') +const World = require('./World/World') +const Doc = require('./Doc/Doc') -//the main function -const nlp = function(str, lex) { - if (lex) { - w.plugin({ - words: lex - }); +//blast-out our word-lists, just once +let world = new World() + +/** parse and tag text into a compromise object */ +const nlp = function(text = '', lexicon) { + if (lexicon) { + world.addWords(lexicon) } - let doc = buildText(str, w); - doc.tagger(); - return doc; -}; + let list = tokenize.fromText(text, world) + let doc = new Doc(list, null, world) + doc.tagger() + return doc +} -//this is used, atleast, for testing the packing -nlp.unpack = function(plugin) { - return unpack(plugin); -}; -//this is handy -nlp.version = pkg.version; -//turn-on some debugging -nlp.verbose = function(str) { - log.enable(str); -}; -//same as main method, except with no POS-tagging. -nlp.tokenize = function(str) { - return buildText(str); -}; +/** parse text into a compromise object, without running POS-tagging */ +nlp.tokenize = function(text = '', lexicon) { + if (lexicon) { + world.addWords(lexicon) + } + let list = tokenize.fromText(text, world) + let doc = new Doc(list, null, world) + return doc +} -//uncompress user-submitted lexicon -nlp.plugin = function(plugin) { - w.plugin(plugin); -}; -//contribute words to the lexicon -nlp.addWords = function(lex) { - w.plugin({ - words: lex - }); -}; -nlp.addTags = function(tags) { - w.plugin({ - tags: tags - }); -}; -nlp.addRegex = function(regex) { - w.plugin({ - regex: regex - }); -}; -nlp.addPatterns = function(patterns) { - w.plugin({ - patterns: patterns - }); -}; -nlp.addPlurals = function(plurals) { - w.plugin({ - plurals: plurals - }); -}; -nlp.addConjugations = function(conj) { - w.plugin({ - conjugations: conj - }); -}; +/** mix in a compromise-plugin */ +nlp.extend = function(fn) { + fn(Doc, world) + return this +} -//make a weird, half-copy of this method +/** make a deep-copy of the library state */ nlp.clone = function() { - let w2 = world.reBuild(); - //this is weird, but it's okay - var nlp2 = function(str, lex) { - if (lex) { - w2.plugin({ - words: lex - }); - } - let doc = buildText(str, w2); - doc.tagger(); - return doc; - }; - nlp2.tokenize = nlp.tokenize; - nlp2.verbose = nlp.verbose; - nlp2.version = nlp.version; - ['Words', 'Tags', 'Regex', 'Patterns', 'Plurals', 'Conjugations'].forEach((fn) => { - nlp2['add' + fn] = function(obj) { - w2['add' + fn](obj); - }; - }); - return nlp2; -}; - -//and then all-the-exports... -if (typeof self !== 'undefined') { - self.nlp = nlp; // Web Worker -} else if (typeof window !== 'undefined') { - window.nlp = nlp; // Browser -} else if (typeof global !== 'undefined') { - global.nlp = nlp; // NodeJS + world = world.clone() + return this } -//don't forget amd! -if (typeof define === 'function' && define.amd) { - define(nlp); + +/** re-generate a Doc object from .json() results */ +nlp.load = function(json) { + let list = tokenize.fromJSON(json, world) + return new Doc(list, null, world) } -//then for some reason, do this too! -if (typeof module !== 'undefined') { - module.exports = nlp; + +/** log our decision-making for debugging */ +nlp.verbose = function(bool = true) { + world.verbose(bool) + return this } + +/** current version of the library */ +nlp.version = version +// alias +nlp.import = nlp.load + +module.exports = nlp diff --git a/src/log/client.js b/src/log/client.js deleted file mode 100644 index 6d6eafc8e..000000000 --- a/src/log/client.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; -const fns = require('../fns'); - -// const colors = { -// 'Person': '#6393b9', -// 'Pronoun': '#81acce', -// 'Noun': 'steelblue', -// 'Verb': 'palevioletred', -// 'Adverb': '#f39c73', -// 'Adjective': '#b3d3c6', -// 'Determiner': '#d3c0b3', -// 'Preposition': '#9794a8', -// 'Conjunction': '#c8c9cf', -// 'Value': 'palegoldenrod', -// 'Expression': '#b3d3c6' -// }; - -const tag = (t, pos, reason) => { - let title = t.normal || '[' + t.silent_term + ']'; - title = fns.leftPad('\'' + title + '\'', 12); - title += ' -> ' + pos; - title += fns.leftPad((reason || ''), 15); - console.log('%c' + title, ' color: #a2c99c'); -}; -const untag = (t, pos, reason) => { - let title = t.normal || '[' + t.silent_term + ']'; - title = fns.leftPad('\'' + title + '\'', 12); - title += ' ~* ' + pos; - title += ' ' + (reason || ''); - console.log('%c' + title, ' color: #b66a6a'); -}; -module.exports = { - tag: tag, - untag: untag, -}; diff --git a/src/log/index.js b/src/log/index.js deleted file mode 100644 index 7552c0b89..000000000 --- a/src/log/index.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; -const client = require('./client'); -const server = require('./server'); - -let enable = false; - -module.exports = { - enable: (str) => { - if (str === undefined) { - str = true; - } - enable = str; - }, - tag: (t, pos, reason) => { - if (enable === true || enable === 'tagger') { - if (typeof window !== 'undefined') { - client.tag(t, pos, reason); - } else { - server.tag(t, pos, reason); - } - } - }, - unTag: (t, pos, reason) => { - if (enable === true || enable === 'tagger') { - if (typeof window !== 'undefined') { - client.untag(t, pos, reason); - } else { - server.untag(t, pos, reason); - } - } - } -}; diff --git a/src/log/server.js b/src/log/server.js deleted file mode 100644 index 6046a5933..000000000 --- a/src/log/server.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -const fns = require('../fns'); - -//use weird bash escape things for some colors -const tag = (t, pos, reason) => { - let title = t.normal || '[' + t.silent_term + ']'; - title = fns.yellow(title); - title = fns.leftPad('\'' + title + '\'', 20); - title += ' -> ' + fns.printTag(pos); - title = fns.leftPad(title, 54); - console.log(' ' + title + '(' + fns.cyan(reason || '') + ')'); -}; - -const untag = function(t, pos, reason) { - let title = '-' + t.normal + '-'; - title = fns.red(title); - title = fns.leftPad(title, 20); - title += ' ~* ' + fns.red(pos); - title = fns.leftPad(title, 54); - console.log(' ' + title + '(' + fns.red(reason || '') + ')'); -}; - -module.exports = { - tag: tag, - untag: untag, -}; diff --git a/src/paths.js b/src/paths.js deleted file mode 100644 index adc7aa180..000000000 --- a/src/paths.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - fns: require('./fns'), - Terms: require('./terms'), -}; diff --git a/src/subset/acronyms/index.js b/src/subset/acronyms/index.js deleted file mode 100644 index 5e7a85b7f..000000000 --- a/src/subset/acronyms/index.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; -const Text = require('../../text'); -//the Acronym() subset class - -const methods = { - stripPeriods: function() { - this.list.forEach((ts) => { - ts.terms.forEach((t) => { - let chars = t._text.split('.'); - if (chars.length > 2) { - t.text = chars.join(''); - } - }); - }); - return this; - }, - addPeriods: function() { - this.list.forEach((ts) => { - ts.terms.forEach((t) => { - let chars = t._text.split('.'); - if (chars.length > 2) { - let str = t._text.replace(/\./g, ''); - t.text = str.split('').join('.') + '.'; - } - }); - }); - return this; - }, - data: function() { - return this.terms().list.map(ts => { - let t = ts.terms[0]; - let parsed = t.text - .toUpperCase() - .replace(/\./g, '') - .split(''); - return { - periods: parsed.join('.'), - normal: parsed.join(''), - text: t.text - }; - }); - } -}; - -const find = function(r, n) { - r = r.match('#Acronym'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/adjectives/index.js b/src/subset/adjectives/index.js deleted file mode 100644 index c0bc951a6..000000000 --- a/src/subset/adjectives/index.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const fns = require('./methods'); -//the Adjectives() subset class - -//is this an adjective we want to goof-around with? -const shouldConvert = function(str, words) { - if (!str || str.length <= 3) { - return false; - } - if (words[str] === 'Comparable') { - return true; - } - if (words[str] === 'Adjective') { - return false; - } - //has space - if (str.indexOf(' ') !== -1) { - return false; - } - return true; -}; - -const methods = { - data: function() { - return this.list.map(ts => { - const str = ts.out('normal'); - let obj = { - normal: str, - text: this.out('text'), - comparative: 'more ' + str, - superlative: 'most ' + str, - adverbForm: null, - nounForm: null - // verbForm: null - }; - if (shouldConvert(str, this.world().words) === true) { - obj.comparative = fns.toComparative(str) || obj.comparative; - obj.superlative = fns.toSuperlative(str) || obj.superlative; - obj.adverbForm = fns.toAdverb(str); - obj.nounForm = fns.toNoun(str); - // obj.verbForm = fns.toVerb(str); - } - return obj; - }); - } -}; - -const find = function(r, n) { - r = r.match('#Adjective'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/adjectives/methods/index.js b/src/subset/adjectives/methods/index.js deleted file mode 100644 index 5491ee356..000000000 --- a/src/subset/adjectives/methods/index.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; -module.exports = { - toNoun: require('./toNoun'), - toSuperlative: require('./toSuperlative'), - toComparative: require('./toComparative'), - toAdverb: require('./toAdverb'), - toVerb: require('./toVerb') -}; diff --git a/src/subset/adjectives/methods/toAdverb.js b/src/subset/adjectives/methods/toAdverb.js deleted file mode 100644 index 0fbf50b59..000000000 --- a/src/subset/adjectives/methods/toAdverb.js +++ /dev/null @@ -1,59 +0,0 @@ -//turn 'quick' into 'quickly' -'use strict'; -const not_matches = [/airs$/, /ll$/, /ee.$/, /ile$/, /y$/]; -const irregulars = require('../../../world/more-data/irregularAdjectives').toAdverb; - -const transforms = [ - { - reg: /al$/i, - repl: 'ally' - }, - { - reg: /ly$/i, - repl: 'ly' - }, - { - reg: /(.{3})y$/i, - repl: '$1ily' - }, - { - reg: /que$/i, - repl: 'quely' - }, - { - reg: /ue$/i, - repl: 'uly' - }, - { - reg: /ic$/i, - repl: 'ically' - }, - { - reg: /ble$/i, - repl: 'bly' - }, - { - reg: /l$/i, - repl: 'ly' - } -]; - -const adj_to_adv = function(str) { - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - for (let i = 0; i < not_matches.length; i++) { - if (not_matches[i].test(str) === true) { - return null; - } - } - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - return str + 'ly'; -}; -// console.log(adj_to_adv('good')); - -module.exports = adj_to_adv; diff --git a/src/subset/adjectives/methods/toComparative.js b/src/subset/adjectives/methods/toComparative.js deleted file mode 100644 index a40b4f65b..000000000 --- a/src/subset/adjectives/methods/toComparative.js +++ /dev/null @@ -1,59 +0,0 @@ -//turn 'quick' into 'quickly' -'use strict'; -const do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /old$/, /oud$/, /e[ae]p$/]; -const dont_rules = [/ary$/, /ous$/]; -const irregulars = require('../../../world/more-data/irregularAdjectives').toComparative; - -const transforms = [ - { - reg: /y$/i, - repl: 'ier' - }, - { - reg: /([aeiou])t$/i, - repl: '$1tter' - }, - { - reg: /([aeou])de$/i, - repl: '$1der' - }, - { - reg: /nge$/i, - repl: 'nger' - } -]; - -const to_comparative = function(str) { - //known-irregulars - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - //known-transforms - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - //dont-patterns - for (let i = 0; i < dont_rules.length; i++) { - if (dont_rules[i].test(str) === true) { - return null; - } - } - //do-patterns - for (let i = 0; i < do_rules.length; i++) { - if (do_rules[i].test(str) === true) { - return str + 'er'; - } - } - //easy-one - if (/e$/.test(str) === true) { - return str + 'r'; - } - return str + 'er'; -// return null; -}; - -// console.log(to_comparative('big')); - -module.exports = to_comparative; diff --git a/src/subset/adjectives/methods/toNoun.js b/src/subset/adjectives/methods/toNoun.js deleted file mode 100644 index f3d022a53..000000000 --- a/src/subset/adjectives/methods/toNoun.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; -//convert 'cute' to 'cuteness' -const irregulars = { - clean: 'cleanliness', - naivety: 'naivety', - hurt: 'hurt' -}; - -const transforms = [ - { - reg: /y$/, - repl: 'iness' - }, - { - reg: /le$/, - repl: 'ility' - }, - { - reg: /ial$/, - repl: 'y' - }, - { - reg: /al$/, - repl: 'ality' - }, - { - reg: /ting$/, - repl: 'ting' - }, - { - reg: /ring$/, - repl: 'ring' - }, - { - reg: /bing$/, - repl: 'bingness' - }, - { - reg: /sing$/, - repl: 'se' - }, - { - reg: /ing$/, - repl: 'ment' - }, - { - reg: /ess$/, - repl: 'essness' - }, - { - reg: /ous$/, - repl: 'ousness' - } -]; - -const to_noun = function(w) { - if (irregulars.hasOwnProperty(w)) { - return irregulars[w]; - } - const lastChar = w.charAt(w.length - 1); - if (lastChar === 'w' || lastChar === 's') { - return null; - } - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(w) === true) { - return w.replace(transforms[i].reg, transforms[i].repl); - } - } - return w + 'ness'; -}; - -module.exports = to_noun; -// console.log(to_noun("great")) diff --git a/src/subset/adjectives/methods/toSuperlative.js b/src/subset/adjectives/methods/toSuperlative.js deleted file mode 100644 index 991078560..000000000 --- a/src/subset/adjectives/methods/toSuperlative.js +++ /dev/null @@ -1,60 +0,0 @@ -//turn 'quick' into 'quickest' -'use strict'; -const do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /oud$/, /...p$/]; -const dont_rules = [/ary$/]; -const irregulars = require('../../../world/more-data/irregularAdjectives').toSuperlative; - -const transforms = [ - { - reg: /y$/i, - repl: 'iest' - }, - { - reg: /([aeiou])t$/i, - repl: '$1ttest' - }, - { - reg: /([aeou])de$/i, - repl: '$1dest' - }, - { - reg: /nge$/i, - repl: 'ngest' - }, - { - reg: /([aeiou])te$/i, - repl: '$1test' - } -]; - -const to_superlative = function(str) { - //irregulars - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - //known transforms - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str)) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - //dont-rules - for (let i = 0; i < dont_rules.length; i++) { - if (dont_rules[i].test(str) === true) { - return null; - } - } - //do-rules - for (let i = 0; i < do_rules.length; i++) { - if (do_rules[i].test(str) === true) { - if (str.charAt(str.length - 1) === 'e') { - return str + 'st'; - } - return str + 'est'; - } - } - return str + 'est'; -}; - -module.exports = to_superlative; -// console.log(to_superlative("great")) diff --git a/src/subset/adjectives/methods/toVerb.js b/src/subset/adjectives/methods/toVerb.js deleted file mode 100644 index 437f082d4..000000000 --- a/src/subset/adjectives/methods/toVerb.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -//turn an adjective like 'soft' into a verb like 'soften' -//(don't do words like 'green' -> 'greenen') - -const irregulars = { - red: 'redden', - sad: 'sadden', - fat: 'fatten' -}; - -const toVerb = str => { - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - if (/e$/.test(str) === true) { - return str + 'n'; - } - return str + 'en'; -}; -module.exports = toVerb; diff --git a/src/subset/adverbs/index.js b/src/subset/adverbs/index.js deleted file mode 100644 index 52ea2c354..000000000 --- a/src/subset/adverbs/index.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const toAdjective = require('./toAdjective'); - -//the () subset class - -const methods = { - data: function() { - return this.terms().list.map(ts => { - let t = ts.terms[0]; - return { - adjectiveForm: toAdjective(t.normal), - normal: t.normal, - text: t.text - }; - }); - } -}; - -const find = function(r, n) { - r = r.splitAfter('#Comma'); - r = r.match('#Adverb+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/adverbs/toAdjective.js b/src/subset/adverbs/toAdjective.js deleted file mode 100644 index d1d1731c4..000000000 --- a/src/subset/adverbs/toAdjective.js +++ /dev/null @@ -1,60 +0,0 @@ -//turns 'quickly' into 'quick' -'use strict'; -const irregulars = { - 'idly': 'idle', - 'sporadically': 'sporadic', - 'basically': 'basic', - 'grammatically': 'grammatical', - 'alphabetically': 'alphabetical', - 'economically': 'economical', - 'conically': 'conical', - 'politically': 'political', - 'vertically': 'vertical', - 'practically': 'practical', - 'theoretically': 'theoretical', - 'critically': 'critical', - 'fantastically': 'fantastic', - 'mystically': 'mystical', - 'pornographically': 'pornographic', - 'fully': 'full', - 'jolly': 'jolly', - 'wholly': 'whole' -}; - -const transforms = [{ - 'reg': /bly$/i, - 'repl': 'ble' -}, { - 'reg': /gically$/i, - 'repl': 'gical' -}, { - 'reg': /([rsdh])ically$/i, - 'repl': '$1ical' -}, { - 'reg': /ically$/i, - 'repl': 'ic' -}, { - 'reg': /uly$/i, - 'repl': 'ue' -}, { - 'reg': /ily$/i, - 'repl': 'y' -}, { - 'reg': /(.{3})ly$/i, - 'repl': '$1' -}]; - -const toAdjective = function(str) { - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - for (let i = 0; i < transforms.length; i++) { - if (transforms[i].reg.test(str) === true) { - return str.replace(transforms[i].reg, transforms[i].repl); - } - } - return str; -}; - -// console.log(toAdjective('quickly')) -module.exports = toAdjective; diff --git a/src/subset/contractions/contract.js b/src/subset/contractions/contract.js deleted file mode 100644 index 2b7710bd9..000000000 --- a/src/subset/contractions/contract.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -//the plumbing to turn two words into a contraction -const combine = (a, b) => { - b.whitespace.after = a.whitespace.after; - a.whitespace.after = ''; - b.whitespace.before = ''; - a.silent_term = a.text; - b.silent_term = b.text; - b.text = ''; - a.tag('Contraction', 'new-contraction'); - b.tag('Contraction', 'new-contraction'); -}; - -const irregulars = { - can: 'can\'t', - will: 'won\'t' -}; - -const contract = function(ts) { - if (ts.expanded === false || ts.match('#Contraction').found) { - return ts; - } - //he is -> he's - ts.match('(#Noun|#QuestionWord) is').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'s'; - ls.contracted = true; - }); - //he did -> he'd - ts.match('#PronNoun did').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); - //how do -> how'd - ts.match('#QuestionWord (did|do)').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); - //he would -> he'd - ts.match('#Noun (could|would)').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'d'; - ls.contracted = true; - }); - //they are -> they're - ts.match('(they|we|you) are').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'re'; - ls.contracted = true; - }); - //i am -> i'm - ts.match('i am').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'m'; - ls.contracted = true; - }); - //they will -> they'll - ts.match('(#Noun|#QuestionWord) will').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'ll'; - ls.contracted = true; - }); - //they have -> they've - ts.match('(they|we|you|i) have').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - ls.terms[0].text += '\'ve'; - ls.contracted = true; - }); - //is not -> isn't - ts.match('(#Copula|#Modal|do|does|have|has|can|will) not').list.forEach((ls) => { - combine(ls.terms[0], ls.terms[1]); - //can't, won't - if (irregulars.hasOwnProperty(ls.terms[0].text) === true) { - ls.terms[0].text = irregulars[ls.terms[0].text]; - } else { - ls.terms[0].text += 'n\'t'; - } - ls.contracted = true; - }); - return ts; -}; - -module.exports = contract; diff --git a/src/subset/contractions/contraction.js b/src/subset/contractions/contraction.js deleted file mode 100644 index 928a6876e..000000000 --- a/src/subset/contractions/contraction.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -const Terms = require('../../paths').Terms; -const contract = require('./contract'); -const expand = require('./expand'); - -const ContractionCl = function(arr, world, original) { - Terms.call(this, arr, world, original); -}; - -//Inherit properties -ContractionCl.prototype = Object.create(Terms.prototype); - -ContractionCl.prototype.data = function() { - let expanded = expand(this.clone()); - let contracted = contract(this.clone()); - return { - text: this.out('text'), - normal: this.out('normal'), - expanded: { - normal: expanded.out('normal'), - text: expanded.out('text') - }, - contracted: { - normal: contracted.out('normal'), - text: contracted.out('text') - }, - isContracted: Boolean(this.contracted) - }; -}; -ContractionCl.prototype.expand = function() { - return expand(this); -}; -ContractionCl.prototype.contract = function() { - return contract(this); -}; -module.exports = ContractionCl; diff --git a/src/subset/contractions/expand.js b/src/subset/contractions/expand.js deleted file mode 100644 index d0ff690ad..000000000 --- a/src/subset/contractions/expand.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; -//turn `i'd` into `i would` -const expand = function(ts) { - if (ts.contracted === false) { - return ts; - } - ts.terms.forEach((t) => { - if (t.silent_term) { - //this term also needs a space now too - if (!t.text) { - t.whitespace.before = ' '; - } - t._text = t.silent_term; - //handle (some) capitalization - if (t.tags.TitleCase) { - t.toTitleCase(); - } - t.normalize(); - t.silent_term = null; - t.unTag('Contraction', 'expanded'); - } - }); - return ts; -}; -module.exports = expand; diff --git a/src/subset/contractions/findPossible.js b/src/subset/contractions/findPossible.js deleted file mode 100644 index 1d54321f3..000000000 --- a/src/subset/contractions/findPossible.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -//find contractable, expanded-contractions -const find = (r) => { - let remain = r.not('#Contraction'); - let m = remain.match('(#Noun|#QuestionWord) (#Copula|did|do|have|had|could|would|will)'); - m.concat(remain.match('(they|we|you|i) have')); - m.concat(remain.match('i am')); - m.concat(remain.match('(#Copula|#Modal|do|does|have|has|can|will) not')); - m.list.forEach((ts) => { - ts.expanded = true; - }); - return m; -}; -module.exports = find; diff --git a/src/subset/contractions/index.js b/src/subset/contractions/index.js deleted file mode 100644 index 12611033e..000000000 --- a/src/subset/contractions/index.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const ContractionCl = require('./contraction'); -const findPossible = require('./findPossible'); -//the Contractions() subset class - -const methods = { - contract: function() { - this.list.forEach(ts => ts.contract()); - return this; - }, - expand: function() { - this.list.forEach(ts => ts.expand()); - return this; - }, - contracted: function() { - this.list = this.list.filter(ts => { - return ts.contracted; - }); - return this; - }, - expanded: function() { - this.list = this.list.filter(ts => { - return !ts.contracted; - }); - return this; - } -}; - -const find = function(r, n) { - //find currently-contracted - let found = r.match('#Contraction #Contraction #Contraction?'); - found.list = found.list.map(ts => { - let c = new ContractionCl(ts.terms, ts.world, ts.refText, ts.refTerms); - c.contracted = true; - return c; - }); - //find currently-expanded - let expanded = findPossible(r); - expanded.list.forEach(ts => { - let c = new ContractionCl(ts.terms, ts.world, ts.refText, ts.refTerms); - c.contracted = false; - found.list.push(c); - }); - found.sort('chronological'); - //get nth element - if (typeof n === 'number') { - found = found.get(n); - } - return found; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/dates/date.js b/src/subset/dates/date.js deleted file mode 100644 index cf9895c12..000000000 --- a/src/subset/dates/date.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; -const Terms = require('../../paths').Terms; -const parseDate = require('./parseDate'); - -const _Date = function(arr, world, refText) { - Terms.call(this, arr, world, refText); - this.month = this.match('#Month'); -}; - -//Inherit properties -_Date.prototype = Object.create(Terms.prototype); - -_Date.prototype.data = function() { - return { - text: this.out('text'), - normal: this.out('normal'), - date: parseDate(this) - }; -}; - -module.exports = _Date; diff --git a/src/subset/dates/index.js b/src/subset/dates/index.js deleted file mode 100644 index 02895497f..000000000 --- a/src/subset/dates/index.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const Date = require('./date'); -const weekdays = require('./weekday'); -const months = require('./month'); -//the Dates() subset class -const methods = { - toShortForm: function() { - this.match('#Month') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - months.toShortForm(t); - }); - this.match('#WeekDay') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - weekdays.toShortForm(t); - }); - return this; - }, - toLongForm: function() { - this.match('#Month') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - months.toLongForm(t); - }); - this.match('#WeekDay') - .terms() - .list.forEach(ts => { - let t = ts.terms[0]; - weekdays.toLongForm(t); - }); - return this; - } -}; - -const find = function(r, n) { - let dates = r.match('#Date+'); - if (typeof n === 'number') { - dates = dates.get(n); - } - dates.list = dates.list.map(ts => { - return new Date(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return dates; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/dates/month/data.js b/src/subset/dates/month/data.js deleted file mode 100644 index fff838ee0..000000000 --- a/src/subset/dates/month/data.js +++ /dev/null @@ -1,33 +0,0 @@ -//follow the javascript scheme -//january is 0 -exports.longMonths = { - 'january': 0, - 'february': 1, - 'march': 2, - 'april': 3, - 'may': 4, - 'june': 5, - 'july': 6, - 'august': 7, - 'september': 8, - 'october': 9, - 'november': 10, - 'december': 11, -}; -exports.shortMonths = { - 'jan': 0, - 'feb': 1, - 'mar': 2, - 'apr': 3, - 'may': 4, - 'jun': 5, - 'jul': 6, - 'aug': 7, - 'sep': 8, - 'oct': 9, - 'nov': 10, - 'dec': 11, - //extra ones - 'febr': 1, - 'sept': 8, -}; diff --git a/src/subset/dates/month/index.js b/src/subset/dates/month/index.js deleted file mode 100644 index bfea70eb6..000000000 --- a/src/subset/dates/month/index.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; -const data = require('./data'); -const shortMonths = data.shortMonths; -const longMonths = data.longMonths; -const titleCase = str => { - return str.charAt(0).toUpperCase() + str.substr(1); -}; -module.exports = { - index: function (t) { - if (t.tags.Month) { - if (longMonths[t.normal] !== undefined) { - return longMonths[t.normal]; - } - if (shortMonths[t.normal] !== undefined) { - return shortMonths[t.normal]; - } - } - return null; - }, - toShortForm: function (t) { - if (t.tags.Month !== undefined) { - if (longMonths[t.normal] !== undefined) { - let shorten = Object.keys(shortMonths); - let punct = t.getPunctuation() || ''; - t.text = shorten[longMonths[t.normal]] + punct; - if (t.tags.TitleCase) { - t.text = titleCase(t.text); - } - } - } - t.dirty = true; - return t; - }, - toLongForm: function (t) { - if (t.tags.Month !== undefined) { - if (shortMonths[t.normal] !== undefined) { - let longer = Object.keys(longMonths); - let punct = t.getPunctuation() || ''; - t.text = longer[shortMonths[t.normal]] + punct; - if (t.tags.TitleCase) { - t.text = titleCase(t.text); - } - } - } - t.dirty = true; - return t; - } - -}; diff --git a/src/subset/dates/parseDate.js b/src/subset/dates/parseDate.js deleted file mode 100644 index a7a272143..000000000 --- a/src/subset/dates/parseDate.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; -const parseTime = require('./parseTime'); -const weekdays = require('./weekday'); -const months = require('./month'); -//a hugely-conservative and incomplete first-pass for parsing written-dates - -//validate a day-of-month -const isDate = (num) => { - if (num && num < 31 && num > 0) { - return true; - } - return false; -}; - -//please change this in one thousand years -const isYear = (num) => { - if (num && num > 1000 && num < 3000) { - return true; - } - return false; -}; - -// -const parseDate = (r) => { - let result = { - month: null, - date: null, - weekday: null, - year: null, - named: null, - time: null, - }; - let m = r.match('(#Holiday|today|tomorrow|yesterday)'); - if (m.found) { - result.named = m.out('normal'); - } - m = r.match('#Month'); - if (m.found) { - result.month = months.index(m.list[0].terms[0]); - } - m = r.match('#WeekDay'); - if (m.found) { - result.weekday = weekdays.index(m.list[0].terms[0]); - } - m = r.match('#Time'); - if (m.found) { - result.time = parseTime(r); - r.not('#Time'); //unsure - } - //january fifth 1992 - m = r.match('#Month #Value #Year'); - if (m.found) { - let numbers = m.values().numbers(); - if (isDate(numbers[0])) { - result.date = numbers[0]; - } - let year = parseInt(r.match('#Year').out('normal'), 10); - if (isYear(year)) { - result.year = year; - } - } - if (!m.found) { - //january fifth, january 1992 - m = r.match('#Month #Value'); - if (m.found) { - let numbers = m.values().numbers(); - let num = numbers[0]; - if (isDate(num)) { - result.date = num; - } - } - //january 1992 - m = r.match('#Month #Year'); - if (m.found) { - let num = parseInt(r.match('#Year').out('normal'), 10); - if (isYear(num)) { - result.year = num; - } - } - } - - //fifth of january - m = r.match('#Value of #Month'); - if (m.found) { - let num = m.values().numbers()[0]; - if (isDate(num)) { - result.date = num; - } - } - return result; -}; -module.exports = parseDate; diff --git a/src/subset/dates/parseTime.js b/src/subset/dates/parseTime.js deleted file mode 100644 index 193f13ff6..000000000 --- a/src/subset/dates/parseTime.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; -const ampm = /([12]?[0-9]) ?(am|pm)/i; -const hourMin = /([12]?[0-9]):([0-9][0-9]) ?(am|pm)?/i; -// -const isHour = (num) => { - if (num && num > 0 && num < 25) { - return true; - } - return false; -}; -const isMinute = (num) => { - if (num && num > 0 && num < 60) { - return true; - } - return false; -}; - - -const parseTime = (r) => { - let result = { - logic: null, - hour: null, - minute: null, - second: null, - timezone: null - }; - - let logic = r.match('(by|before|for|during|at|until|after) #Time').firstTerm(); - if (logic.found) { - result.logic = logic.out('normal'); - } - - let time = r.match('#Time'); - time.terms().list.forEach((ts) => { - let t = ts.terms[0]; - //3pm - let m = t.text.match(ampm); - if (m !== null) { - result.hour = parseInt(m[1], 10); - if (m[2] === 'pm') { - result.hour += 12; - } - if (isHour(result.hour) === false) { - result.hour = null; - } - } - //3:15 - m = t.text.match(hourMin); - if (m !== null) { - result.hour = parseInt(m[1], 10); - result.minute = parseInt(m[2], 10); - if (!isMinute(result.minute)) { - result.minute = null; - } - if (m[3] === 'pm') { - result.hour += 12; - } - if (isHour(result.hour) === false) { - result.hour = null; - } - } - }); - return result; -}; -module.exports = parseTime; diff --git a/src/subset/dates/weekday/data.js b/src/subset/dates/weekday/data.js deleted file mode 100644 index e4a2b6d71..000000000 --- a/src/subset/dates/weekday/data.js +++ /dev/null @@ -1,21 +0,0 @@ -//follow the javascript scheme -//sunday is 0 -exports.longDays = { - 'sunday': 0, - 'monday': 1, - 'tuesday': 2, - 'wednesday': 3, - 'thursday': 4, - 'friday': 5, - 'saturday': 6, -}; -exports.shortDays = { - 'sun': 0, - 'mon': 1, - 'tues': 2, - 'wed': 3, - 'weds': 3, - 'thurs': 4, - 'fri': 5, - 'sat': 6, -}; diff --git a/src/subset/dates/weekday/index.js b/src/subset/dates/weekday/index.js deleted file mode 100644 index f8e7e69f8..000000000 --- a/src/subset/dates/weekday/index.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -const data = require('./data'); -const shortDays = data.shortDays; -const longDays = data.longDays; - -module.exports = { - index: function (t) { - if (t.tags.WeekDay) { - if (longDays[t.normal] !== undefined) { - return longDays[t.normal]; - } - if (shortDays[t.normal] !== undefined) { - return shortDays[t.normal]; - } - } - return null; - }, - toShortForm: function (t) { - if (t.tags.WeekDay) { - if (longDays[t.normal] !== undefined) { - let shorten = Object.keys(shortDays); - t.text = shorten[longDays[t.normal]]; - } - } - return t; - }, - toLongForm: function (t) { - if (t.tags.WeekDay) { - if (shortDays[t.normal] !== undefined) { - let longer = Object.keys(longDays); - t.text = longer[shortDays[t.normal]]; - } - } - return t; - } -}; diff --git a/src/subset/ngrams/endGrams.js b/src/subset/ngrams/endGrams.js deleted file mode 100644 index a3e8583a6..000000000 --- a/src/subset/ngrams/endGrams.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; -const Ngrams = require('./index'); -const getGrams = require('./getGrams'); - -//like an n-gram, but only the endings of matches -const EndGrams = function(arr, world, original) { - Ngrams.call(this, arr, world, original); -}; - -//Inherit properties -EndGrams.prototype = Object.create(Ngrams.prototype); - -//like an n-gram, but only the startings of matches -EndGrams.find = function(r, n, size) { - let opts = { - size: [1, 2, 3, 4], - edge: 'end' - }; - //only look for bigrams, for example - if (size) { - opts.size = [size]; - } - //fetch them - let arr = getGrams(r, opts); - r = new EndGrams(arr); - //default sort - r.sort(); - //grab top one, or something - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; -module.exports = EndGrams; diff --git a/src/subset/ngrams/getGrams.js b/src/subset/ngrams/getGrams.js deleted file mode 100644 index e62c94a92..000000000 --- a/src/subset/ngrams/getGrams.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; -const Gram = require('./gram'); - -//strip contractions - remove '' term for "it's" -const noEmpty = function(fts) { - return fts = fts.terms.filter((t) => t._text !== ''); -}; - -//do all grams of one size, on one termList -const getGrams = function(fts, n) { - let terms = noEmpty(fts); - if (terms.length < n) { - return []; - } - let arr = []; - for(let i = 0; i < terms.length - n + 1; i++) { - let gram = new Gram(terms.slice(i, i + n)); - arr.push(gram); - } - return arr; -}; - -//left-sided grams -const startGram = function(fts, n) { - let terms = noEmpty(fts); - if (terms.length < n) { - return []; - } - let arr = [ - new Gram(terms.slice(0, n)), - ]; - return arr; -}; - -//right-sided grams -const endGram = function(fts, n) { - let terms = noEmpty(fts); - if (terms.length < n) { - return []; - } - let arr = [ - new Gram(terms.slice(terms.length - n, terms.length)) - ]; - return arr; -}; - -//ngrams are consecutive terms of a specific size -const buildGrams = function(r, options) { - options = options || {}; - options.size = options.size || [1, 2, 3]; - if (typeof options.size === 'number') { - options.size = [options.size]; - } - let obj = {}; - //collect and count all grams - options.size.forEach((size) => { - r.list.forEach((ts) => { - let newGrams = []; - if (options.edge === 'start') { - newGrams = startGram(ts, size); - } else if (options.edge === 'end') { - newGrams = endGram(ts, size); - } else { - newGrams = getGrams(ts, size); - } - newGrams.forEach((g) => { - if (obj.hasOwnProperty(g.key)) { - obj[g.key].inc(); - } else { - obj[g.key] = g; - } - }); - }); - }); - - //flatten to an array - let arr = Object.keys(obj).map((k) => obj[k]); - return arr; -}; - -module.exports = buildGrams; diff --git a/src/subset/ngrams/gram.js b/src/subset/ngrams/gram.js deleted file mode 100644 index 8f33e5271..000000000 --- a/src/subset/ngrams/gram.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -const Terms = require('../../paths').Terms; - -//this is one-or-more terms together, sorted by frequency -const Gram = function(arr, world, original) { - Terms.call(this, arr, world, original); - //string to sort/uniq by - this.key = this.out('normal'); - //bigram/trigram/etc - this.size = arr.length; - //number of occurances - this.count = 1; -}; - -//Inherit properties -Gram.prototype = Object.create(Terms.prototype); - -Gram.prototype.inc = function() { - this.count += 1; -}; - -module.exports = Gram; diff --git a/src/subset/ngrams/index.js b/src/subset/ngrams/index.js deleted file mode 100644 index c4bf37541..000000000 --- a/src/subset/ngrams/index.js +++ /dev/null @@ -1,80 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const getGrams = require('./getGrams'); - -const sort = function(r) { - r.list = r.list.sort((a, b) => { - if (a.count > b.count) { - return -1; - } - //(tie-braker) - if (a.count === b.count && (a.size > b.size || a.key.length > b.key.length)) { - return -1; - } - return 1; - }); - return r; -}; - -//the Ngrams() subset class -const methods = { - data: function() { - return this.list.map(ts => { - return { - normal: ts.out('normal'), - count: ts.count, - size: ts.size - }; - }); - }, - unigrams: function() { - this.list = this.list.filter(g => g.size === 1); - return this; - }, - bigrams: function() { - this.list = this.list.filter(g => g.size === 2); - return this; - }, - trigrams: function() { - this.list = this.list.filter(g => g.size === 3); - return this; - }, - //default sort the ngrams - sort: function() { - return sort(this); - } -}; - -const find = function(r, obj) { - let sizes = []; - //support .ngrams(3), for compat - if (typeof obj === 'number') { - obj = { - n: obj - }; - } - obj = obj || {}; - let max = obj.max || 4; - for (let i = 1; i <= max; i++) { - sizes.push(i); - } - //only look for bigrams, for example - if (obj.size) { - sizes = [obj.size]; - } - let opts = { - size: sizes - }; - //fetch them - let arr = getGrams(r, opts); - r = new Text(arr); - //default sort - r = sort(r); - //grab top one, or something - if (obj.n !== undefined) { - r = r.get(obj.n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/ngrams/startGrams.js b/src/subset/ngrams/startGrams.js deleted file mode 100644 index de8d2eeea..000000000 --- a/src/subset/ngrams/startGrams.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; -const Ngrams = require('./index'); -const getGrams = require('./getGrams'); - -const StartGrams = function(arr, world, original) { - Ngrams.call(this, arr, world, original); -}; - -//Inherit properties -StartGrams.prototype = Object.create(Ngrams.prototype); - -//like an n-gram, but only the startings of matches -StartGrams.find = function(r, n, size) { - let opts = { - size: [1, 2, 3, 4], - edge: 'start' - }; - //only look for bigrams, for example - if (size) { - opts.size = [size]; - } - //fetch them - let arr = getGrams(r, opts); - r = new StartGrams(arr); - //default sort - r.sort(); - //grab top one, or something - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = StartGrams; diff --git a/src/subset/nouns/hasPlural.js b/src/subset/nouns/hasPlural.js deleted file mode 100644 index 6ba0b5761..000000000 --- a/src/subset/nouns/hasPlural.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -//certain words can't be plural, like 'peace' -const hasPlural = function(t) { - //end quick - if (!t.tags.Noun) { - return false; - } - if (t.tags.Plural) { - return true; - } - //is it potentially plural? - const noPlural = ['Pronoun', 'Place', 'Value', 'Person', 'Month', 'WeekDay', 'RelativeDay', 'Holiday']; - for (let i = 0; i < noPlural.length; i++) { - if (t.tags[noPlural[i]]) { - return false; - } - } - //terms known as un-inflectable, like 'peace' - if (t.tags.Uncountable === true) { - return false; - } - return true; -}; - -module.exports = hasPlural; diff --git a/src/subset/nouns/index.js b/src/subset/nouns/index.js deleted file mode 100644 index 00d1b75bd..000000000 --- a/src/subset/nouns/index.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const Noun = require('./noun'); - -//the () subset class -const methods = { - isPlural: function() { - this.list = this.list.filter(ts => ts.isPlural()); - return this; - }, - hasPlural: function() { - return this.list.map(ts => ts.hasPlural()); - }, - toPlural: function() { - this.list.forEach(ts => ts.toPlural()); - return this; - }, - toSingular: function(verbose) { - this.list.forEach(ts => ts.toSingular(verbose)); - return this; - }, - toPossessive: function(verbose) { - this.list.forEach(ts => ts.toPossessive(verbose)); - return this; - }, - articles: function() { - return this.list.map(ts => { - return { - text: ts.out('text'), - normal: ts.out('normal'), - article: ts.article() - }; - }); - - } -}; - -const find = function(r, n) { - r = r.clauses(); - r = r.match('#Noun+ (of|by)? the? #Noun+?'); - //nouns that we don't want in these results, for weird reasons - r = r.not('#Pronoun'); - r = r.not('(there|these)'); - r = r.not('(#Month|#WeekDay)'); //allow Durations, Holidays - // //allow possessives like "spencer's", but not generic ones like, - r = r.not('(my|our|your|their|her|his)'); - r = r.not('(of|for|by|the)$'); - if (typeof n === 'number') { - r = r.get(n); - } - r.list = r.list.map(ts => { - return new Noun(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/nouns/isPlural.js b/src/subset/nouns/isPlural.js deleted file mode 100644 index 6489fdcae..000000000 --- a/src/subset/nouns/isPlural.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; -const rules = require('./methods/data/indicators'); -const prep = /([a-z]*) (of|in|by|for) [a-z]/; -const hasPlural = require('./hasPlural'); - -const knownPlural = { - i: false, - he: false, - she: false, - we: true, - they: true -}; - -//is it potentially plural? -const noPlural = ['Place', 'Value', 'Person', 'Month', 'WeekDay', 'RelativeDay', 'Holiday', 'Possessive']; -//first, try to guess based on existing tags -const couldEvenBePlural = function(t) { - if (hasPlural(t) === false) { - return false; - } - for (let i = 0; i < noPlural.length; i++) { - if (t.tags[noPlural[i]]) { - return false; - } - } - return true; -}; - -/** returns true, false, or null */ -const isPlural = function(t, world) { - if (t.tags.Plural) { - return true; - } - if (t.tags.Singular) { - return false; - } - let str = t.normal; - //whitelist a few easy ones - if (knownPlural.hasOwnProperty(str) === true) { - return knownPlural[str]; - } - //check given irregulars - if (world.plurals && world.plurals.hasOwnProperty(str) === true) { - return false; - } - //check opposite-ones - if (world.cache.toSingular && world.cache.toSingular.hasOwnProperty(str) === true) { - return true; - } - //inspect the existing tags to see if a plural is valid - if (couldEvenBePlural(t) === false) { - return null; - } - //handle 'mayors of chicago' - const preposition = str.match(prep); - if (preposition !== null) { - str = preposition[1]; - } - //check the suffix-type rules for indications - for (let i = 0; i < rules.plural_indicators.length; i++) { - if (rules.plural_indicators[i].test(str) === true) { - return true; - } - } - for (let i = 0; i < rules.singular_indicators.length; i++) { - if (rules.singular_indicators[i].test(str) === true) { - return false; - } - } - // a fallback 'looks check plural' rule.. - if (/s$/.test(str) === true && /ss$/.test(str) === false && str.length > 3) { - //needs some lovin' - return true; - } - return false; -}; - -module.exports = isPlural; -// console.log(is_plural('octopus')) diff --git a/src/subset/nouns/makeArticle.js b/src/subset/nouns/makeArticle.js deleted file mode 100644 index 37d98d5a9..000000000 --- a/src/subset/nouns/makeArticle.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -//chooses an indefinite aricle 'a/an' for a word -const irregulars = { - 'hour': 'an', - 'heir': 'an', - 'heirloom': 'an', - 'honest': 'an', - 'honour': 'an', - 'honor': 'an', - 'uber': 'an' //german u -}; -//pronounced letters of acronyms that get a 'an' -const an_acronyms = { - a: true, - e: true, - f: true, - h: true, - i: true, - l: true, - m: true, - n: true, - o: true, - r: true, - s: true, - x: true -}; -//'a' regexes -const a_regexs = [ - /^onc?e/i, //'wu' sound of 'o' - /^u[bcfhjkqrstn][aeiou]/i, // 'yu' sound for hard 'u' - /^eul/i -]; - -const makeArticle = function(t) { - let str = t.normal; - //no 'the john smith', but 'a london hotel' - if (t.tags.Person) { - return ''; - } - //no a/an if it's plural - if (t.tags.Plural) { - return 'the'; - } - //explicit irregular forms - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - //spelled-out acronyms - let firstLetter = str.substr(0, 1); - if (t.isAcronym() && an_acronyms.hasOwnProperty(firstLetter)) { - return 'an'; - } - //'a' regexes - for (let i = 0; i < a_regexs.length; i++) { - if (a_regexs[i].test(str)) { - return 'a'; - } - } - //basic vowel-startings - if (/^[aeiou]/i.test(str)) { - return 'an'; - } - return 'a'; -}; - -module.exports = makeArticle; diff --git a/src/subset/nouns/methods/data/indicators.js b/src/subset/nouns/methods/data/indicators.js deleted file mode 100644 index 63245ccb0..000000000 --- a/src/subset/nouns/methods/data/indicators.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; -//similar to plural/singularize rules, but not the same -const plural_indicators = [ - /(^v)ies$/i, - /ises$/i, - /ives$/i, - /(antenn|formul|nebul|vertebr|vit)ae$/i, - /(octop|vir|radi|nucle|fung|cact|stimul)i$/i, - /(buffal|tomat|tornad)oes$/i, - /(analy|ba|diagno|parenthe|progno|synop|the)ses$/i, - /(vert|ind|cort)ices$/i, - /(matr|append)ices$/i, - /(x|ch|ss|sh|s|z|o)es$/i, - /men$/i, - /news$/i, - /.tia$/i, - /(^f)ves$/i, - /(lr)ves$/i, - /(^aeiouy|qu)ies$/i, - /(m|l)ice$/i, - /(cris|ax|test)es$/i, - /(alias|status)es$/i, - /ics$/i -]; - -//similar to plural/singularize rules, but not the same -const singular_indicators = [ - /(ax|test)is$/i, - /(octop|vir|radi|nucle|fung|cact|stimul)us$/i, - /(octop|vir)i$/i, - /(rl)f$/i, - /(alias|status)$/i, - /(bu)s$/i, - /(al|ad|at|er|et|ed|ad)o$/i, - /(ti)um$/i, - /(ti)a$/i, - /sis$/i, - /(?:(^f)fe|(lr)f)$/i, - /hive$/i, - /(^aeiouy|qu)y$/i, - /(x|ch|ss|sh|z)$/i, - /(matr|vert|ind|cort)(ix|ex)$/i, - /(m|l)ouse$/i, - /(m|l)ice$/i, - /(antenn|formul|nebul|vertebr|vit)a$/i, - /.sis$/i, - /^(?!talis|.*hu)(.*)man$/i -]; -module.exports = { - singular_indicators: singular_indicators, - plural_indicators: plural_indicators -} diff --git a/src/subset/nouns/methods/data/pluralRules.js b/src/subset/nouns/methods/data/pluralRules.js deleted file mode 100644 index da75ee0d2..000000000 --- a/src/subset/nouns/methods/data/pluralRules.js +++ /dev/null @@ -1,33 +0,0 @@ -//patterns for turning 'bus' to 'buses' -module.exports = [ - [/(ax|test)is$/i, '$1es'], - [/(octop|vir|radi|nucle|fung|cact|stimul)us$/i, '$1i'], - [/(octop|vir)i$/i, '$1i'], - [/(kn|l|w)ife$/i, '$1ives'], - [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)f$/i, '$1ves'], - [/^(dwar|handkerchie|hoo|scar|whar)f$/i, '$1ves'], - [/(alias|status)$/i, '$1es'], - [/(bu)s$/i, '$1ses'], - [/(al|ad|at|er|et|ed|ad)o$/i, '$1oes'], - [/([ti])um$/i, '$1a'], - [/([ti])a$/i, '$1a'], - [/sis$/i, 'ses'], - [/(hive)$/i, '$1s'], - [/([^aeiouy]|qu)y$/i, '$1ies'], - [/(x|ch|ss|sh|s|z)$/i, '$1es'], - [/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices'], - [/([m|l])ouse$/i, '$1ice'], - [/([m|l])ice$/i, '$1ice'], - [/^(ox)$/i, '$1en'], - [/^(oxen)$/i, '$1'], - [/(quiz)$/i, '$1zes'], - [/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae'], - [/(sis)$/i, 'ses'], - [/^(?!talis|.*hu)(.*)man$/i, '$1men'], - [/(.*)/i, '$1s'] -].map(function(a) { - return { - reg: a[0], - repl: a[1] - }; -}); diff --git a/src/subset/nouns/methods/data/singleRules.js b/src/subset/nouns/methods/data/singleRules.js deleted file mode 100644 index 732ec16b7..000000000 --- a/src/subset/nouns/methods/data/singleRules.js +++ /dev/null @@ -1,33 +0,0 @@ -//patterns for turning 'dwarves' to 'dwarf' -module.exports = [ - [/([^v])ies$/i, '$1y'], - [/ises$/i, 'isis'], - [/(kn|[^o]l|w)ives$/i, '$1ife'], - [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i, '$1f'], - [/^(dwar|handkerchie|hoo|scar|whar)ves$/i, '$1f'], - [/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a'], - [/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i, '$1us'], - [/(buffal|tomat|tornad)(oes)$/i, '$1o'], - // [/(analy|diagno|parenthe|progno|synop|the)ses$/i, '$1sis'], - [/(..[aeiou]s)es$/i, '$1'], - [/(vert|ind|cort)(ices)$/i, '$1ex'], - [/(matr|append)(ices)$/i, '$1ix'], - [/(x|ch|ss|sh|z|o)es$/i, '$1'], - [/men$/i, 'man'], - [/(n)ews$/i, '$1ews'], - [/([ti])a$/i, '$1um'], - [/([^aeiouy]|qu)ies$/i, '$1y'], - [/(s)eries$/i, '$1eries'], - [/(m)ovies$/i, '$1ovie'], - [/([m|l])ice$/i, '$1ouse'], - [/(cris|ax|test)es$/i, '$1is'], - [/(alias|status)es$/i, '$1'], - [/(ss)$/i, '$1'], - [/(ics)$/i, '$1'], - [/s$/i, ''] -].map(function(a) { - return { - reg: a[0], - repl: a[1] - }; -}); diff --git a/src/subset/nouns/methods/paths.js b/src/subset/nouns/methods/paths.js deleted file mode 100644 index da9b0cd6a..000000000 --- a/src/subset/nouns/methods/paths.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../../../paths'); diff --git a/src/subset/nouns/methods/pluralize.js b/src/subset/nouns/methods/pluralize.js deleted file mode 100644 index 177aabba2..000000000 --- a/src/subset/nouns/methods/pluralize.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; -// const irregulars = require('../../../lexicon/uncompressed/irregularPlurals').toPlural; -const pluralRules = require('./data/pluralRules'); - -//turn 'shoe' into 'shoes' -const pluralize = function(str, world) { - const irregulars = world.plurals || {}; - //irregular - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - //regular rule-based inflector - for (let i = 0; i < pluralRules.length; i++) { - if (pluralRules[i].reg.test(str) === true) { - return str.replace(pluralRules[i].reg, pluralRules[i].repl); - } - } - return null; -}; - -module.exports = pluralize; diff --git a/src/subset/nouns/methods/singularize.js b/src/subset/nouns/methods/singularize.js deleted file mode 100644 index 7d06ec766..000000000 --- a/src/subset/nouns/methods/singularize.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; -const singleRules = require('./data/singleRules'); - -//turn 'shoes' into 'shoe' -const toSingle = function(str, world) { - //reverse it //TODO: cache in world object somewhere - let irregulars = world.cache.toSingular || {}; - //check irregulars - if (irregulars.hasOwnProperty(str) === true) { - return irregulars[str]; - } - if (world && world.plurals) { - //given irregulars - let keys = Object.keys(world.plurals); - for (let i = 0; i < keys.length; i++) { - if (world.plurals[keys[i]] === str) { - return keys[i]; - } - } - } - - //inflect first word of preposition-phrase - if (/([a-z]*) (of|in|by|for) [a-z]/.test(str) === true) { - const first = (str.match(/^([a-z]*) (of|in|by|for) [a-z]/) || [])[1]; - if (first) { - const better_first = toSingle(first); //recursive - return better_first + str.replace(first, ''); - } - } - - //regular rule-based inflector - for (let i = 0; i < singleRules.length; i++) { - if (singleRules[i].reg.test(str) === true) { - return str.replace(singleRules[i].reg, singleRules[i].repl); - } - } - return null; -}; - -module.exports = toSingle; -// console.log(toSingle('days')) diff --git a/src/subset/nouns/noun.js b/src/subset/nouns/noun.js deleted file mode 100644 index cc0fa4f16..000000000 --- a/src/subset/nouns/noun.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; -const Terms = require('../../paths').Terms; -const hasPlural = require('./hasPlural'); -const isPlural = require('./isPlural'); -const toPossessive = require('./toPossessive'); -const makeArticle = require('./makeArticle'); -const pluralize = require('./methods/pluralize'); -const singularize = require('./methods/singularize'); - -const methods = { - article: function() { - return makeArticle(this.main); - }, - isPlural: function() { - return isPlural(this.main, this.world); - }, - hasPlural: function() { - return hasPlural(this.main); - }, - toPlural: function(verbose) { - let t = this.main; - if (hasPlural(t) && !isPlural(t, this.world)) { - t.text = pluralize(t.normal, this.world, verbose) || t.text; - t.unTag('Singular', 'toPlural'); - t.tag('Plural', 'toPlural'); - } - return this; - }, - toSingular: function(verbose) { - let t = this.main; - if (isPlural(t, this.world)) { - t.text = singularize(t.normal, this.world, verbose) || t.text; - t.unTag('Plural', 'toSingular'); - t.tag('Singular', 'toSingular'); - } - return this; - }, - toPossessive: function() { - let t = this.main; - if (t.tags.Possessive) { - return this; - } - t = toPossessive(t); - return this; - }, - data: function() { - let t = this.main; - let singular = t.text; - if (isPlural(t, this.world)) { - singular = singularize(t.normal, this.world) || t.text; - } - let plural = t.text; - if (hasPlural(t) && !isPlural(t, this.world)) { - plural = pluralize(t.normal, this.world) || t.text; - } - //support 'mayors of chicago' - let qualifier = ''; - if (this.qualifier) { - qualifier = this.qualifier.out('normal'); - singular += ' ' + qualifier; - plural += ' ' + qualifier; - } - return { - text: this.out('text'), - normal: this.out('normal'), - article: this.article(), - main: t.normal, - qualifier: qualifier, - singular: singular, - plural: plural - }; - } -}; - -const Noun = function(arr, world, refText) { - Terms.call(this, arr, world, refText); - //support 'mayor of chicago' as one noun-phrase - this.main = this.match('[#Noun+] (of|by|for)'); - if (this.main.found) { - this.main = this.main.list[0].terms[0]; - } else { - this.main = this.terms[this.terms.length - 1]; - } - //'of chicago' - this.qualifier = this.match(this.main.normal + ' [.+]').list[0]; -}; -Noun.prototype = Object.create(Terms.prototype); - -Object.keys(methods).forEach(k => { - Noun.prototype[k] = methods[k]; -}); -module.exports = Noun; diff --git a/src/subset/nouns/toPossessive.js b/src/subset/nouns/toPossessive.js deleted file mode 100644 index dfa55deea..000000000 --- a/src/subset/nouns/toPossessive.js +++ /dev/null @@ -1,33 +0,0 @@ -const exceptions = { - he: 'his', - she: 'hers', - they: 'theirs', - we: 'ours', - i: 'mine', - you: 'yours', - - her: 'hers', - their: 'theirs', - our: 'ours', - my: 'mine', - your: 'yours', -}; - -// turn "David" to "David's" -const toPossessive = function(t) { - t.tag('Possessive', 'toPossessive'); - // exceptions - if (exceptions.hasOwnProperty(t.normal)) { - t.text = exceptions[t.normal]; - return t; - } - // flanders' - if (/s$/.test(t.normal)) { - t.text += '\''; - return t; - } - //normal form: - t.text += '\'s'; - return t; -}; -module.exports = toPossessive; diff --git a/src/subset/people/guessGender.js b/src/subset/people/guessGender.js deleted file mode 100644 index eb6524b2c..000000000 --- a/src/subset/people/guessGender.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -// make a statistical assumption about the gender of the person based on their given name -// used for pronoun resolution only. -// not intended for classification, or discrimination of people. -const gender = function (firstName) { - if (!firstName) { - return null; - } - //statistical guesses - if (/.(i|ee|[a|e]y|a)$/.test(firstName) === true) { //this is almost-always true - return 'Female'; - } - if (/[ou]$/.test(firstName) === true) { //if it ends in a 'oh or uh', male - return 'Male'; - } - if (/(nn|ll|tt)/.test(firstName) === true) { //if it has double-consonants, female - return 'Female'; - } - // name not recognized, or recognized as of indeterminate gender - return null; -}; -module.exports = gender; diff --git a/src/subset/people/index.js b/src/subset/people/index.js deleted file mode 100644 index 17e6ec481..000000000 --- a/src/subset/people/index.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const Person = require('./person'); -//this is used for pronoun and honorifics, and not intented for more-than grammatical use (see #117) - -//the () subset class -const methods = { - pronoun: function() { - return this.list.map(ts => ts.pronoun()); - }, - firstNames: function() { - return this.match('#FirstName'); - }, - lastNames: function() { - return this.match('#LastName'); - } -}; - -const find = function(r, n) { - let people = r.clauses(); - people = people.match('#Person+'); - if (typeof n === 'number') { - people = people.get(n); - } - people.list = people.list.map(ts => { - return new Person(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return people; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/people/person.js b/src/subset/people/person.js deleted file mode 100644 index 4db9a7b65..000000000 --- a/src/subset/people/person.js +++ /dev/null @@ -1,80 +0,0 @@ -'use strict'; -const Terms = require('../../paths').Terms; -const guessGender = require('./guessGender'); - -const Person = function(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - this.firstName = this.match('#FirstName+'); - this.middleName = this.match('#Acronym+'); - this.nickName = this.match('#NickName+'); - this.honorifics = this.match('#Honorific'); - this.lastName = this.match('#LastName+'); - //assume first-last - if (!this.firstName.found && this.length > 1) { - let m = this.not('(#Acronym|#Honorific)'); - this.firstName = m.first(); - this.lastName = m.last(); - } - return this; -}; -//Inherit properties -Person.prototype = Object.create(Terms.prototype); - -const methods = { - data: function() { - return { - text: this.out('text'), - normal: this.out('normal'), - firstName: this.firstName.out('normal'), - middleName: this.middleName.out('normal'), - nickName: this.nickName.out('normal'), - lastName: this.lastName.out('normal'), - genderGuess: this.guessGender(), - pronoun: this.pronoun(), - honorifics: this.honorifics.out('array') - }; - }, - guessGender: function() { - //try known honorifics - if (this.honorifics.match('(mr|mister|sr|sir|jr)').found) { - return 'Male'; - } - if (this.honorifics.match('(mrs|miss|ms|misses|mme|mlle)').found) { - return 'Female'; - } - //try known first-names - if (this.firstName.match('#MaleName').found) { - return 'Male'; - } - if (this.firstName.match('#FemaleName').found) { - return 'Female'; - } - //look-for regex clues - let str = this.firstName.out('normal'); - return guessGender(str); - }, - pronoun: function() { - let str = this.firstName.out('normal'); - let g = this.guessGender(str); - if (g === 'Male') { - return 'he'; - } - if (g === 'Female') { - return 'she'; - } - return 'they'; - }, - root: function() { - let first = this.firstName.out('root'); - let last = this.lastName.out('root'); - if (first && last) { - return first + ' ' + last; - } - return last || first || this.out('root'); - } -}; - -Object.keys(methods).forEach(k => { - Person.prototype[k] = methods[k]; -}); -module.exports = Person; diff --git a/src/subset/possessives/index.js b/src/subset/possessives/index.js deleted file mode 100644 index 6dd883854..000000000 --- a/src/subset/possessives/index.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -const Text = require('../../text'); -// const Terms = require('../../paths').Terms; - -const methods = { - //remove the 's on the end of the word - strip() { - this.list.forEach((ts) => { - let t = ts.terms[ts.terms.length - 1]; - t.text = t.text.replace(/'s$/, ''); - t.unTag('Possessive', '.strip()'); - }); - return this; - } -}; - -const find = function(r, n) { - r = r.match('#Possessive+'); - r = r.splitAfter('#Comma'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/sentences/index.js b/src/subset/sentences/index.js deleted file mode 100644 index 4fef73bf0..000000000 --- a/src/subset/sentences/index.js +++ /dev/null @@ -1,112 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const Sentence = require('./sentence'); -//the Sentences() subset class -const methods = { - /** conjugate the main/first verb*/ - toPastTense: function() { - this.list = this.list.map(ts => { - ts = ts.toPastTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toPresentTense: function() { - this.list = this.list.map(ts => { - ts = ts.toPresentTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toFutureTense: function() { - this.list = this.list.map(ts => { - ts = ts.toFutureTense(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toContinuous: function() { - this.list = this.list.map(ts => { - ts = ts.toContinuous(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - /** negative/positive */ - toNegative: function() { - this.list = this.list.map(ts => { - ts = ts.toNegative(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - toPositive: function() { - this.list = this.list.map(ts => { - ts = ts.toPositive(); - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return this; - }, - - /** look for 'was _ by' patterns */ - isPassive: function() { - this.list = this.list.filter(ts => { - return ts.isPassive(); - }); - return this; - }, - //return only questions - isQuestion: function() { - // this.list = this.list.filter(ts => { - // return ts.isQuestion(); - // }); - return this.questions() - }, - /** add a word to the start */ - prepend: function(str) { - this.list = this.list.map(ts => { - return ts.prepend(str); - }); - return this; - }, - /** add a word to the end */ - append: function(str) { - this.list = this.list.map(ts => { - return ts.append(str); - }); - return this; - }, - - /** convert between question/statement/exclamation*/ - toExclamation: function() { - this.list.forEach(ts => { - ts.setPunctuation('!'); - }); - return this; - }, - toQuestion: function() { - this.list.forEach(ts => { - ts.setPunctuation('?'); - }); - return this; - }, - toStatement: function() { - this.list.forEach(ts => { - ts.setPunctuation('.'); - }); - return this; - } -}; - -const find = function(r, n) { - r = r.all(); - if (typeof n === 'number') { - r = r.get(n); - } - r.list = r.list.map(ts => { - return new Sentence(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/sentences/isQuestion.js b/src/subset/sentences/isQuestion.js deleted file mode 100644 index dd3373238..000000000 --- a/src/subset/sentences/isQuestion.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -//is this sentence asking a question? -const isQuestion = function (ts) { - let endPunct = ts.getPunctuation(); - let clauses = ts.match('*').splitAfter('#Comma'); - - if (/\?/.test(endPunct) === true) { - return true; - } - - // Has ellipsis at the end means it's probably not a question - // e.g., Is this just fantasy... - if (/\.\.$/.test(ts.out('text'))) { - return false; - } - - // Starts with question word, but has a comma, so probably not a question - // e.g., Why are we caught in a land slide, no escape from reality - if (ts.has('^#QuestionWord') && ts.has('#Comma')) { - return false; - } - - // Starts with a #QuestionWord - // e.g., What open your eyes look up to the skies and see - if (ts.has('^#QuestionWord')) { - return true; - } - - // Second word is a #QuestionWord - // e.g., I'm what a poor boy - // case ts.has('^\w+\s#QuestionWord'): - // return true; - - // is it, do you - start of sentence - // e.g., Do I need no sympathy - if (ts.has('^(do|does|did|is|was|can|could|will|would|may) #Noun')) { - return true; - } - - // these are a little more loose.. - // e.g., Must I be come easy come easy go - if (ts.has('^(have|must) you')) { - return true; - } - - // Clause starts with a question word - // e.g., Anyway the wind blows, what doesn't really matter to me - if (clauses.has('^#QuestionWord')) { - return true; - } - - //is wayne gretskzy alive - if (clauses.has('(do|does|is|was) #Noun+ #Adverb? (#Adjective|#Infinitive)$')) { - return true; - } - - // Probably not a question - return false; - -}; -module.exports = isQuestion; diff --git a/src/subset/sentences/sentence.js b/src/subset/sentences/sentence.js deleted file mode 100644 index 9e9f22244..000000000 --- a/src/subset/sentences/sentence.js +++ /dev/null @@ -1,201 +0,0 @@ -'use strict'; -const Terms = require('../../paths').Terms; -const toNegative = require('./toNegative'); -const toPositive = require('./toPositive'); -const Verb = require('../verbs/verb'); -const insert = require('./smartInsert'); - -//decide on main subject-verb-object -const parse = function(s) { - //strip conditions first - let conditions = s.match('#Condition'); - let tmp = s.not('#Condition'); - //choose the verb first - let verb = tmp.match('#VerbPhrase+').first(); //this should be much smarter - let vb = verb.out('normal'); - //get subj noun left-of the verb - let subject = tmp.match('#Determiner? #Adjective+? #Noun ' + vb).first().not('#VerbPhrase'); - //get obj noun right-of the verb - let object = tmp.match(vb + ' #Preposition? #Determiner? #Noun').first().not('#VerbPhrase'); - s.conditions = conditions; - s.subject = subject; - s.verb = verb; - s.object = object; - if (s.verb.found) { - s.verb = new Verb(s.verb.list[0].terms, s.world, s.refText, s.refTerms); - } - return s; -}; - -const fixContraction = function(contr) { - if (contr.found) { - contr.contractions().expand(); - } -}; - -const killContraction = function(s) { - s.terms = s.terms.filter(t => { - if (t.silent_term) { - if (t.silent_term === 'am' || t.silent_term === 'will' || t.silent_term === 'did') { - return false; - } - t.text = t.silent_term; - t.silent_term = null; - t.unTag('Contraction'); - if (t.tags.TitleCase === true) { - t.toTitleCase(); - } - } - return true; - }); -}; - -//if the subject of thr sentence is plural, use infinitive form of verb -// (he goes / i go) -const useInfinitive = function(s) { - if (s.subject.found && s.subject.has('(i|we)')) { - return true; - } - return false; -}; - -const methods = { - /** inflect the main/first noun*/ - toSingular: function() { - let nouns = this.match('#Noun').match('!#Pronoun').firstTerm(); - nouns.things().toSingular(); - return this; - }, - toPlural: function() { - let nouns = this.match('#Noun').match('!#Pronoun').firstTerm(); - nouns.things().toPlural(); - return this; - }, - - /** find the first important verbPhrase. returns a Term object */ - mainVerb: function() { - parse(this); //re-parse - if (this.verb.found) { - return this.verb; - } - return null; - }, - - /** sentence tense conversion**/ - toPastTense: function() { - let verb = this.mainVerb(); - if (verb) { - //this is really ugly.. - let start = verb.out('root'); - verb.toPastTense(); - //support "i'm going" - let contr = this.match('#Contraction ' + start); - fixContraction(contr); - let end = verb.out('root'); - // this.replace(start, end) - let r = this.parentTerms.replace(start, end); - return r; - } - return this; - }, - toPresentTense: function() { - let verb = this.mainVerb(); - if (verb) { - let start = verb.out('normal'); - //plural/singular stuff - if (useInfinitive(this) === true) { - if (this.has('(am|will|did) ' + start)) { - killContraction(this); - } - verb.toInfinitive(); - //irregular "i am" - // this.debug(); - // if (this.has('i #Adverb? is')) { - // this.replace(' #Adverb? [is]', 'am'); - // } - } else { - verb.toPresentTense(); - let contr = this.match('#Contraction ' + start); - fixContraction(contr); - } - //support "i'm going" - let end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - return this; - }, - toFutureTense: function() { - let verb = this.mainVerb(); - if (verb) { - let start = verb.clone(); //.out('root'); - verb.toFutureTense(); - //support "i'm going" - let contr = this.match('#Contraction ' + start.out('normal')); - fixContraction(contr); - let end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - return this; - }, - toContinuous: function() { - let verb = this.mainVerb(); - if (verb) { - let start = verb.clone(); //.out('root'); - //'is walking' or 'are walking'? - // let aux = 'is'; - // if (useInfinitive(this)) { - // aux = 'are'; - // } - verb.toGerund(); - // verb.insertBefore(aux); - //support "i'm going" - let contr = this.match('#Contraction ' + start.out('normal')); - fixContraction(contr); - let end = verb.out('normal'); - return this.parentTerms.replace(start, end); - } - return this; - }, - - /** negation **/ - isNegative: function() { - return this.match('#Negative').list.length === 1; - }, - toNegative: function() { - if (this.isNegative()) { - return this; - } - return toNegative(this); - }, - toPositive: function() { - if (!this.isNegative()) { - return this; - } - return toPositive(this); - }, - - /** smarter insert methods*/ - append: function(str) { - return insert.append(this, str); - }, - prepend: function(str) { - return insert.prepend(this, str); - }, - - /** look for 'was _ by' patterns */ - isPassive: function() { - return this.match('was #Adverb? #PastTense #Adverb? by').found; //haha - } -}; - -const Sentence = function(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - parse(this); -}; -//Terms inheritence -Sentence.prototype = Object.create(Terms.prototype); -//add-in methods -Object.keys(methods).forEach(k => { - Sentence.prototype[k] = methods[k]; -}); -module.exports = Sentence; diff --git a/src/subset/sentences/smartInsert.js b/src/subset/sentences/smartInsert.js deleted file mode 100644 index e8d5000ae..000000000 --- a/src/subset/sentences/smartInsert.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; -const hasCapital = /^[A-Z]/; - -//sticking words at the start sentence-sensitive -const prepend = (ts, str) => { - let firstTerm = ts.terms[0]; - ts.insertAt(0, str); - //handle titlecase of first-word - if (hasCapital.test(firstTerm.text)) { - //is it titlecased because it should be? - if (firstTerm.needsTitleCase() === false) { - firstTerm.toLowerCase(); - } - let newTerm = ts.terms[0]; - newTerm.toTitleCase(); - } - return ts; -}; - -//sticking words on end sentence-sensitive -const append = (ts, str) => { - let endTerm = ts.terms[ts.terms.length - 1]; - //move the sentence punctuation to the end - let punct = ts.getPunctuation(); - if (punct) { - endTerm.killPunctuation(); - } - ts.insertAt(ts.terms.length, str); - let newTerm = ts.terms[ts.terms.length - 1]; - if (punct) { - newTerm.text += punct; - } - //move over sentence-ending whitespace too - if (endTerm.whitespace.after) { - newTerm.whitespace.after = endTerm.whitespace.after; - endTerm.whitespace.after = ''; - } - return ts; -}; - -module.exports = { - append: append, - prepend: prepend -}; diff --git a/src/subset/sentences/toNegative.js b/src/subset/sentences/toNegative.js deleted file mode 100644 index ad1dc1dce..000000000 --- a/src/subset/sentences/toNegative.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -//these terms are nicer ways to negate a sentence -//ie. john always walks -> john always doesn't walk -const logicalNegate = { - everyone: 'no one', - everybody: 'nobody', - someone: 'no one', - somebody: 'nobody', - // everything:"nothing", - always: 'never' -}; - -//different rule for i/we/they/you + infinitive -//that is, 'i walk' -> 'i don\'t walk', not 'I not walk' -const toNegative = ts => { - let lg = ts.match('(everyone|everybody|someone|somebody|always)').first(); - if (lg.found && logicalNegate[lg.out('normal')]) { - let found = lg.out('normal'); - // ts = ts.replace(found, logicalNegate[found]); - ts = ts.match(found).replaceWith(logicalNegate[found]).list[0]; - return ts.parentTerms; - } - //negate the main verb of the sentence - let vb = ts.mainVerb(); - if (vb) { - vb.toNegative(); - } - return ts; -}; -module.exports = toNegative; diff --git a/src/subset/sentences/toPositive.js b/src/subset/sentences/toPositive.js deleted file mode 100644 index ef8589207..000000000 --- a/src/subset/sentences/toPositive.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -//ie. john never walks -> john always walks -//nobody/noone are ambiguous logically (somebody? / everybody?) -const logical = { - 'never': 'always', - 'nothing': 'everything', -}; - -const toPositive = (ts) => { - let m = ts.match('(never|nothing)').first(); - if (m.found) { - let str = m.out('normal'); - if (logical[str]) { - ts = ts.match(str).replaceWith(logical[str], true).list[0]; - return ts.parentTerms; - } - } - //otherwise just remove 'not' - ts.delete('#Negative'); - return ts; -}; -module.exports = toPositive; diff --git a/src/subset/terms/index.js b/src/subset/terms/index.js deleted file mode 100644 index 10971051a..000000000 --- a/src/subset/terms/index.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const Terms = require('../../paths').Terms; - -//the Terms() subset class -//this is just a wrapper around the actual Term class, -//which is buried in `ts.terms[0]` -const methods = { - data: function() { - return this.list.map(ts => { - let t = ts.terms[0]; - return { - spaceBefore: t.whitespace.before, - text: t.text, - spaceAfter: t.whitespace.after, - normal: t.normal, - implicit: t.silent_term, - bestTag: t.bestTag(), - tags: Object.keys(t.tags) - }; - }); - } -}; - -const find = function(r, n) { - let list = []; - //make a Terms Object for every Term - r.list.forEach(ts => { - ts.terms.forEach(t => { - list.push(new Terms([t], ts.world, r)); - }); - }); - r = new Text(list, r.world, r.parent); - if (typeof n === 'number') { - r = r.get(n); - } - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/values/format/index.js b/src/subset/values/format/index.js deleted file mode 100644 index 2ff9362c2..000000000 --- a/src/subset/values/format/index.js +++ /dev/null @@ -1,29 +0,0 @@ -const numOrdinal = require('./numOrdinal'); -const textOrdinal = require('./textOrdinal'); -const textCardinal = require('./textCardinal'); -const niceNumber = require('./niceNumber'); - -//make all the number formats -const fmt = { - nice: function(num) { - return niceNumber(num); - }, - ordinal: function(num) { - return numOrdinal(num); - }, - cardinal: function(num) { - return String(num); - }, - niceOrdinal: function(num) { - num = numOrdinal(num); - num = niceNumber(num); - return num; - }, - text: function(num) { - return textCardinal(num).join(' '); - }, - textOrdinal: function(num) { - return textOrdinal(num); - } -}; -module.exports = fmt; diff --git a/src/subset/values/format/niceNumber.js b/src/subset/values/format/niceNumber.js deleted file mode 100644 index efab35e8e..000000000 --- a/src/subset/values/format/niceNumber.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -//put a comma or two in -const niceNumber = function (num) { - if (!num && num !== 0) { - return null; - } - num = String(num); - let x = num.split('.'); - let x1 = x[0]; - let x2 = x.length > 1 ? '.' + x[1] : ''; - let rgx = /(\d+)(\d{3})/; - while (rgx.test(x1)) { - x1 = x1.replace(rgx, '$1' + ',' + '$2'); - } - return x1 + x2; -}; -module.exports = niceNumber; diff --git a/src/subset/values/format/numOrdinal.js b/src/subset/values/format/numOrdinal.js deleted file mode 100644 index daebc7ba4..000000000 --- a/src/subset/values/format/numOrdinal.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -const toString = require('./toString'); - -//turn a number like 5 into an ordinal like 5th -const numOrdinal = function(num) { - if (!num && num !== 0) { - return null; - } - //the teens are all 'th' - let tens = num % 100; - if (tens > 10 && tens < 20) { - return String(num) + 'th'; - } - //the rest of 'em - const mapping = { - 0: 'th', - 1: 'st', - 2: 'nd', - 3: 'rd' - }; - let str = toString(num); - let last = str.slice(str.length - 1, str.length); - if (mapping[last]) { - str += mapping[last]; - } else { - str += 'th'; - } - return str; -}; - -module.exports = numOrdinal; diff --git a/src/subset/values/format/textCardinal.js b/src/subset/values/format/textCardinal.js deleted file mode 100644 index 7f3dcf78e..000000000 --- a/src/subset/values/format/textCardinal.js +++ /dev/null @@ -1,160 +0,0 @@ -'use strict'; -const toString = require('./toString'); - -// turns an integer/float into a textual number, like 'fifty-five' -const tens_mapping = [ - ['ninety', 90], - ['eighty', 80], - ['seventy', 70], - ['sixty', 60], - ['fifty', 50], - ['forty', 40], - ['thirty', 30], - ['twenty', 20] -]; -const ones_mapping = [ - '', - 'one', - 'two', - 'three', - 'four', - 'five', - 'six', - 'seven', - 'eight', - 'nine', - 'ten', - 'eleven', - 'twelve', - 'thirteen', - 'fourteen', - 'fifteen', - 'sixteen', - 'seventeen', - 'eighteen', - 'nineteen' -]; - -const sequence = [ - [1e24, 'septillion'], - [1e21, 'sextillion'], - [1e18, 'quintillion'], - [1e15, 'quadrillion'], - [1e12, 'trillion'], - [1e9, 'billion'], - [1e8, 'hundred million'], - [1e6, 'million'], - [100000, 'hundred thousand'], - [1000, 'thousand'], - [100, 'hundred'], - [1, 'one'] -]; - -//turn number into an array of magnitudes, like [[5, million], [2, hundred]] -const breakdown_magnitudes = function(num) { - let working = num; - let have = []; - sequence.forEach((a) => { - if (num >= a[0]) { - let howmany = Math.floor(working / a[0]); - working -= howmany * a[0]; - if (howmany) { - have.push({ - unit: a[1], - count: howmany - }); - } - } - }); - return have; -}; - -//turn numbers from 100-0 into their text -const breakdown_hundred = function(num) { - let arr = []; - if (num > 100) { - return arr; //something bad happened.. - } - for (let i = 0; i < tens_mapping.length; i++) { - if (num >= tens_mapping[i][1]) { - num -= tens_mapping[i][1]; - arr.push(tens_mapping[i][0]); - } - } - //(hopefully) we should only have 20-0 now - if (ones_mapping[num]) { - arr.push(ones_mapping[num]); - } - return arr; -}; - -/** print-out 'point eight nine'*/ -const handle_decimal = (num) => { - const names = [ - 'zero', - 'one', - 'two', - 'three', - 'four', - 'five', - 'six', - 'seven', - 'eight', - 'nine' - ]; - let arr = []; - //parse it out like a string, because js math is such shit - let str = toString(num); - let decimal = str.match(/\.([0-9]+)/); - if (!decimal || !decimal[0]) { - return arr; - } - arr.push('point'); - let decimals = decimal[0].split(''); - for (let i = 0; i < decimals.length; i++) { - arr.push(names[decimals[i]]); - } - return arr; -}; - -/** turns an integer into a textual number */ -const to_text = function(num) { - //big numbers, north of sextillion, aren't gonna work well.. - //keep them small.. - if (num > 1e21) { - return [String(num)]; - } - let arr = []; - //handle negative numbers - if (num < 0) { - arr.push('negative'); - num = Math.abs(num); - } - //break-down into units, counts - let units = breakdown_magnitudes(num); - //build-up the string from its components - for (let i = 0; i < units.length; i++) { - let unit_name = units[i].unit; - if (unit_name === 'one') { - unit_name = ''; - //put an 'and' in here - if (arr.length > 1) { - arr.push('and'); - } - } - arr = arr.concat(breakdown_hundred(units[i].count)); - arr.push(unit_name); - } - //also support decimals - 'point eight' - arr = arr.concat(handle_decimal(num)); - //remove empties - arr = arr.filter((s) => s); - if (arr.length === 0) { - arr[0] = ''; - } - return arr; -}; - -module.exports = to_text; - -// console.log(to_text(-1000.8)); diff --git a/src/subset/values/format/textOrdinal.js b/src/subset/values/format/textOrdinal.js deleted file mode 100644 index edd111380..000000000 --- a/src/subset/values/format/textOrdinal.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; -const textValue = require('./textCardinal'); -const ordinalWord = require('../../../world/more-data/numbers').toOrdinal; -// -const textOrdinal = num => { - let words = textValue(num); - //convert the last number to an ordinal - let last = words[words.length - 1]; - words[words.length - 1] = ordinalWord[last] || last; - return words.join(' '); -}; - -module.exports = textOrdinal; diff --git a/src/subset/values/format/toString.js b/src/subset/values/format/toString.js deleted file mode 100644 index 80e75d8b6..000000000 --- a/src/subset/values/format/toString.js +++ /dev/null @@ -1,15 +0,0 @@ -//turn big numbers, like 2.3e+22, into a tonne of 0's -const numToString = function(n) { - if (n < 1000000) { - return String(n); - } - var str = n.toFixed(0); - if (str.indexOf('e+') === -1) { - return str; - } - return str.replace('.', '').split('e+').reduce(function(p, b) { - return p + Array(b - p.length + 2).join(0); - }); -}; -module.exports = numToString; -// console.log(numToString(2.5e+22)); diff --git a/src/subset/values/index.js b/src/subset/values/index.js deleted file mode 100644 index 5e75bad0c..000000000 --- a/src/subset/values/index.js +++ /dev/null @@ -1,201 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const Value = require('./value'); -const parse = require('./parse'); - -//the Values() subset class -const methods = { - noDates: function() { - return this.not('#Date'); - }, - noUnits: function() { - return this.not('#Unit'); - }, - units: function() { - return this.match('#Unit+'); - }, - /** five -> 5 */ - numbers: function() { - return this.list.map(ts => { - return ts.number(); - }); - }, - /** five -> '5' */ - toNumber: function() { - this.list = this.list.map(ts => { - return ts.toNumber(); - }); - return this; - }, - /**5 -> 'five' */ - toText: function() { - this.list = this.list.map(ts => { - return ts.toText(); - }); - return this; - }, - /**5th -> 5 */ - toCardinal: function() { - this.list = this.list.map(ts => { - return ts.toCardinal(); - }); - return this; - }, - /**5 -> 5th */ - toOrdinal: function() { - this.list = this.list.map(ts => { - return ts.toOrdinal(); - }); - return this; - }, - /**5900 -> 5,900 */ - toNice: function() { - this.list = this.list.map(ts => { - return ts.toNice(); - }); - return this; - }, - /**seven === 7th */ - isEqual: function(num) { - num = parse(num); - this.list = this.list.filter(ts => { - return num !== null && ts.number() === num; - }); - return this; - }, - /**eight > 7th */ - greaterThan: function(num) { - num = parse(num); - this.list = this.list.filter(ts => { - return num !== null && ts.number() > num; - }); - return this; - }, - /**five < 7th */ - lessThan: function(num) { - num = parse(num); - this.list = this.list.filter(ts => { - return num !== null && ts.number() < num; - }); - return this; - }, - between: function(min, max) { - if (min === undefined || max === undefined) { - return this; - } - min = parse(min); - max = parse(max); - this.list = this.list.filter(ts => { - let n = ts.number(); - return n > min && n < max; - }); - return this; - }, - /**seven + 2 = 'nine' */ - add: function(n) { - this.list = this.list.map(ts => { - return ts.add(n); - }); - return this; - }, - /**seven - 2 = 'five' */ - subtract: function(n) { - this.list = this.list.map(ts => { - return ts.subtract(n); - }); - return this; - }, - /**seven -> 'eight' */ - increment: function() { - this.list = this.list.map(ts => { - return ts.add(1); - }); - return this; - }, - /**seven -> 'eight' */ - decrement: function() { - this.list = this.list.map(ts => { - return ts.subtract(1); - }); - return this; - } -}; - -const find = function(r, n) { - const tens = 'twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|fourty'; - const teens = 'eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen'; - r = r.match('#Value+ #Unit?'); - // r = r.match('#Value+ #Unit?'); - - //"50 83" - if (r.has('#NumericValue #NumericValue')) { - //a comma may mean two numbers - if (r.has('#Value #Comma #Value')) { - r.splitAfter('#Comma'); - } else { - r.splitAfter('#NumericValue'); - } - } - //three-length - if (r.has('#Value #Value #Value') && !r.has('#Multiple')) { - //twenty-five-twenty - if (r.has('(' + tens + ') #Cardinal #Cardinal')) { - r.splitAfter('(' + tens + ') #Cardinal'); - } - } - - //two-length ones - if (r.has('#Value #Value')) { - //june 21st 1992 is two seperate values - if (r.has('#NumericValue #NumericValue')) { - r.splitOn('#Year'); - } - //sixty fifteen - if (r.has('(' + tens + ') (' + teens + ')')) { - r.splitAfter('(' + tens + ')'); - } - //"72 82" - let double = r.match('#Cardinal #Cardinal'); - if (double.found && !r.has('(point|decimal)')) { - //not 'two hundred' - if (!double.has('#Cardinal (#Multiple|point|decimal)')) { - //one proper way, 'twenty one', or 'hundred one' - if (!double.has('(' + tens + ') #Cardinal') && !double.has('#Multiple #Value')) { - r.splitAfter(double.terms(0).out('normal')); - } - } - } - //seventh fifth - if (r.match('#Ordinal #Ordinal').match('#TextValue').found && !r.has('#Multiple')) { - //the one proper way, 'twenty first' - if (!r.has('(' + tens + ') #Ordinal')) { - r.splitAfter('#Ordinal'); - } - } - //fifth five - if (r.has('#Ordinal #Cardinal')) { - r.splitBefore('#Cardinal+'); - } - //five 2017 (support '5 hundred', and 'twenty 5' - if ( - r.has('#TextValue #NumericValue') && - !r.has('(' + tens + '|#Multiple)') - ) { - r.splitBefore('#NumericValue+'); - } - } - //5-8 - if (r.has('#NumberRange')) { - r.splitAfter('#NumberRange'); - } - if (typeof n === 'number') { - r = r.get(n); - } - let world = r.world(); - r.list = r.list.map(ts => { - return new Value(ts.terms, world, ts.refText, ts.refTerms); - }); - return r; -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/values/parse.js b/src/subset/values/parse.js deleted file mode 100644 index e85fbcc5b..000000000 --- a/src/subset/values/parse.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -const parseText = require('./parseText'); -// 2.5, $5.50, 3,432, etc - -const numeric = /^-?(\$|€|¥|£)?\.?[0-9]+[0-9,\.]*(st|nd|rd|th|rth|%)?$/; - -const parseString = function(str) { - if (numeric.test(str) === true) { - //clean up a number, like '$4,342.00' - str = str.replace(/,/g, ''); - str = str.replace(/^[\$|€|¥|£]/g, ''); - str = str.replace(/%$/, ''); - str = str.replace(/(st|nd|rd|th|rth)$/g, ''); - let num = parseFloat(str); - if (num || num === 0) { - return num; - } - } - return parseText(str); -}; - -//turn it all into a number -const parse = function(val) { - if (val === null || val === undefined || typeof val === 'number') { - return val; - } - if (typeof val === 'string') { - return parseString(val); - } - //numerical values can only be one term - if (val.terms.length === 1 && val.terms[0].tags.TextValue !== true) { - let str = val.terms[0].normal; - return parseString(str); - } - return parseText(val.out('normal')); -}; -module.exports = parse; diff --git a/src/subset/values/parseText/data.js b/src/subset/values/parseText/data.js deleted file mode 100644 index c794ffbf0..000000000 --- a/src/subset/values/parseText/data.js +++ /dev/null @@ -1,18 +0,0 @@ -const numbers = require('../../../world/more-data/numbers'); -const fns = require('../paths').fns; - -//setup number-word data -const ones = fns.extend(numbers.ordinal.ones, numbers.cardinal.ones); -const teens = fns.extend(numbers.ordinal.teens, numbers.cardinal.teens); -const tens = fns.extend(numbers.ordinal.tens, numbers.cardinal.tens); -const multiples = fns.extend(numbers.ordinal.multiples, numbers.cardinal.multiples); - -//add this one -multiples.grand = 1000; - -module.exports = { - ones: ones, - teens: teens, - tens: tens, - multiples: multiples -}; diff --git a/src/subset/values/parseText/index.js b/src/subset/values/parseText/index.js deleted file mode 100644 index 80dc91e67..000000000 --- a/src/subset/values/parseText/index.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; -const findModifiers = require('./findModifiers'); -const words = require('./data'); -const isValid = require('./validate'); -const parseDecimals = require('./parseDecimals'); -const parseNumeric = require('./parseNumeric'); -const improperFraction = /^([0-9,\. ]+)\/([0-9,\. ]+)$/; - -//some numbers we know -const casualForms = { - // 'a few': 3, - 'a couple': 2, - 'a dozen': 12, - 'two dozen': 24, - zero: 0 -}; - -// a 'section' is something like 'fifty-nine thousand' -// turn a section into something we can add to - like 59000 -const section_sum = obj => { - return Object.keys(obj).reduce((sum, k) => { - sum += obj[k]; - return sum; - }, 0); -}; - -//turn a string into a number -const parse = function(str) { - //convert some known-numbers - if (casualForms.hasOwnProperty(str) === true) { - return casualForms[str]; - } - //'a/an' is 1 - if (str === 'a' || str === 'an') { - return 1; - } - const modifier = findModifiers(str); - str = modifier.str; - let last_mult = null; - let has = {}; - let sum = 0; - let isNegative = false; - const terms = str.split(/[ -]/); - for (let i = 0; i < terms.length; i++) { - let w = terms[i]; - w = parseNumeric(w); - if (!w || w === 'and') { - continue; - } - if (w === '-' || w === 'negative') { - isNegative = true; - continue; - } - if (w.charAt(0) === '-') { - isNegative = true; - w = w.substr(1); - } - //decimal mode - if (w === 'point') { - sum += section_sum(has); - sum += parseDecimals(terms.slice(i + 1, terms.length)); - sum *= modifier.amount; - return sum; - } - //improper fraction - const fm = w.match(improperFraction); - if (fm) { - const num = parseFloat(fm[1].replace(/[, ]/g, '')); - const denom = parseFloat(fm[2].replace(/[, ]/g, '')); - if (denom) { - sum += num / denom || 0; - } - continue; - } - //prevent mismatched units, like 'seven eleven' - if (isValid(w, has) === false) { - return null; - } - //buildOut section, collect 'has' values - if (/^[0-9\.]+$/.test(w)) { - has['ones'] = parseFloat(w); //not technically right - } else if (words.ones.hasOwnProperty(w) === true) { - has['ones'] = words.ones[w]; - } else if (words.teens.hasOwnProperty(w) === true) { - has['teens'] = words.teens[w]; - } else if (words.tens.hasOwnProperty(w) === true) { - has['tens'] = words.tens[w]; - } else if (words.multiples.hasOwnProperty(w) === true) { - let mult = words.multiples[w]; - - //something has gone wrong : 'two hundred five hundred' - if (mult === last_mult) { - return null; - } - //support 'hundred thousand' - //this one is tricky.. - if (mult === 100 && terms[i + 1] !== undefined) { - // has['hundreds']= - const w2 = terms[i + 1]; - if (words.multiples[w2]) { - mult *= words.multiples[w2]; //hundredThousand/hundredMillion - i += 1; - } - } - //natural order of things - //five thousand, one hundred.. - if (last_mult === null || mult < last_mult) { - sum += (section_sum(has) || 1) * mult; - last_mult = mult; - has = {}; - } else { - //maybe hundred .. thousand - sum += section_sum(has); - last_mult = mult; - sum = (sum || 1) * mult; - has = {}; - } - } - } - //dump the remaining has values - sum += section_sum(has); - //post-process add modifier - sum *= modifier.amount; - sum *= isNegative ? -1 : 1; - //dont return 0, if it went straight-through - if (sum === 0 && Object.keys(has).length === 0) { - return null; - } - return sum; -}; - -module.exports = parse; diff --git a/src/subset/values/parseText/parseDecimals.js b/src/subset/values/parseText/parseDecimals.js deleted file mode 100644 index b2f071f47..000000000 --- a/src/subset/values/parseText/parseDecimals.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -const words = require('./data'); - -//concatenate into a string with leading '0.' -const parseDecimals = function(arr) { - let str = '0.'; - for (let i = 0; i < arr.length; i++) { - let w = arr[i]; - if (words.ones.hasOwnProperty(w) === true) { - str += words.ones[w]; - } else if (words.teens.hasOwnProperty(w) === true) { - str += words.teens[w]; - } else if (words.tens.hasOwnProperty(w) === true) { - str += words.tens[w]; - } else if (/^[0-9]$/.test(w) === true) { - str += w; - } else { - return 0; - } - } - return parseFloat(str); -}; - -module.exports = parseDecimals; diff --git a/src/subset/values/parseText/parseNumeric.js b/src/subset/values/parseText/parseNumeric.js deleted file mode 100644 index 232743fc4..000000000 --- a/src/subset/values/parseText/parseNumeric.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -//parse a string like "4,200.1" into Number 4200.1 -const parseNumeric = str => { - //remove ordinal - 'th/rd' - str = str.replace(/1st$/, '1'); - str = str.replace(/2nd$/, '2'); - str = str.replace(/3rd$/, '3'); - str = str.replace(/([4567890])r?th$/, '$1'); - //remove prefixes - str = str.replace(/^[$€¥£¢]/, ''); - //remove suffixes - str = str.replace(/[%$€¥£¢]$/, ''); - //remove commas - str = str.replace(/,/g, ''); - //split '5kg' from '5' - str = str.replace(/([0-9])([a-z]{1,2})$/, '$1'); - return str; -}; - -module.exports = parseNumeric; diff --git a/src/subset/values/parseText/validate.js b/src/subset/values/parseText/validate.js deleted file mode 100644 index ac8fbfcdb..000000000 --- a/src/subset/values/parseText/validate.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; -const words = require('./data'); - -//prevent things like 'fifteen ten', and 'five sixty' -const isValid = (w, has) => { - if (words.ones.hasOwnProperty(w)) { - if (has.ones || has.teens) { - return false; - } - } else if (words.teens.hasOwnProperty(w)) { - if (has.ones || has.teens || has.tens) { - return false; - } - } else if (words.tens.hasOwnProperty(w)) { - if (has.ones || has.teens || has.tens) { - return false; - } - } - return true; -}; -module.exports = isValid; diff --git a/src/subset/values/paths.js b/src/subset/values/paths.js deleted file mode 100644 index af7293c6a..000000000 --- a/src/subset/values/paths.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../../paths'); diff --git a/src/subset/values/value.js b/src/subset/values/value.js deleted file mode 100644 index b95f2b65f..000000000 --- a/src/subset/values/value.js +++ /dev/null @@ -1,245 +0,0 @@ -'use strict'; -const paths = require('../../paths'); -const Terms = paths.Terms; -const parse = require('./parse'); -const fmt = require('./format'); - -// const unpackRange = function(ts) { -// if (ts.has('#NumberRange')) { -// ts.terms.forEach(t => { -// if (t.silent_term && !t._text) { -// t.text = t.silent_term; -// } -// }); -// } -// return ts; -// }; - -const parseValue = function(ts) { - ts.val = ts.match('#Value+'); - // ts.val = unpackRange(ts.val); - ts.val = ts.val.list[0]; - ts.unit = ts.match('#Unit+'); - if (ts.unit.found) { - ts.unit = ts.unit.list[0]; - } - return ts; -}; - -const isPercent = function(val, unit) { - //pre-tagged - if (val.has('#Percent') || unit.has('#Percent')) { - return true; - } - // 'five percent' - if (unit.out('normal') === 'percent') { - return true; - } - //'5%' - if (val.out('normal').match(/%$/) !== null) { - return true; - } - return false; -}; - -//set the text as the same num format -const setNumber = function(ts, num) { - let str = ts.val.out(); - if (ts.has('#Ordinal')) { - if (ts.has('#TextValue')) { - str = fmt.textOrdinal(num); //ordinal text - } else { - str = fmt.ordinal(num); //ordinal number - } - } else if (ts.has('#TextValue')) { - str = fmt.text(num); //cardinal text - } else if (ts.has('#NiceNumber')) { - str = fmt.nice(num); //8,929 number - } else { - str = fmt.cardinal(num); //cardinal number - } - //add the unit at the end - if (ts.unit.found) { - str += ts.unit.out('text'); - } - ts = ts.replaceWith(str, true); - return parseValue(ts); -}; - -const Value = function(arr, world, refText, refTerms) { - Terms.call(this, arr, world, refText, refTerms); - parseValue(this); -}; - -//Terms inheritence -Value.prototype = Object.create(Terms.prototype); - -const methods = { - data: function() { - let num = parse(this.val); - return { - number: num, - nice: fmt.nice(num), - ordinal: fmt.ordinal(num), - niceOrdinal: fmt.niceOrdinal(num), - text: fmt.text(num), - textOrdinal: fmt.textOrdinal(num), - unit: this.unit.out('normal') - }; - }, - number: function() { - return parse(this.val); - }, - // /** five -> '5' */ - toNumber: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#Ordinal')) { - str = fmt.ordinal(num); - } else { - str = String(num); - //convert 'five percent' -> '5%' - if (isPercent(this.val, this.unit)) { - str = str + '%'; - this.unit.delete(); - } - } - // let before = this.terms[0].whitespace.before; - // let after = this.terms[this.terms.length - 1].whitespace.after; - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('NumericValue'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - // this.whitespace.before(before); - // this.whitespace.after(after); - } - return this; - }, - // /**5 -> 'five' */ - toText: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#Ordinal')) { - str = fmt.textOrdinal(num); - } else { - str = fmt.text(num); - //add percent - if (isPercent(this.val, this.unit)) { - str = str + ' percent'; - } - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('TextValue'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5th -> 5 */ - toCardinal: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#TextValue')) { - str = fmt.text(num); - } else { - str = num; - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('Cardinal'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5 -> 5th */ - toOrdinal: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#TextValue')) { - str = fmt.textOrdinal(num); - } else { - str = fmt.ordinal(num); - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('Ordinal'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - // - // /**5900 -> 5,900 */ - toNice: function() { - let num = parse(this.val); - if (num || num === 0) { - let str = ''; - if (this.val.has('#Ordinal')) { - str = fmt.niceOrdinal(num); - } else { - str = fmt.nice(num); - } - if (this.unit.found) { - str = str + this.unit.out('text'); - } - this.replaceWith(str, true).tag('NumericValue'); - //make sure unit gets the right tag.. - if (this.unit.found) { - this.match(this.unit.out('normal')).tag('Unit'); - } - } - return this; - }, - /** seven + 2 = nine */ - add: function(n) { - if (!n) { - return this; - } - let num = parse(this.val) || 0; - num += n; //add it - return setNumber(this, num); - }, - /** seven - 2 = five */ - subtract: function(n) { - if (!n) { - return this; - } - let num = parse(this.val) || 0; - num -= n; //subtract it - return setNumber(this, num); - }, - /**seven -> 'eight' */ - increment: function() { - return this.add(1); - }, - /**seven -> 'six' */ - decrement: function() { - return this.subtract(1); - } -}; - -Object.keys(methods).forEach(k => { - Value.prototype[k] = methods[k]; -}); -module.exports = Value; diff --git a/src/subset/verbs/index.js b/src/subset/verbs/index.js deleted file mode 100644 index b944597e5..000000000 --- a/src/subset/verbs/index.js +++ /dev/null @@ -1,121 +0,0 @@ -'use strict'; -const Text = require('../../text'); -const Verb = require('./verb'); - -//the () subset class -const methods = { - conjugation: function(verbose) { - return this.list.map(ts => { - return ts.conjugation(verbose); - }); - }, - conjugate: function(num, verbose) { - //suppport only conjugating one verb in our result.. - if (num !== null && typeof num === 'number' && this.list[num]) { - return this.list[num].conjugate(verbose); - } - //otherwise, return an array of conjugations - return this.list.map(ts => { - return ts.conjugate(verbose); - }); - }, - - /** plural/singular **/ - isPlural: function() { - this.list = this.list.filter(ts => { - return ts.isPlural(); - }); - return this; - }, - isSingular: function() { - this.list = this.list.filter(ts => { - return !ts.isPlural(); - }); - return this; - }, - - /** negation **/ - isNegative: function() { - this.list = this.list.filter(ts => { - return ts.isNegative(); - }); - return this; - }, - isPositive: function() { - this.list = this.list.filter(ts => { - return !ts.isNegative(); - }); - return this; - }, - toNegative: function() { - this.list = this.list.map(ts => { - return ts.toNegative(); - }); - return this; - }, - toPositive: function() { - this.list.forEach(ts => { - ts.toPositive(); - }); - return this; - }, - - /** tense **/ - toPastTense: function() { - this.list.forEach(ts => { - ts.toPastTense(); - }); - return this; - }, - toPresentTense: function() { - this.list.forEach(ts => { - ts.toPresentTense(); - }); - return this; - }, - toFutureTense: function() { - this.list.forEach(ts => { - ts.toFutureTense(); - }); - return this; - }, - toInfinitive: function() { - this.list.forEach(ts => { - ts.toInfinitive(); - }); - return this; - }, - toGerund: function() { - this.list.forEach(ts => { - ts.toGerund(); - }); - return this; - }, - asAdjective: function() { - return this.list.map(ts => ts.asAdjective()); - } -}; -//aliases -methods.toContinuous = methods.toGerund; - -const find = function(r, n) { - r = r.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); - r = r.splitAfter('#Comma'); - r.list.forEach(ts => { - ts.terms.forEach( t => { - if(t.whitespace.before.match('/')){ - r.splitOn(t.normal) - } - }) - }) - r = r.if('#Verb'); //this should be (much) smarter - if (typeof n === 'number') { - r = r.get(n); - } - r.list = r.list.map(ts => { - return new Verb(ts.terms, ts.world, ts.refText, ts.refTerms); - }); - return new Text(r.list, this.world, this.parent); -}; - -module.exports = Text.makeSubset(methods, find); diff --git a/src/subset/verbs/interpret.js b/src/subset/verbs/interpret.js deleted file mode 100644 index 949eb0b93..000000000 --- a/src/subset/verbs/interpret.js +++ /dev/null @@ -1,102 +0,0 @@ -'use strict'; -const predict = require('./methods/predict'); -const isPlural = require('./methods/isPlural'); - -//'walking' - aka progressive -const isContinuous = function(ts) { - return ts.match('#Gerund').found; -}; - -//will not walk -const isNegative = function(ts) { - let negs = ts.match('#Negative').list; - if (negs.length === 2) { - return false; - } - if (negs.length === 1) { - return true; - } - return false; -}; - -//been walked by.. -const isPassive = function(ts) { - if (ts.match('is being #PastTense').found) { - return true; - } - if (ts.match('(had|has) been #PastTense').found) { - return true; - } - if (ts.match('will have been #PastTense').found) { - return true; - } - return false; -}; - -//had walked -const isPerfect = function(ts) { - if (ts.match('^(had|have) #PastTense')) { - return true; - } - return false; -}; - -//should walk, could walk -const getModal = function(ts) { - let modal = ts.match('#Modal'); - if (!modal.found) { - return null; - } - return modal.out('normal'); -}; - -//past/present/future -const getTense = function(ts) { - //look at the preceding words - if (ts.auxiliary.found) { - //'will' - if (ts.match('will have #PastTense').found) { - return 'Past'; - } - if (ts.auxiliary.match('will').found) { - return 'Future'; - } - //'was' - if (ts.auxiliary.match('was').found) { - return 'Past'; - } - } - //look at the main verb tense - if (ts.verb) { - const tenses = { - PastTense: 'Past', - FutureTense: 'Future', - FuturePerfect: 'Future', - }; - let tense = predict(ts.verb); //yikes - return tenses[tense] || 'Present'; - } - return 'Present'; -}; - -// const isImperative = function(ts) {}; -// const isConditional = function(ts) {}; - -// detect signals in Auxiliary verbs -// 'will' -> future, 'have'->perfect, modals, negatives, adverbs -const interpret = (ts) => { - let isNeg = isNegative(ts); - // let aux = ts.Auxiliary.clone(); - // aux = aux.not('(#Negative|#Adverb)'); - let obj = { - negative: isNeg, - continuous: isContinuous(ts), - passive: isPassive(ts), - perfect: isPerfect(ts), - plural: isPlural(ts), - modal: getModal(ts), - tense: getTense(ts), - }; - return obj; -}; -module.exports = interpret; diff --git a/src/subset/verbs/methods/conjugate/conjugate.js b/src/subset/verbs/methods/conjugate/conjugate.js deleted file mode 100644 index 1ddc7d7db..000000000 --- a/src/subset/verbs/methods/conjugate/conjugate.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; -const checkIrregulars = require('./irregulars'); -const suffixPass = require('./suffixes'); -const toActor = require('./toActor'); -const generic = require('./generic'); -const predict = require('../predict'); -const toInfinitive = require('../toInfinitive'); -const toBe = require('./toBe'); - -//turn a verb into all it's forms -const conjugate = function(t, world) { - //handle is/was/will-be specially - if (t.normal === 'is' || t.normal === 'was' || t.normal === 'will') { - return toBe(); - } - - //dont conjugate didn't - if (t.tags.Contraction) { - t.text = t.silent_term; - } - let all = { - PastTense: null, - PresentTense: null, - Infinitive: null, - Gerund: null, - Actor: null - }; - //first, get its current form - let form = predict(t); - if (form) { - all[form] = t.normal; - } - if (form !== 'Infinitive') { - all['Infinitive'] = toInfinitive(t, world) || ''; - } - //check irregular forms - const irregObj = checkIrregulars(all['Infinitive'], world) || {}; - Object.keys(irregObj).forEach(k => { - if (irregObj[k] && !all[k]) { - all[k] = irregObj[k]; - } - }); - //ok, send this infinitive to all conjugators - let inf = all['Infinitive'] || t.normal; - - //check suffix rules - const suffObj = suffixPass(inf); - Object.keys(suffObj).forEach(k => { - if (suffObj[k] && !all[k]) { - all[k] = suffObj[k]; - } - }); - //ad-hoc each missing form - //to Actor - if (!all.Actor) { - all.Actor = toActor(inf); - } - - //use fallback, generic transformations - Object.keys(all).forEach(k => { - if (!all[k] && generic[k]) { - all[k] = generic[k](all); - } - }); - - return all; -}; - -module.exports = conjugate; diff --git a/src/subset/verbs/methods/conjugate/data/rules.js b/src/subset/verbs/methods/conjugate/data/rules.js deleted file mode 100644 index 13fe2756c..000000000 --- a/src/subset/verbs/methods/conjugate/data/rules.js +++ /dev/null @@ -1,202 +0,0 @@ -module.exports = [ - { - reg: /(eave)$/i, - repl: { - pr: '$1s', - pa: '$1d', - gr: 'eaving', - ar: '$1r' - } - }, - { - reg: /(ink)$/i, - repl: { - pr: '$1s', - pa: 'unk', - gr: '$1ing', - ar: '$1er' - } - }, - { - reg: /([aeiou]k)in$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing', - ar: '$1er' - } - }, - { - reg: /(end)$/i, - repl: { - pr: '$1s', - pa: 'ent', - gr: '$1ing', - ar: '$1er' - } - }, - { - reg: /(ide)$/i, - repl: { - pr: '$1s', - pa: 'ode', - gr: 'iding', - ar: 'ider' - } - }, - { - reg: /(ake)$/i, - repl: { - pr: '$1s', - pa: 'ook', - gr: 'aking', - ar: '$1r' - } - }, - { - reg: /(eed)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing', - ar: '$1er' - } - }, - - { - reg: /(e)(ep)$/i, - repl: { - pr: '$1$2s', - pa: '$1pt', - gr: '$1$2ing', - ar: '$1$2er' - } - }, { - reg: /(a[tg]|i[zn]|ur|nc|gl|is)e$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing', - prt: '$1en' - } - }, { - reg: /([i|f|rr])y$/i, - repl: { - pr: '$1ies', - pa: '$1ied', - gr: '$1ying' - } - }, { - reg: /([td]er)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /([bd]l)e$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(ish|tch|ess)$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(ion|end|e[nc]t)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(om)e$/i, - repl: { - pr: '$1es', - pa: 'ame', - gr: '$1ing' - } - }, { - reg: /(.eat)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /([aeiu])([pt])$/i, - repl: { - pr: '$1$2s', - pa: '$1$2', - gr: '$1$2$2ing' - } - }, { - reg: /(er)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - } - }, { - reg: /(en)$/i, - repl: { - pr: '$1s', - pa: '$1ed', - gr: '$1ing' - }, - }, { - reg: /(ed)$/i, - repl: { - pr: '$1s', - pa: '$1ded', - ar: '$1der', - gr: '$1ding' - }, - }, - { - reg: /(..)(ow)$/i, - repl: { - pr: '$1$2s', - pa: '$1ew', - gr: '$1$2ing', - prt: '$1$2n' - } - }, - { - reg: /(..)([cs]h)$/i, - repl: { - pr: '$1$2es', - pa: '$1$2ed', - gr: '$1$2ing' - }, - }, - { - reg: /([^aeiou][ou])(g|d)$/i, - repl: { - pr: '$1$2s', - pa: '$1$2$2ed', - gr: '$1$2$2ing' - }, - }, - { - reg: /([^aeiou][aeiou])(b|t|p|m)$/i, - repl: { - pr: '$1$2s', - pa: '$1$2$2ed', - gr: '$1$2$2ing' - }, - }, - { - reg: /([aeiou]zz)$/i, - repl: { - pr: '$1es', - pa: '$1ed', - gr: '$1ing' - } - } -]; diff --git a/src/subset/verbs/methods/conjugate/faster.js b/src/subset/verbs/methods/conjugate/faster.js deleted file mode 100644 index 9681950ae..000000000 --- a/src/subset/verbs/methods/conjugate/faster.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; -const checkIrregulars = require('./irregulars'); -const suffixPass = require('./suffixes'); -const generic = require('./generic'); -//this method is the same as regular conjugate, but optimised for use in the lexicon during warm-up. -//it's way faster because it knows input is already infinitive - -const want = ['Gerund', 'PastTense', 'PresentTense']; - -const fasterConjugate = function(inf, world) { - let all = { - Infinitive: inf - }; - //check irregulars list - if (world && world.conjugations) { - const irregObj = checkIrregulars(all['Infinitive'], world); - if (irregObj !== null) { - Object.keys(irregObj).forEach(k => { - if (irregObj[k] && !all[k]) { - all[k] = irregObj[k]; - } - }); - } - } - //check suffix rules - const suffObj = suffixPass(inf); - Object.keys(suffObj).forEach(k => { - if (suffObj[k] && !all[k]) { - all[k] = suffObj[k]; - } - }); - for (let i = 0; i < want.length; i++) { - if (all[want[i]] === undefined) { - all[want[i]] = generic[want[i]](all); - } - } - return all; -}; -module.exports = fasterConjugate; -// console.log(fasterConjugate('repeat')); diff --git a/src/subset/verbs/methods/conjugate/generic.js b/src/subset/verbs/methods/conjugate/generic.js deleted file mode 100644 index 7ac235821..000000000 --- a/src/subset/verbs/methods/conjugate/generic.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; -//non-specifc, 'hail-mary' transforms from infinitive, into other forms -const hasY = /[bcdfghjklmnpqrstvwxz]y$/; -const generic = { - - Gerund: (o) => { - const inf = o.Infinitive; - if (inf.charAt(inf.length - 1) === 'e') { - return inf.replace(/e$/, 'ing'); - } - return inf + 'ing'; - }, - - PresentTense: (o) => { - const inf = o.Infinitive; - if (inf.charAt(inf.length - 1) === 's') { - return inf + 'es'; - } - if (hasY.test(inf) === true) { - return inf.slice(0, -1) + 'ies'; - } - return inf + 's'; - }, - - PastTense: (o) => { - const inf = o.Infinitive; - if (inf.charAt(inf.length - 1) === 'e') { - return inf + 'd'; - } - if (inf.substr(-2) === 'ed') { - return inf; - } - if (hasY.test(inf) === true) { - return inf.slice(0, -1) + 'ied'; - } - return inf + 'ed'; - }, - - // FutureTense: (o) => { - // return 'will ' + o.Infinitive; - // }, - // - // PerfectTense: (o) => { - // return 'have ' + (o.Participle || o.PastTense); - // }, - // - // Pluperfect: (o) => { - // if (o.PastTense) { - // return 'had ' + o.PastTense; - // } - // return null; - // }, - // FuturePerfect: (o) => { - // if (o.PastTense) { - // return 'will have ' + o.PastTense; - // } - // return null; - // } - -}; - -module.exports = generic; diff --git a/src/subset/verbs/methods/conjugate/index.js b/src/subset/verbs/methods/conjugate/index.js deleted file mode 100644 index 817ae361a..000000000 --- a/src/subset/verbs/methods/conjugate/index.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; -const conjugate = require('./conjugate'); -const toBe = require('./toBe'); - -const addAdverbs = function(obj, vb) { - if (vb.adverbs.found) { - //does the adverb go at the start or end? - let isFirst = vb.first().match('#Adverb').found; - Object.keys(obj).forEach(k => { - if (isFirst) { - obj[k] = vb.adverbs.out() + ' ' + obj[k]; - } else { - obj[k] = obj[k] + vb.adverbs.out(); - } - }); - } - return obj; -}; - -//conjugation using auxillaries+adverbs and stuff -const multiWordConjugate = (vb, verbose) => { - let isNegative = vb.negative.found; - let isPlural = vb.isPlural(); - //handle 'to be' verb seperately - if (vb.verb.tags.Copula || (vb.verb.normal === 'be' && vb.auxiliary.match('will').found)) { - let isI = false; - //account for 'i is' -> 'i am' irregular - if (vb.parent && vb.parent.has('i #Adverb? #Copula')) { - isI = true; - } - let copulas = toBe(isPlural, isNegative, isI); - return addAdverbs(copulas, vb); - } - let obj = conjugate(vb.verb, vb.world, verbose); - //apply particles - if (vb.particle.found) { - Object.keys(obj).forEach(k => { - obj[k] = obj[k] + vb.particle.out(); - }); - } - //apply negative - if (isNegative) { - obj.PastTense = 'did not ' + obj.Infinitive; - obj.PresentTense = 'does not ' + obj.Infinitive; - obj.Gerund = 'not ' + obj.Gerund; - } - //future Tense is pretty straightforward - if (!obj.FutureTense) { - if (isNegative) { - obj.FutureTense = 'will not ' + obj.Infinitive; - } else { - obj.FutureTense = 'will ' + obj.Infinitive; - } - } - //apply adverbs - obj = addAdverbs(obj, vb); - return obj; -}; -module.exports = multiWordConjugate; diff --git a/src/subset/verbs/methods/conjugate/irregulars.js b/src/subset/verbs/methods/conjugate/irregulars.js deleted file mode 100644 index 797e304dd..000000000 --- a/src/subset/verbs/methods/conjugate/irregulars.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; -// let irregulars = require('../../../../lexicon/uncompressed/irregularVerbs').irregulars; //weeee! -const fns = require('../../../../fns'); //weeee! -const forms = ['Participle', 'Gerund', 'PastTense', 'PresentTense', 'FuturePerfect', 'PerfectTense', 'Actor']; - -const checkIrregulars = function(str, world) { - const irregulars = world.conjugations; - const infArr = Object.keys(irregulars); - //check irregulars in world - if (world && world.conjugations && world.conjugations.hasOwnProperty(str) === true) { - return world.conjugations[str]; - } - //fast infinitive lookup - if (irregulars.hasOwnProperty(str) === true) { - let obj = fns.copy(irregulars[str]); - obj.Infinitive = str; - return obj; - } - //longer check of known-verb forms - for (let i = 0; i < infArr.length; i++) { - for (let o = 0; o < forms.length; o++) { - let irObj = irregulars[infArr[i]]; - if (irObj[forms[o]] === str) { - let obj = fns.copy(irObj); - obj.Infinitive = infArr[i]; - return obj; - } - } - } - return {}; -}; - -module.exports = checkIrregulars; -// console.log(checkIrregulars('bit')); diff --git a/src/subset/verbs/methods/conjugate/suffixes.js b/src/subset/verbs/methods/conjugate/suffixes.js deleted file mode 100644 index c46483d40..000000000 --- a/src/subset/verbs/methods/conjugate/suffixes.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -const rules = require('./data/rules'); -const mapping = { - pr: 'PresentTense', - pa: 'PastTense', - gr: 'Gerund', - prt: 'Participle', - ar: 'Actor', -}; -const keys = Object.keys(mapping); - -//check suffix rules -const suffixPass = function(inf) { - let found = {}; - for(let i = 0; i < rules.length; i++) { - if (rules[i].reg.test(inf) === true) { - let obj = rules[i].repl; - for(let o = 0; o < keys.length; o++) { - if (obj.hasOwnProperty(keys[o]) === true) { - let key = mapping[keys[o]]; - // console.log(rules[i]); - found[key] = inf.replace(rules[i].reg, obj[keys[o]]); - } - } - return found; - } - } - return found; -}; - -module.exports = suffixPass; diff --git a/src/subset/verbs/methods/conjugate/toActor.js b/src/subset/verbs/methods/conjugate/toActor.js deleted file mode 100644 index 7662afa00..000000000 --- a/src/subset/verbs/methods/conjugate/toActor.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; -//turn 'walk' into 'walker' -const irregulars = { - 'tie': 'tier', - 'dream': 'dreamer', - 'sail': 'sailer', - 'run': 'runner', - 'rub': 'rubber', - 'begin': 'beginner', - 'win': 'winner', - 'claim': 'claimant', - 'deal': 'dealer', - 'spin': 'spinner' -}; -const dont = { - 'aid': 1, - 'fail': 1, - 'appear': 1, - 'happen': 1, - 'seem': 1, - 'try': 1, - 'say': 1, - 'marry': 1, - 'be': 1, - 'forbid': 1, - 'understand': 1, - 'bet': 1 -}; -const rules = [{ - 'reg': /e$/i, - 'repl': 'er' -}, { - 'reg': /([aeiou])([mlgp])$/i, - 'repl': '$1$2$2er' -}, { - 'reg': /([rlf])y$/i, - 'repl': '$1ier' -}, { - 'reg': /^(.?.[aeiou])t$/i, - 'repl': '$1tter' -}]; - -const toActor = function(inf) { - //check blacklist - if (dont[inf]) { - return null; - } - //check irregulars - if (irregulars.hasOwnProperty(inf)) { - return irregulars[inf]; - } - //try rules - for (let i = 0; i < rules.length; i++) { - if (rules[i].reg.test(inf) === true) { - return inf.replace(rules[i].reg, rules[i].repl); - } - } - //yup, - return inf + 'er'; -}; - -module.exports = toActor; diff --git a/src/subset/verbs/methods/conjugate/toBe.js b/src/subset/verbs/methods/conjugate/toBe.js deleted file mode 100644 index 574f9d7c7..000000000 --- a/src/subset/verbs/methods/conjugate/toBe.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; -//too many special cases for is/was/will be -const toBe = (isPlural, isNegative, isI) => { - let obj = { - PastTense: 'was', - PresentTense: 'is', - FutureTense: 'will be', - Infinitive: 'is', - Gerund: 'being', - Actor: '', - PerfectTense: 'been', - Pluperfect: 'been', - }; - //"i is" -> "i am" - if (isI === true) { - obj.PresentTense = 'am'; - obj.Infinitive = 'am'; - } - if (isPlural) { - obj.PastTense = 'were'; - obj.PresentTense = 'are'; - obj.Infinitive = 'are'; - } - if (isNegative) { - obj.PastTense += ' not'; - obj.PresentTense += ' not'; - obj.FutureTense = 'will not be'; - obj.Infinitive += ' not'; - obj.PerfectTense = 'not ' + obj.PerfectTense; - obj.Pluperfect = 'not ' + obj.Pluperfect; - obj.Gerund = 'not ' + obj.Gerund; - } - return obj; -}; -module.exports = toBe; diff --git a/src/subset/verbs/methods/isPlural.js b/src/subset/verbs/methods/isPlural.js deleted file mode 100644 index 14e70e932..000000000 --- a/src/subset/verbs/methods/isPlural.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -//sometimes you can tell if a verb is plural/singular, just by the verb -// i am / we were -//othertimes you need its noun 'we walk' vs 'i walk' -const isPlural = (vb) => { - if (vb.match('(are|were|does)').found) { - return true; - } - if (vb.match('(is|am|do|was)').found) { - return false; - } - //consider its prior noun - let noun = vb.getNoun(); - if (noun && noun.found) { - if (noun.match('#Plural').found) { - return true; - } - if (noun.match('#Singular').found) { - return false; - } - } - return null; -}; -module.exports = isPlural; diff --git a/src/subset/verbs/methods/paths.js b/src/subset/verbs/methods/paths.js deleted file mode 100644 index da9b0cd6a..000000000 --- a/src/subset/verbs/methods/paths.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../../../paths'); diff --git a/src/subset/verbs/methods/predict/index.js b/src/subset/verbs/methods/predict/index.js deleted file mode 100644 index f7a499c2d..000000000 --- a/src/subset/verbs/methods/predict/index.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; -const suffix_rules = require('./suffix_rules'); - -const goodTypes = { - Infinitive: true, - Gerund: true, - PastTense: true, - PresentTense: true, - FutureTense: true, - PerfectTense: true, - Pluperfect: true, - FuturePerfect: true, - Participle: true -}; - -const predictForm = function(term) { - //do we already know the form? - const keys = Object.keys(goodTypes); - for (let i = 0; i < keys.length; i++) { - if (term.tags[keys[i]]) { - return keys[i]; - } - } - //consult our handy suffix rules - const arr = Object.keys(suffix_rules); - for (let i = 0; i < arr.length; i++) { - const substr = term.normal.substr(-arr[i].length); - if (substr === arr[i] && term.normal.length > arr[i].length) { - return suffix_rules[arr[i]]; - } - } - return null; -}; - -module.exports = predictForm; diff --git a/src/subset/verbs/methods/predict/suffix_rules.js b/src/subset/verbs/methods/predict/suffix_rules.js deleted file mode 100644 index 28084ce6e..000000000 --- a/src/subset/verbs/methods/predict/suffix_rules.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; -//suffix signals for verb tense, generated from test data -const compact = { - 'Gerund': [ - 'ing' - ], - 'Actor': [ - 'erer' - ], - 'Infinitive': [ - 'ate', - 'ize', - 'tion', - 'rify', - 'then', - 'ress', - 'ify', - 'age', - 'nce', - 'ect', - 'ise', - 'ine', - 'ish', - 'ace', - 'ash', - 'ure', - 'tch', - 'end', - 'ack', - 'and', - 'ute', - 'ade', - 'ock', - 'ite', - 'ase', - 'ose', - 'use', - 'ive', - 'int', - 'nge', - 'lay', - 'est', - 'ain', - 'ant', - 'ent', - 'eed', - 'er', - 'le', - 'own', - 'unk', - 'ung', - 'en' - ], - 'PastTense': [ - 'ed', - 'lt', - 'nt', - 'pt', - 'ew', - 'ld' - ], - 'PresentTense': [ - 'rks', - 'cks', - 'nks', - 'ngs', - 'mps', - 'tes', - 'zes', - 'ers', - 'les', - 'acks', - 'ends', - 'ands', - 'ocks', - 'lays', - 'eads', - 'lls', - 'els', - 'ils', - 'ows', - 'nds', - 'ays', - 'ams', - 'ars', - 'ops', - 'ffs', - 'als', - 'urs', - 'lds', - 'ews', - 'ips', - 'es', - 'ts', - 'ns', - 's' - ] -}; -const suffix_rules = {}; -const keys = Object.keys(compact); -const l = keys.length; - -for (let i = 0; i < l; i++) { - let l2 = compact[keys[i]].length; - for (let o = 0; o < l2; o++) { - suffix_rules[compact[keys[i]][o]] = keys[i]; - } -} -module.exports = suffix_rules; diff --git a/src/subset/verbs/methods/toAdjective/index.js b/src/subset/verbs/methods/toAdjective/index.js deleted file mode 100644 index 81d9a11c4..000000000 --- a/src/subset/verbs/methods/toAdjective/index.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; -//turn a infinitiveVerb, like "walk" into an adjective like "walkable" - -const rules = [ - [/y$/, 'i'], //relay - reliable - [/([aeiou][n])$/, '$1n'], //win - winnable -]; - -//convert - 'convertible' -//http://grammarist.com/usage/able-ible/ -//http://blog.oxforddictionaries.com/2012/10/ibles-and-ables/ -const ible_suffixes = { - collect: true, - exhaust: true, - convert: true, - digest: true, - discern: true, - dismiss: true, - reverse: true, - access: true, - collapse: true, - express: true -}; - -const irregulars = { - eat: 'edible', - hear: 'audible', - see: 'visible', - defend: 'defensible', - write: 'legible', - move: 'movable', - divide: 'divisible', - perceive: 'perceptible' -}; - -//takes an infitive verb, and returns an adjective form -const toAdjective = function(str) { - if (irregulars.hasOwnProperty(str)) { - return irregulars[str]; - } - for(let i = 0; i < rules.length; i++) { - if (rules[i][0].test(str) === true) { - str = str.replace(rules[i][0], rules[i][1]); - } - } - //ible/able - let adj = str + 'able'; - if (ible_suffixes[str]) { - adj = str + 'ible'; - } - return adj; -}; - -module.exports = toAdjective; diff --git a/src/subset/verbs/methods/toInfinitive/index.js b/src/subset/verbs/methods/toInfinitive/index.js deleted file mode 100644 index f31db1ee8..000000000 --- a/src/subset/verbs/methods/toInfinitive/index.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; -//turn any verb into its infinitive form -const rules = require('./rules'); -const predict = require('../predict'); - -const toInfinitive = function(t, world) { - const irregulars = world.cache.toInfinitive || {}; //verb_mapping(world.conjugations); //TODO: do this at world cache - if (t.tags.Infinitive) { - return t.normal; - } - //check the irregular verb conjugations - if (irregulars.hasOwnProperty(t.normal) === true) { - return irregulars[t.normal]; - } - //check the suffix rules - let form = predict(t); - if (rules[form]) { - for (let i = 0; i < rules[form].length; i++) { - let rule = rules[form][i]; - if (t.normal.match(rule.reg)) { - return t.normal.replace(rule.reg, rule.to); - } - } - } - return t.normal; -}; - -module.exports = toInfinitive; diff --git a/src/subset/verbs/methods/toInfinitive/rules.js b/src/subset/verbs/methods/toInfinitive/rules.js deleted file mode 100644 index 11fce7ea8..000000000 --- a/src/subset/verbs/methods/toInfinitive/rules.js +++ /dev/null @@ -1,177 +0,0 @@ -'use strict'; -//rules for turning a verb into infinitive form -let rules = { - Participle: [ - { - reg: /own$/i, - to: 'ow' - }, - { - reg: /(.)un([g|k])$/i, - to: '$1in$2' - } - ], - Actor: [ - { - reg: /(er)er$/i, - to: '$1' - } - ], - PresentTense: [ - { - reg: /(..)(ies)$/i, - to: '$1y' - }, { - reg: /(tch|sh)es$/i, - to: '$1' - }, { - reg: /(ss|zz)es$/i, - to: '$1' - }, { - reg: /([tzlshicgrvdnkmu])es$/i, - to: '$1e' - }, { - reg: /(n[dtk]|c[kt]|[eo]n|i[nl]|er|a[ytrl])s$/i, - to: '$1' - }, { - reg: /(ow)s$/i, - to: '$1' - }, { - reg: /(op)s$/i, - to: '$1' - }, { - reg: /([eirs])ts$/i, - to: '$1t' - }, { - reg: /(ll)s$/i, - to: '$1' - }, { - reg: /(el)s$/i, - to: '$1' - }, { - reg: /(ip)es$/i, - to: '$1e' - }, { - reg: /ss$/i, - to: 'ss' - }, { - reg: /s$/i, - to: '' - }], - Gerund: [ - { - reg: /pping$/i, - to: 'p' - }, { - reg: /lling$/i, - to: 'll' - }, { - reg: /tting$/i, - to: 't' - }, { - reg: /dding$/i, - to: 'd' - }, { - reg: /ssing$/i, - to: 'ss' - }, { - reg: /(..)gging$/i, - to: '$1g' - }, { - reg: /([^aeiou])ying$/i, - to: '$1y' - }, { - reg: /([^ae]i.)ing$/i, - to: '$1e' - }, { - reg: /(ea.)ing$/i, - to: '$1' - }, { - reg: /(u[rtcb]|[bdtpkg]l|n[cg]|a[gdkvtc]|[ua]s|[dr]g|yz|o[rlsp]|cre)ing$/i, - to: '$1e' - }, { - reg: /(ch|sh)ing$/i, - to: '$1' - }, { - reg: /(..)ing$/i, - to: '$1' - }], - PastTense: [ - { - reg: /(ued)$/i, - to: 'ue' - }, { - reg: /a([^aeiouy])ed$/i, - to: 'a$1e' - }, { - reg: /([aeiou]zz)ed$/i, - to: '$1' - }, { - reg: /(e|i)lled$/i, - to: '$1ll' - }, { - reg: /(.)(sh|ch)ed$/i, - to: '$1$2' - }, { - reg: /(tl|gl)ed$/i, - to: '$1e' - }, { - reg: /(um?pt?)ed$/i, - to: '$1' - }, { - reg: /(ss)ed$/i, - to: '$1' - }, { - reg: /pped$/i, - to: 'p' - }, { - reg: /tted$/i, - to: 't' - }, { - reg: /(..)gged$/i, - to: '$1g' - }, { - reg: /(..)lked$/i, - to: '$1lk' - }, { - reg: /([^aeiouy][aeiou])ked$/i, - to: '$1ke' - }, { - reg: /(.[aeiou])led$/i, - to: '$1l' - }, { - reg: /(..)(h|ion|n[dt]|ai.|[cs]t|pp|all|ss|tt|int|ail|ld|en|oo.|er|k|pp|w|ou.|rt|ght|rm)ed$/i, - to: '$1$2' - }, { - reg: /(.ut)ed$/i, - to: '$1e' - }, { - reg: /(.pt)ed$/i, - to: '$1' - }, { - reg: /(us)ed$/i, - to: '$1e' - }, { - reg: /(..[^aeiouy])ed$/i, - to: '$1e' - }, { - reg: /(..)ied$/i, - to: '$1y' - }, { - reg: /(.o)ed$/i, - to: '$1o' - }, { - reg: /(..i)ed$/i, - to: '$1' - }, { - reg: /(.a[^aeiou])ed$/i, - to: '$1' - }, { - reg: /([rl])ew$/i, - to: '$1ow' - }, { - reg: /([pl])t$/i, - to: '$1t' - }] -}; -module.exports = rules; diff --git a/src/subset/verbs/methods/verbContraction.js b/src/subset/verbs/methods/verbContraction.js deleted file mode 100644 index f03a2cfa6..000000000 --- a/src/subset/verbs/methods/verbContraction.js +++ /dev/null @@ -1,25 +0,0 @@ -//these are contractions with a implicit verb. -const expand = function(vb) { - vb.match('#Contraction+').list.forEach((ts) => { - if (ts.has('#Verb')) { - ts.terms.forEach((t) => { - if (t.silent_term) { - //this term also needs a space now too - if (!t.text) { - t.whitespace.before = ' '; - } - t._text = t.silent_term; - //handle (some) capitalization - if (t.tags.TitleCase) { - t.toTitleCase(); - } - t.normalize(); - t.silent_term = null; - t.unTag('Contraction', 'expanded'); - } - }); - } - }); - return vb; -}; -module.exports = expand; diff --git a/src/subset/verbs/toNegative.js b/src/subset/verbs/toNegative.js deleted file mode 100644 index cf01b42c6..000000000 --- a/src/subset/verbs/toNegative.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; -//turns a verb negative - may not have enough information to do it properly -// (eg 'did not eat' vs 'does not eat') - needs the noun -const toInfinitive = require('./methods/toInfinitive'); - -//this methods operate on parentTerms, so return subset -const getVerb = function(ts) { - ts = ts.match('(#Adverb|#Auxiliary|#Verb|#Negative|#Particle)+'); - ts = ts.splitAfter('#Comma'); - return ts.list[0]; -}; - -const toNegative = ts => { - //would not walk - let modal = ts.match('#Auxiliary').first(); //.notIf('(is|are|was|will|has|had)').first(); //.first(); - if (modal.found) { - let index = modal.list[0].index(); - let vb = ts.parentTerms.insertAt(index + 1, 'not', 'Verb'); - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //words that pair easily with a 'not' - 'is not' - let copula = ts.match('(#Copula|will|has|had|do)').first(); - if (copula.found) { - let index = copula.list[0].index(); - let vb = ts.parentTerms.insertAt(index + 1, 'not', 'Verb'); - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - let isPlural = ts.isPlural(); - - //walked -> did not walk - let past = ts.match('#PastTense').last(); - if (past.found) { - // past.debug(); - let first = past.list[0]; - let index = first.index(); - first.terms[0].text = toInfinitive(first.terms[0], ts.world); - let vb = ts.parentTerms.insertAt(index, 'did not', 'Verb'); - //add 'do not'? - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //walks -> does not walk - let pres = ts.match('#PresentTense').first(); - if (pres.found) { - let first = pres.list[0]; - let index = first.index(); - first.terms[0].text = toInfinitive(first.terms[0], ts.world); - //some things use 'do not', everything else is 'does not' - let noun = ts.getNoun(); - let vb = null; - if (noun.match('(i|we|they|you)').found) { - vb = ts.parentTerms.insertAt(index, 'do not', 'Verb'); - } else { - vb = ts.parentTerms.insertAt(index, 'does not', 'Verb'); - } - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //not walking - let gerund = ts.match('#Gerund').last(); - if (gerund.found) { - let index = gerund.list[0].index(); - let vb = ts.parentTerms.insertAt(index, 'not', 'Verb'); - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - //walk -> do not walk - let verb = ts.match('#Verb').last(); - if (verb.found) { - let first = verb.list[0]; - let index = first.index(); - first.terms[0].text = toInfinitive(first.terms[0], ts.world); - let vb = ts; - if (isPlural) { - vb = ts.parentTerms.insertAt(index - 1, 'do not', 'Verb'); - } else { - vb = ts.parentTerms.insertAt(index - 1, 'does not', 'Verb'); - } - vb.match('not').tag('Negative', 'tag-not'); - return getVerb(vb); - } - - return ts; -}; -module.exports = toNegative; diff --git a/src/subset/verbs/verb.js b/src/subset/verbs/verb.js deleted file mode 100644 index 42c88b9b8..000000000 --- a/src/subset/verbs/verb.js +++ /dev/null @@ -1,168 +0,0 @@ -'use strict'; -const Terms = require('../../paths').Terms; -const conjugate = require('./methods/conjugate'); -const toAdjective = require('./methods/toAdjective'); -const interpret = require('./interpret'); -const toNegative = require('./toNegative'); -const isPlural = require('./methods/isPlural'); -const expand = require('./methods/verbContraction'); - -const parse = function(r) { - let original = r; - r.negative = r.match('#Negative'); - r.adverbs = r.match('#Adverb'); - let aux = r.clone().not('(#Adverb|#Negative)'); - r.verb = aux - .match('#Verb') - .not('#Particle') - .last(); - r.particle = aux.match('#Particle').last(); - if (r.verb.found) { - let str = r.verb.out('normal'); - r.auxiliary = original.not(str).not('(#Adverb|#Negative)'); - r.verb = r.verb.list[0].terms[0]; - // r.auxiliary = aux.match('#Auxiliary+'); - } else { - r.verb = original.terms[0]; - r.auxiliary = aux.not('.'); - } - return r; -}; - -const methods = { - parse: function() { - return parse(this); - }, - data: function(verbose) { - return { - text: this.out('text'), - normal: this.out('normal'), - parts: { - negative: this.negative.out('normal'), - auxiliary: this.auxiliary.out('normal'), - verb: this.verb.out('normal'), - particle: this.particle.out('normal'), - adverbs: this.adverbs.out('normal') - }, - interpret: interpret(this, verbose), - conjugations: this.conjugate() - }; - }, - getNoun: function() { - if (!this.refTerms) { - return null; - } - let str = '#Adjective? #Noun+ ' + this.out('normal'); - return this.refTerms.match(str).match('#Noun+'); - }, - //which conjugation is this right now? - conjugation: function() { - return interpret(this, false).tense; - }, - //blast-out all forms - conjugate: function(verbose) { - return conjugate(this, verbose); - }, - - isPlural: function() { - return isPlural(this); - }, - /** negation **/ - isNegative: function() { - return this.match('#Negative').list.length === 1; - }, - isPerfect: function() { - return this.auxiliary.match('(have|had)').found; - }, - toNegative: function() { - if (this.isNegative()) { - return this; - } - return toNegative(this); - }, - toPositive: function() { - return this.match('#Negative').delete(); - }, - - /** conjugation **/ - toPastTense: function() { - if (this.has('#Contraction')) { - this.list = expand(this.parentTerms).list; - } - let obj = this.conjugate(); - let end = obj.PastTense; - let r = this.replaceWith(end, false); - r.verb.tag('#PastTense'); - return r; - }, - toPresentTense: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let r = this.replaceWith(obj.PresentTense, false); - r.verb.tag('#PresentTense'); - return r; - }, - toFutureTense: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let r = this.replaceWith(obj.FutureTense, false); - r.verb.tag('#FutureTense'); - return r; - }, - toInfinitive: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let r = this.replaceWith(obj.Infinitive, false); - r.verb.tag('#Infinitive'); - return r; - }, - toGerund: function() { - if (this.has('#Contraction')) { - expand(this.parentTerms); - } - let obj = this.conjugate(); - let aux = 'is'; - //support 'i am', 'we are', 'he is' - let noun = this.getNoun().out('normal'); - if (noun) { - let auxList = { - i: 'am', - we: 'are', - they: 'are', - }; - if (auxList.hasOwnProperty(noun)) { - aux = auxList[noun]; - } - } - let end = aux + ' ' + obj.Gerund; - //i would go -> i would have be going - // if (this.auxiliary && this.auxiliary.has('#Modal') && !this.auxiliary.has('will')) { - // end = this.auxiliary.match('#Modal').out() + ' have ' + end; - // } - let r = this.replaceWith(end, false); - r.verb.tag('#Gerund'); - return r; - }, - asAdjective: function() { - return toAdjective(this.verb.out('normal')); - } -}; - -const Verb = function(arr, world, refText, parentTerms) { - Terms.call(this, arr, world, refText, parentTerms); - //basic verb-phrase parsing: - return parse(this); -}; -//Terms inheritence -Verb.prototype = Object.create(Terms.prototype); -//apply methods -Object.keys(methods).forEach(k => { - Verb.prototype[k] = methods[k]; -}); -module.exports = Verb; diff --git a/src/tagger/index.js b/src/tagger/index.js deleted file mode 100644 index a4ab99fc5..000000000 --- a/src/tagger/index.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; -//the steps and processes of pos-tagging -const step = { - punctuation_step: require('./steps/01-punctuation_step'), - emoji_step: require('./steps/02-emoji_step'), - lexicon_step: require('./steps/03-lexicon_step'), - lexicon_multi: require('./steps/04-lexicon_multi'), - web_step: require('./steps/05-web_step'), - suffix_step: require('./steps/06-suffix_step'), - neighbour_step: require('./steps/07-neighbour_step'), - capital_step: require('./steps/08-capital_step'), - noun_fallback: require('./steps/09-noun_fallback'), - contraction: require('./steps/10-contraction_step'), - date_step: require('./steps/11-date_step'), - auxiliary_step: require('./steps/12-auxiliary_step'), - negation_step: require('./steps/13-negation_step'), - comma_step: require('./steps/14-comma_step'), - quotation_step: require('./steps/15-quotation_step'), - possessive_step: require('./steps/16-possessive_step'), - acronym_step: require('./steps/17-acronym_step'), - person_step: require('./steps/18-person_step'), - organization_step: require('./steps/19-organization_step'), - parentheses_step: require('./steps/20-parentheses_step'), - plural_step: require('./steps/21-plural_step'), - value_step: require('./steps/22-value_step'), - corrections: require('./steps/23-corrections'), - properNoun: require('./steps/24-proper_noun'), - custom: require('./steps/25-custom'), -}; -const tagPhrase = require('./phrase'); - -const tagger = function(ts) { - ts = step.punctuation_step(ts); - ts = step.emoji_step(ts); - ts = step.lexicon_step(ts); - ts = step.lexicon_multi(ts); - ts = step.web_step(ts); - ts = step.suffix_step(ts); - ts = step.comma_step(ts); //formerly #14 - ts = step.neighbour_step(ts); - ts = step.capital_step(ts); - ts = step.noun_fallback(ts); - ts = step.contraction(ts); - ts = step.date_step(ts); //3ms - ts = step.auxiliary_step(ts); - ts = step.negation_step(ts); - ts = step.quotation_step(ts); - ts = step.possessive_step(ts); - ts = step.acronym_step(ts); - ts = step.person_step(ts); //1ms - ts = step.organization_step(ts); - ts = step.parentheses_step(ts); - ts = step.plural_step(ts); - ts = step.value_step(ts); - ts = step.corrections(ts); //2ms - ts = step.properNoun(ts); - ts = tagPhrase(ts); - ts = step.custom(ts); - return ts; -}; - -module.exports = tagger; diff --git a/src/tagger/phrase/00-conditionPass.js b/src/tagger/phrase/00-conditionPass.js deleted file mode 100644 index 35e1be5e6..000000000 --- a/src/tagger/phrase/00-conditionPass.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -// -const conditionPass = function(ts) { - //'if it really goes, I will..' - let m = ts.match('#Condition .{1,7} #ClauseEnd'); - //make sure it ends on a comma - if (m.found && m.match('#Comma$')) { - m.tag('Condition'); - } - //'go a bit further, if it then has a pronoun - m = ts.match('#Condition .{1,13} #ClauseEnd #Pronoun'); - if (m.found && m.match('#Comma$')) { - m.not('#Pronoun$').tag('Condition', 'end-pronoun'); - } - //if it goes then .. - m = ts.match('#Condition .{1,7} then'); - if (m.found) { - m.not('then$').tag('Condition', 'cond-then'); - } - //as long as .. - m = ts.match('as long as .{1,7} (then|#ClauseEnd)'); - if (m.found) { - m.not('then$').tag('Condition', 'as-long-then'); - } - //at the end of a sentence: - //'..., if it really goes.' - m = ts.match('#Comma #Condition .{1,7} .$'); - if (m.found) { - m.not('^#Comma').tag('Condition', 'comma-7-end'); - } - // '... if so.' - m = ts.match('#Condition .{1,4}$'); - if (m.found) { - m.tag('Condition', 'cond-4-end'); - } - return ts; -}; - -module.exports = conditionPass; diff --git a/src/tagger/phrase/01-verbPhrase.js b/src/tagger/phrase/01-verbPhrase.js deleted file mode 100644 index 24253e64b..000000000 --- a/src/tagger/phrase/01-verbPhrase.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; -//a verbPhrase is a sequence of axiliaries, adverbs and verbs -const verbPhrase = function (ts) { - if (ts.has('(#Verb|#Auxiliary)')) { - ts.match('#Verb').tag('VerbPhrase', 'verbphrase-verb'); - //quickly was - ts.match('#Adverb #Verb').tag('VerbPhrase', 'adverb-verb'); - //was quickly - ts.match('#Verb #Adverb').tag('VerbPhrase', 'verb-adverb'); - //is not - ts.match('#Verb #Negative').tag('VerbPhrase', 'verb-not'); - //never is - ts.match('never #Verb').tag('VerbPhrase', 'not-verb'); - //'will have had'.. - ts.match('#Auxiliary+').tag('VerbPhrase', '2'); - // 'is' - ts.match('#Copula').tag('VerbPhrase', '#3'); - //'really will'.. - ts.match('#Adverb #Auxiliary').tag('VerbPhrase', '#4'); - //to go - // ts.match('to #Infinitive').tag('VerbPhrase', '#5'); - //work with - // ts.match('#Verb #Preposition').tag('VerbPhrase', '#6'); - } - return ts; -}; - -module.exports = verbPhrase; diff --git a/src/tagger/phrase/02-nounPhrase.js b/src/tagger/phrase/02-nounPhrase.js deleted file mode 100644 index fd9af43ee..000000000 --- a/src/tagger/phrase/02-nounPhrase.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; -// -const nounPhrase = function (r) { - let reason = 'noun-phrase-correction'; - //fifty stars - r.match('#Value #Noun').tag('NounPhrase', reason); - //nice house - r.match('#Adjective #NounPhrase').tag('NounPhrase', reason); - //tag preceding determiner 'the nice house' - r.match('#Determiner #NounPhrase').tag('NounPhrase', reason); - // - r.match('#Noun #Preposition #Noun').tag('NounPhrase', reason); - //john and sara - r.match('#Noun #Conjunction #Noun').tag('NounPhrase', reason); - //difficult but necessary talks - r.match('#Adjective #Conjunction #Adjective #NounPhrase').tag('NounPhrase', reason); - - return r; -}; - -module.exports = nounPhrase; diff --git a/src/tagger/phrase/03-adjectivePhrase.js b/src/tagger/phrase/03-adjectivePhrase.js deleted file mode 100644 index 52b54eb48..000000000 --- a/src/tagger/phrase/03-adjectivePhrase.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; -// -const adjectivePhrase = function (r) { - let reason = 'adjPhrase-correction'; - //is really not so good - // r.match('#Copula+ #Adverb? #Negative? as? #Adverb? #Adjective').tag('AdjectivePhrase').term(0).tag('#Copula'); - // //stonger than - // r.match('#Comparative than').tag('AdjectivePhrase'); - //very easy - r.match('#Copula #Adverb? #Negative? #Adverb? #Adjective #Adverb?').match('#Adverb? #Adjective #Adverb?').tag('AdjectivePhrase', reason); - //difficult but necessary - r.match('#AdjectivePhrase #Conjunction #Adjective').tag('AdjectivePhrase', reason); - //is as strong as - r.match('#AdjectivePhrase as').tag('AdjectivePhrase', reason); - return r; -}; - -module.exports = adjectivePhrase; diff --git a/src/tagger/phrase/index.js b/src/tagger/phrase/index.js deleted file mode 100644 index aaee713e0..000000000 --- a/src/tagger/phrase/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; -const conditionPass = require('./00-conditionPass'); -const verbPhrase = require('./01-verbPhrase'); -// const nounPhrase = require('./02-nounPhrase'); -// const AdjectivePhrase = require('./03-adjectivePhrase'); -// -const phraseTag = function (ts) { - ts = conditionPass(ts); - ts = verbPhrase(ts); - // ts = nounPhrase(ts); - // ts = AdjectivePhrase(ts); - return ts; -}; - -module.exports = phraseTag; diff --git a/src/tagger/steps/01-punctuation_step.js b/src/tagger/steps/01-punctuation_step.js deleted file mode 100644 index 7330a86b0..000000000 --- a/src/tagger/steps/01-punctuation_step.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; -//regs- -const titleCase = /^[A-Z][a-z']/; -const romanNum = /^[IVXCM]+$/; - -//not so smart (right now) -const isRomanNumeral = function(t) { - if (t.text.length > 1 && romanNum.test(t.text) === true) { - return t.canBe('RomanNumeral'); - } - return false; -}; - -const oneLetters = { - a: true, - i: true, - //internet-slang - u: true, - r: true, - c: true, - k: true -}; - -const punctuation_step = function(ts) { - let rules = ts.world.regex || []; - ts.terms.forEach((t, o) => { - let str = t.text; - //anything can be titlecase - if (titleCase.test(str) === true) { - t.tag('TitleCase', 'punct-rule'); - } - //add hyphenation - if (t.whitespace.after === '-' && ts.terms[o + 1] && ts.terms[o + 1].whitespace.before === '') { - t.tag('Hyphenated', 'has-hyphen'); - ts.terms[o + 1].tag('Hyphenated', 'has-hyphen'); - } - //look at () parentheses - if (t.text[0] === '(') { - t.tag('StartBracket'); - } - //look at end-brackets (allow some punctuation after)! - if (/\)[,.?!;:]?$/.test(t.text) === true) { - t.tag('EndBracket'); - } - //ok, normalise it a little, - str = str.replace(/[,\.\?]$/, ''); - //do punctuation rules (on t.text) - for (let i = 0; i < rules.length; i++) { - let r = rules[i]; - if (r.reg.test(str) === true) { - //don't over-write any other known tags - if (t.canBe(r.tag)) { - t.tag(r.tag, 'punctuation-rule- "' + r.reg.toString() + '"'); - } - return; - } - } - //terms like 'e' - if (str.length === 1 && ts.terms[o + 1] && /[A-Z]/.test(str) && !oneLetters[str.toLowerCase()]) { - t.tag('Acronym', 'one-letter-acronym'); - } - //roman numerals (weak rn) - if (isRomanNumeral(t)) { - t.tag('RomanNumeral', 'is-roman-numeral'); - } - //'100+' - if (/[0-9]\+$/.test(t.text) === true) { - t.tag('NumericValue', 'number-plus'); - } - }); - return ts; -}; - -module.exports = punctuation_step; diff --git a/src/tagger/steps/02-emoji_step.js b/src/tagger/steps/02-emoji_step.js deleted file mode 100644 index b2c8a8679..000000000 --- a/src/tagger/steps/02-emoji_step.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict'; -const emojiReg = require('./rules/emoji_regex'); -const emoticon = require('./rules/emoticon_list'); -//for us, there's three types - -// * ;) - emoticons -// * 🌵 - unicode emoji -// * :smiling_face: - asci-represented emoji - -//test for forms like ':woman_tone2:‍:ear_of_rice:' -//https://github.com/Kikobeats/emojis-keywords/blob/master/index.js -const isColonEmoji = (t) => { - if (t.text.charAt(0) === ':') { - //end comma can be last or second-last ':haircut_tone3:‍♀️' - if (t.text.match(/:.?$/) === null) { - return false; - } - //ensure no spaces - if (t.text.match(' ')) { - return false; - } - //reasonably sized - if (t.text.length > 35) { - return false; - } - return true; - } - return false; -}; - -//check against emoticon whitelist -const isEmoticon = (t) => { - //normalize the 'eyes' - let str = t.text.replace(/^[:;]/, ':'); - return emoticon.hasOwnProperty(str) === true; -}; - -// -const emojiStep = (ts) => { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //test for :keyword: emojis - if (isColonEmoji(t)) { - t.tag('Emoji', 'colon-emoji'); - } - //test for unicode emojis - if (t.text.match(emojiReg)) { - t.tag('Emoji', 'unicode-emoji'); - } - //test for emoticon ':)' emojis - if (isEmoticon(t)) { - t.tag('Emoji', 'emoticon-emoji'); - } - } - return ts; -}; -module.exports = emojiStep; diff --git a/src/tagger/steps/03-lexicon_step.js b/src/tagger/steps/03-lexicon_step.js deleted file mode 100644 index c126dc7d7..000000000 --- a/src/tagger/steps/03-lexicon_step.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; -const split = require('./contraction/split'); -// const l = require('../../lexicon/init'); -// const lexicon = l.lexicon; - -const lexicon_pass = function(ts) { - const lexicon = ts.world.words || {}; - //loop through each term - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //basic term lookup - if (lexicon.hasOwnProperty(t.normal) === true) { - t.tag(lexicon[t.normal], 'lexicon'); - continue; - } - //support silent_term matches - if (t.silent_term && lexicon.hasOwnProperty(t.silent_term) === true) { - t.tag(lexicon[t.silent_term], 'silent_term-lexicon'); - continue; - } - //check root version too - if (t.root && t.normal !== t.root) { - if (lexicon.hasOwnProperty(t.root) === true) { - t.tag(lexicon[t.root], 'lexicon'); - continue; - } - } - //support contractions (manually) - let parts = split(t); - if (parts && parts.start) { - let start = parts.start.toLowerCase(); - if (lexicon.hasOwnProperty(start) === true) { - t.tag(lexicon[start], 'contraction-lexicon'); - continue; - } - } - } - return ts; -}; - -module.exports = lexicon_pass; diff --git a/src/tagger/steps/04-lexicon_multi.js b/src/tagger/steps/04-lexicon_multi.js deleted file mode 100644 index 4aab07805..000000000 --- a/src/tagger/steps/04-lexicon_multi.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; -const MAX = 4; - -//find terms in the lexicon longer than one word (like 'hong kong') -const findMultiWords = function(ts, i, world) { - let lex = world.words; - let start = ts.terms[i].root; - let nextTerms = ts.terms.slice(i + 1, i + MAX).map((t) => t.root); - //look for matches, try biggest first - let max = MAX; - if (nextTerms.length < max) { - max = nextTerms.length; - } - for(let k = max; k > 0; k -= 1) { - let howAbout = start + ' ' + nextTerms.slice(0, k).join(' '); - if (lex.hasOwnProperty(howAbout) === true) { - ts.slice(i, i + k + 1).tag(lex[howAbout], 'multi-lexicon-' + howAbout); - return k; - } - } - return 0; -}; - - -//try multiple-word matches in the lexicon (users and default) -const lexiconMulti = ts => { - ts.world.cache = ts.world.cache || {}; - let firstWords = ts.world.cache.firstWords || {}; - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //try multi words from user-lexicon - if (firstWords.hasOwnProperty(t.root) === true) { - let jump = findMultiWords(ts, i, ts.world); - i += jump; - continue; - } - } - return ts; -}; -module.exports = lexiconMulti; diff --git a/src/tagger/steps/05-web_step.js b/src/tagger/steps/05-web_step.js deleted file mode 100644 index bd026b82c..000000000 --- a/src/tagger/steps/05-web_step.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -//identify urls, hashtags, @mentions, emails -//regs -const email = /^\w+@\w+\.[a-z]{2,3}$/; //not fancy -const hashTag = /^#[a-z0-9_]{2,}$/; -const atMention = /^@\w{2,}$/; -const urlA = /^(https?:\/\/|www\.)\w+\.[a-z]{2,3}/; //with http/www -const urlB = /^[\w\.\/]+\.(com|net|gov|org|ly|edu|info|biz|ru|jp|de|in|uk|br)/; //http://mostpopularwebsites.net/top-level-domain - -const web_pass = function(terms) { - for (let i = 0; i < terms.length; i++) { - let t = terms.get(i); - let str = t.text.trim().toLowerCase(); - if (email.test(str) === true) { - t.tag('Email', 'web_pass'); - } - if (hashTag.test(str) === true) { - t.tag('HashTag', 'web_pass'); - } - if (atMention.test(str) === true) { - t.tag('AtMention', 'web_pass'); - } - if (urlA.test(str) === true || urlB.test(str) === true) { - t.tag('Url', 'web_pass'); - } - } - return terms; -}; - -module.exports = web_pass; diff --git a/src/tagger/steps/06-suffix_step.js b/src/tagger/steps/06-suffix_step.js deleted file mode 100644 index d717488c4..000000000 --- a/src/tagger/steps/06-suffix_step.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; -const regs = require('./rules/regex_list'); -const suffixes = require('./rules/suffix_lookup'); - -const misc = [ - //slang things - [/^(lol)+[sz]$/, 'Expression'], //lol - [/^ma?cd[aeiou]/, 'LastName'], //macdonell - Last patterns https://en.wikipedia.org/wiki/List_of_family_name_affixes - //starting-ones - [/^[\-\+]?[0-9][0-9,]*(\.[0-9])*$/, 'Cardinal'], //like 5 - [/^(un|de|re)\\-[a-z]../, 'Verb'], - [/^[\-\+]?[0-9]+(\.[0-9])*$/, 'NumericValue'], - [/^https?\:?\/\/[a-z0-9]/, 'Url'], //the colon is removed in normalisation - [/^www\.[a-z0-9]/, 'Url'], - [/^(over|under)[a-z]{2,}/, 'Adjective'], - [/^[0-9]{1,4}\.[0-9]{1,2}\.[0-9]{1,4}$/, 'Date'], // 03-02-89 - //ending-ones - [/^[0-9]+([a-z]{1,2})$/, 'Value'], //like 5kg - [/^[0-9][0-9,\.]*(st|nd|rd|r?th)$/, ['NumericValue', 'Ordinal']], //like 5th - //middle (anywhere) - [/[a-z]*\\-[a-z]*\\-/, 'Adjective'] -]; - -//straight-up lookup of known-suffixes -const lookup = function(t) { - const len = t.normal.length; - let max = 7; - if (len <= max) { - max = len - 1; - } - for (let i = max; i > 1; i -= 1) { - let str = t.normal.substr(len - i, len); - if (suffixes[i][str] !== undefined) { - // console.log('suffix-match: ' + str); - return suffixes[i][str]; - } - } - return null; -}; - -//word-regexes indexed by last-character -const regexFn = function(t) { - let char = t.normal.charAt(t.normal.length - 1); - if (regs[char] === undefined) { - return null; - } - let arr = regs[char]; - for (let o = 0; o < arr.length; o++) { - if (arr[o][0].test(t.normal) === true) { - return arr[o]; - } - } - return null; -}; - -const suffix_step = function(ts) { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //try known suffixes - let tag = lookup(t); - if (tag !== null && t.canBe(tag) === true) { - t.tag(tag, 'suffix-lookup'); - continue; - } - //apply regexes by final-char - tag = regexFn(t); - if (tag !== null && t.canBe(tag[1]) === true) { - t.tag(tag[1], 'regex-list: ' + String(tag[0])); - continue; - } - //apply misc regexes - for (let o = 0; o < misc.length; o++) { - if (misc[o][0].test(t.normal) === true) { - tag = misc[o][1]; - if (t.canBe(tag) === true) { - t.tag(tag, 'misc-regex-' + misc[o][0]); - } - } - } - } - return ts; -}; - -module.exports = suffix_step; diff --git a/src/tagger/steps/07-neighbour_step.js b/src/tagger/steps/07-neighbour_step.js deleted file mode 100644 index adc8596d7..000000000 --- a/src/tagger/steps/07-neighbour_step.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; -const markov = require('./rules/neighbours'); -const afterThisWord = markov.afterThisWord; -const beforeThisWord = markov.beforeThisWord; -const beforeThisPos = markov.beforeThisPos; -const afterThisPos = markov.afterThisPos; - -const nothing = { - TitleCase: true, - UpperCase: true, - CamelCase: true, - Hyphenated: true, - StartBracket: true, - EndBracket: true, - Comma: true, - ClauseEnd: true, -}; - -//basically a last-ditch effort before everything falls back to a noun -//for unknown terms, look left + right first, and hit-up the markov-chain for clues -const neighbour_step = function (ts) { - ts.terms.forEach((t, n) => { - //is it still unknown? - let termTags = Object.keys(t.tags); - termTags = termTags.filter((tag) => nothing.hasOwnProperty(tag) === false); - if (termTags.length === 0) { - let lastTerm = ts.terms[n - 1]; - let nextTerm = ts.terms[n + 1]; - //look at previous word for clues - if (lastTerm && afterThisWord.hasOwnProperty(lastTerm.normal) && !lastTerm.tags.ClauseEnd) { - t.tag(afterThisWord[lastTerm.normal], 'neighbour-after-"' + lastTerm.normal + '"'); - return; - } - //look at next word for clues.. - //(not if there's a comma, though) - if (!t.tags.ClauseEnd && nextTerm && beforeThisWord.hasOwnProperty(nextTerm.normal)) { - t.tag(beforeThisWord[nextTerm.normal], 'neighbour-before-"' + nextTerm.normal + '"'); - return; - } - //look at the last POS for clues - let tags = []; - if (lastTerm) { - tags = Object.keys(lastTerm.tags); - for (let i = 0; i < tags.length; i++) { - if (afterThisPos[tags[i]]) { - t.tag(afterThisPos[tags[i]], 'neighbour-after-[' + tags[i] + ']'); - return; - } - } - } - //look at the next POS for clues - if (nextTerm) { - tags = Object.keys(nextTerm.tags); - for (let i = 0; i < tags.length; i++) { - if (beforeThisPos[tags[i]]) { - t.tag(beforeThisPos[tags[i]], 'neighbour-before-[' + tags[i] + ']'); - return; - } - } - } - } - }); - - return ts; -}; - -module.exports = neighbour_step; diff --git a/src/tagger/steps/08-capital_step.js b/src/tagger/steps/08-capital_step.js deleted file mode 100644 index d241a15c6..000000000 --- a/src/tagger/steps/08-capital_step.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -//titlecase is a signal for a noun - -const capital_logic = function (s) { - //(ignore first word) - for (let i = 1; i < s.terms.length; i++) { - let t = s.terms[i]; - //has a capital, but isn't too weird. - if (t.tags.TitleCase && t.isWord()) { - t.tag('Noun', 'capital-step'); - t.tag('TitleCase', 'capital-step'); - } - } - //support first-word of sentence as proper titlecase - let t = s.terms[0]; - if (t && t.tags.TitleCase) { - if (t.tags.Person || t.tags.Organization || t.tags.Place) { - t.tag('TitleCase', 'first-term-capital'); - } - } - return s; -}; - -module.exports = capital_logic; diff --git a/src/tagger/steps/09-noun_fallback.js b/src/tagger/steps/09-noun_fallback.js deleted file mode 100644 index 75a898e5a..000000000 --- a/src/tagger/steps/09-noun_fallback.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; -//tag word as noun if we know nothing about it, still. - -//tags that dont really count -const nothing = { - TitleCase: true, - UpperCase: true, - CamelCase: true, - Hyphenated: true, - StartBracket: true, - EndBracket: true, - Comma: true, - ClauseEnd: true, -}; -//are the tags basically empty -const gotNothing = function(t) { - //fail-fast - if (t.tags.Noun || t.tags.Verb || t.tags.Adjective) { - return false; - } - let tags = Object.keys(t.tags); - if (tags.length === 0) { - return true; - } - if (tags.filter(tag => !nothing[tag]).length === 0) { - return true; - } - return false; -}; - -//in last-ditch, try to match 'rewatch' -> 'watch' in the lexicon -const tryRoot = function(t) { - if (/^(re|un)-?[^aeiou]./.test(t.normal) === true) { - let str = t.normal.replace(/^(re|un)-?/, ''); - if (t.world.words.hasOwnProperty(str) === true) { - let tag = t.world.words[str]; - if (tag === 'Infinitive' || tag === 'PresentTense' || tag === 'PastTense' || tag === 'Gerund') { - return tag; - } - } - } - return null; -}; - -const noun_fallback = function(s) { - for (let i = 0; i < s.terms.length; i++) { - let t = s.terms[i]; - //fail-fast - if (t.tags.Noun || t.tags.Verb) { - continue; - } - //ensure it only has the tag 'Term' - if (gotNothing(t)) { - //ensure it's atleast word-looking - if (t.isWord() === false) { - continue; - } - let rootTag = tryRoot(t); - if (rootTag !== null) { - t.tag(rootTag, 'root-tag-match'); - continue; - } - t.tag('Noun', 'noun-fallback'); - } - } - return s; -}; - -module.exports = noun_fallback; diff --git a/src/tagger/steps/10-contraction_step.js b/src/tagger/steps/10-contraction_step.js deleted file mode 100644 index 6cd123c42..000000000 --- a/src/tagger/steps/10-contraction_step.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -const irregulars = require('./contraction/01-irregulars'); -const isWasHas = require('./contraction/02-isWasHas'); -const easyOnes = require('./contraction/03-easyOnes'); -const numberRange = require('./contraction/04-numberRange'); - -//find and pull-apart contractions -const interpret = function(ts) { - //check irregulars - ts = irregulars(ts); - //guess-at ambiguous "'s" one - ts = isWasHas(ts); - //check easy ones - ts = easyOnes(ts); - //5-7 - ts = numberRange(ts); - return ts; -}; - -module.exports = interpret; diff --git a/src/tagger/steps/11-date_step.js b/src/tagger/steps/11-date_step.js deleted file mode 100644 index d4a93b065..000000000 --- a/src/tagger/steps/11-date_step.js +++ /dev/null @@ -1,242 +0,0 @@ -'use strict'; -//ambiguous 'may' and 'march' -const preps = '(in|by|before|during|on|until|after|of|within|all)'; -const thisNext = '(last|next|this|previous|current|upcoming|coming)'; -const sections = '(start|end|middle|starting|ending|midpoint|beginning)'; -const seasons = '(spring|summer|winter|fall|autumn)'; - -//ensure a year is approximately typical for common years -//please change in one thousand years -const tagYear = (v, reason) => { - if (v.found !== true) { - return; - } - v.list.forEach((ts) => { - let num = parseInt(ts.terms[0].normal, 10); - if (num && num > 1000 && num < 3000) { - ts.terms[0].tag('Year', reason); - } - }); -}; -//same, but for less-confident values -const tagYearSafer = (v, reason) => { - if (v.found !== true) { - return; - } - v.list.forEach((ts) => { - let num = parseInt(ts.terms[0].normal, 10); - if (num && num > 1900 && num < 2030) { - ts.terms[0].tag('Year', reason); - } - }); -}; - -//non-destructively tag values & prepositions as dates -const datePass = function (ts) { - //ambiguous month - person forms - let people = '(january|april|may|june|summer|autumn|jan|sep)'; - if (ts.has(people)) { - //give to april - ts.match(`#Infinitive #Determiner? #Adjective? #Noun? (to|for) ${people}`).lastTerm().tag('Person', 'ambig-person'); - //remind june - ts.match(`#Infinitive ${people}`).lastTerm().tag('Person', 'infinitive-person'); - //may waits for - ts.match(`${people} #PresentTense (to|for)`).firstTerm().tag('Person', 'ambig-active'); - //april will - ts.match(`${people} #Modal`).firstTerm().tag('Person', 'ambig-modal'); - //would april - ts.match(`#Modal ${people}`).lastTerm().tag('Person', 'modal-ambig'); - //with april - ts.match(`(that|with|for) ${people}`).term(1).tag('Person', 'that-month'); - //it is may - ts.match(`#Copula ${people}`).term(1).tag('Person', 'is-may'); - //may is - ts.match(`${people} #Copula`).term(0).tag('Person', 'may-is'); - //april the 5th - ts.match(`${people} the? #Value`).term(0).tag('Month', 'person-value'); - //wednesday april - ts.match(`#Date ${people}`).term(1).tag('Month', 'correction-may'); - //may 5th - ts.match(`${people} the? #Value`).firstTerm().tag('Month', 'may-5th'); - //5th of may - ts.match(`#Value of ${people}`).lastTerm().tag('Month', '5th-of-may'); - //by april - ts.match(`${preps} ${people}`).ifNo('#Holiday').term(1).tag('Month', 'preps-month'); - //this april - ts.match(`(next|this|last) ${people}`).term(1).tag('Month', 'correction-may'); //maybe not 'this' - } - //ambiguous month - verb-forms - let verbs = '(may|march)'; - if (ts.has(verbs)) { - //quickly march - ts.match(`#Adverb ${verbs}`).lastTerm().tag('Infinitive', 'ambig-verb'); - ts.match(`${verbs} #Adverb`).lastTerm().tag('Infinitive', 'ambig-verb'); - //all march - ts.match(`${preps} ${verbs}`).lastTerm().tag('Month', 'in-month'); - //this march - ts.match(`(next|this|last) ${verbs}`).lastTerm().tag('Month', 'this-month'); - //with date - ts.match(`${verbs} the? #Value`).firstTerm().tag('Month', 'march-5th'); - ts.match(`#Value of? ${verbs}`).lastTerm().tag('Month', '5th-of-march'); - //nearby - ts.match(`[${verbs}] .? #Date`).lastTerm().tag('Month', 'march-and-feb'); - ts.match(`#Date .? [${verbs}]`).lastTerm().tag('Month', 'feb-and-march'); - - if (ts.has('march')) { - //march to - ts.match('march (up|down|back|to|toward)').term(0).tag('Infinitive', 'march-to'); - //must march - ts.match('#Modal march').term(1).tag('Infinitive', 'must-march'); - } - - } - //sun 5th - if (ts.has('sun')) { - //sun feb 2 - ts.match('sun #Date').firstTerm().tag('WeekDay', 'sun-feb'); - //sun the 5th - ts.match('sun the #Ordinal').tag('Date').firstTerm().tag('WeekDay', 'sun-the-5th'); - //the sun - ts.match('#Determiner sun').lastTerm().tag('Singular', 'the-sun'); - } - //sat, nov 5th - if (ts.has('sat')) { - //sat november - ts.match('sat #Date').firstTerm().tag('WeekDay', 'sat-feb'); - //this sat - ts.match(`${preps} sat`).lastTerm().tag('WeekDay', 'sat'); - } - - //months: - if (ts.has('#Month')) { - //June 5-7th - ts.match(`#Month #DateRange+`).tag('Date', 'correction-numberRange'); - //5th of March - ts.match('#Value of #Month').tag('Date', 'value-of-month'); - //5 March - ts.match('#Cardinal #Month').tag('Date', 'cardinal-month'); - //march 5 to 7 - ts.match('#Month #Value to #Value').tag('Date', 'value-to-value'); - //march the 12th - ts.match('#Month the #Value').tag('Date', 'month-the-value'); - } - - ts.match('in the (night|evening|morning|afternoon|day|daytime)').tag('Time', 'in-the-night'); - ts.match('(#Value|#Time) (am|pm)').tag('Time', 'value-ampm'); - - //months: - if (ts.has('#Value')) { - //for 4 months - ts.match('for #Value #Duration').tag('Date', 'for-x-duration'); - //values - ts.match('#Value #Abbreviation').tag('Value', 'value-abbr'); - ts.match('a #Value').if('(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)').tag('Value', 'a-value'); - ts.match('(minus|negative) #Value').tag('Value', 'minus-value'); - ts.match('#Value grand').tag('Value', 'value-grand'); - // ts.match('#Ordinal (half|quarter)').tag('Value', 'ordinal-half');//not ready - ts.match('(half|quarter) #Ordinal').tag('Value', 'half-ordinal'); - ts.match('(hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion) and #Value').tag('Value', 'magnitude-and-value'); - ts.match('#Value (point|decimal) #Value').tag('Value', 'value-point-value'); - //for four days - ts.match(`${preps}? #Value #Duration`).tag('Date', 'value-duration'); - ts.match('(#WeekDay|#Month) #Value').ifNo('#Money').tag('Date', 'date-value'); - ts.match('#Value (#WeekDay|#Month)').ifNo('#Money').tag('Date', 'value-date'); - //may twenty five - let vs = ts.match('#TextValue #TextValue'); - if (vs.found && vs.has('#Date')) { - vs.tag('#Date', 'textvalue-date'); - } - //two days before - ts.match('#Value #Duration #Conjunction').tag('Date', 'val-duration-conjunction'); - //two years old - ts.match('#Value #Duration old').unTag('Date', 'val-years-old'); - } - - - //seasons - if (ts.has(seasons)) { - ts.match(`${preps}? ${thisNext} ${seasons}`).tag('Date', 'thisNext-season'); - ts.match(`the? ${sections} of ${seasons}`).tag('Date', 'section-season'); - } - - //rest-dates - if (ts.has('#Date')) { - //june the 5th - ts.match('#Date the? #Ordinal').tag('Date', 'correction-date'); - //last month - ts.match(`${thisNext} #Date`).tag('Date', 'thisNext-date'); - //by 5 March - ts.match('due? (by|before|after|until) #Date').tag('Date', 'by-date'); - //tomorrow before 3 - ts.match('#Date (by|before|after|at|@|about) #Cardinal').not('^#Date').tag('Time', 'date-before-Cardinal'); - //saturday am - ts.match('#Date (am|pm)').term(1).unTag('Verb').unTag('Copula').tag('Time', 'date-am'); - ts.match('(last|next|this|previous|current|upcoming|coming|the) #Date').tag('Date', 'next-feb'); - ts.match('#Date (#Preposition|to) #Date').tag('Date', 'date-prep-date'); - //start of june - ts.match(`the? ${sections} of #Date`).tag('Date', 'section-of-date'); - //fifth week in 1998 - ts.match('#Ordinal #Duration in #Date').tag('Date', 'duration-in-date'); - //early in june - ts.match('(early|late) (at|in)? the? #Date').tag('Time', 'early-evening'); - } - - - //year/cardinal tagging - if (ts.has('#Cardinal')) { - let v = ts.match(`#Date #Value #Cardinal`).lastTerm(); - tagYear(v, 'date-value-year'); - //scoops up a bunch - v = ts.match(`#Date+ #Cardinal`).lastTerm(); - tagYear(v, 'date-year'); - //feb 8 2018 - v = ts.match(`#Month #Value #Cardinal`).lastTerm(); - tagYear(v, 'month-value-year'); - //feb 8 to 10th 2018 - v = ts.match(`#Month #Value to #Value #Cardinal`).lastTerm(); - tagYear(v, 'month-range-year'); - //in 1998 - v = ts.match(`(in|of|by|during|before|starting|ending|for|year) #Cardinal`).lastTerm(); - tagYear(v, 'in-year'); - //q2 2009 - v = ts.match('(q1|q2|q3|q4) [#Cardinal]'); - tagYear(v, 'in-year'); - //2nd quarter 2009 - v = ts.match('#Ordinal quarter [#Cardinal]'); - tagYear(v, 'in-year'); - //in the year 1998 - v = ts.match('the year [#Cardinal]'); - tagYear(v, 'in-year'); - - //it was 1998 - v = ts.match('it (is|was) [#Cardinal]'); - tagYearSafer(v, 'in-year'); - //was 1998 and... - v = ts.match(`#Cardinal !#Plural`).firstTerm(); - tagYearSafer(v, 'year-unsafe'); - } - - //another pass at dates.. - if (ts.has('#Date')) { - //time: - if (ts.has('#Time')) { - ts.match('#Cardinal #Time').not('#Year').tag('Time', 'value-time'); - ts.match('(by|before|after|at|@|about) #Time').tag('Time', 'preposition-time'); - //2pm est - ts.match('#Time (eastern|pacific|central|mountain)').term(1).tag('Time', 'timezone'); - ts.match('#Time (est|pst|gmt)').term(1).tag('Time', 'timezone abbr'); - } - - //fix over-greedy - let date = ts.match('#Date+').splitOn('Clause'); - - if (date.has('(#Year|#Time)') === false) { - //12 february 12 - date.match('#Value (#Month|#Weekday) #Value').lastTerm().unTag('Date'); - } - } - - return ts; -}; - -module.exports = datePass; diff --git a/src/tagger/steps/12-auxiliary_step.js b/src/tagger/steps/12-auxiliary_step.js deleted file mode 100644 index 4b92dd055..000000000 --- a/src/tagger/steps/12-auxiliary_step.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -//auxiliary verbs are extra verbs beside the main ones -// "[will be] going" - etc. - -const Auxiliary = { - 'do': true, - 'don\'t': true, - 'does': true, - 'doesn\'t': true, - 'will': true, - 'wont': true, - 'won\'t': true, - 'have': true, - 'haven\'t': true, - 'had': true, - 'hadn\'t': true, - 'not': true, -}; - -const corrections = function(ts) { - //set verbs as auxillaries - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (Auxiliary[t.normal] || Auxiliary[t.silent_term]) { - let next = ts.terms[i + 1]; - //if next word is a verb - if (next && (next.tags.Verb || next.tags.Adverb || next.tags.Negative)) { - t.tag('Auxiliary', 'corrections-Auxiliary'); - continue; - } - } - } - return ts; -}; - -module.exports = corrections; diff --git a/src/tagger/steps/13-negation_step.js b/src/tagger/steps/13-negation_step.js deleted file mode 100644 index f0323010b..000000000 --- a/src/tagger/steps/13-negation_step.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -// 'not' is sometimes a verb, sometimes an adjective -const negation_step = function(ts) { - for(let i = 0; i < ts.length; i++) { - let t = ts.get(i); - if (t.normal === 'not' || t.silent_term === 'not') { - //find the next verb/adjective - for(let o = i + 1; o < ts.length; o++) { - if (ts.get(o).tags.Verb) { - t.tag('VerbPhrase', 'negate-verb'); - break; - } - if (ts.get(o).tags.Adjective) { - t.tag('AdjectivePhrase', 'negate-adj'); - break; - } - } - } - } - return ts; -}; - -module.exports = negation_step; diff --git a/src/tagger/steps/14-comma_step.js b/src/tagger/steps/14-comma_step.js deleted file mode 100644 index bfb5fd2f6..000000000 --- a/src/tagger/steps/14-comma_step.js +++ /dev/null @@ -1,128 +0,0 @@ -'use strict'; -//-types of comma-use- -// PlaceComma - Hollywood, California -// List - cool, fun, and great. -// ClauseEnd - if so, we do. - -//like Toronto, Canada -const isPlaceComma = (ts, i) => { - let t = ts.terms[i]; - let nextTerm = ts.terms[i + 1]; - //'australia, canada' is a list - if (nextTerm && t.tags.Place && !t.tags.Country && nextTerm.tags.Country) { - return true; - } - return false; -}; - -//adj, noun, or verb -const mainTag = (t) => { - if (t.tags.Adjective) { - return 'Adjective'; - } - if (t.tags.Noun) { - return 'Noun'; - } - if (t.tags.Verb) { - return 'Verb'; - } - if (t.tags.Value) { - return 'Value'; - } - return null; -}; - - -//take the first term with a comma, and test to the right. -//the words with a comma must be the same pos. -const isList = (ts, i) => { - let start = i; - let tag = mainTag(ts.terms[i]); - //ensure there's a following comma, and its the same pos - //then a Conjunction - let sinceComma = 0; - let count = 0; - let hasConjunction = false; - for(i = i + 1; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //are we approaching the end - if (count > 0 && t.tags.Conjunction) { - hasConjunction = true; - continue; - } - //found one, - if (t.tags[tag]) { - //looks good. keep it going - if (t.tags.Comma) { - count += 1; - sinceComma = 0; - continue; - } - if (count > 0 && hasConjunction) { //is this the end of the list? - ts.slice(start, i).tag('List'); - return true; - } - } - sinceComma += 1; - //have we gone too far without a comma? - if (sinceComma > 5) { - return false; - } - //this one, not a clause.. - if (tag === 'Value') { - return true; - } - } - return false; -}; - -const commaStep = function(ts) { - //tag the correct punctuation forms - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - let punct = t.getPunctuation(); - if (punct === ',') { - t.tag('Comma', 'comma-step'); - continue; - } - if (punct === ';' || punct === ':') { - t.tag('ClauseEnd', 'clause-punt'); - continue; - } - //support elipses - if (t.whitespace.after.match(/^\.\./)) { - t.tag('ClauseEnd', 'clause-elipses'); - continue; - } - - //support ' - ' clause - if (ts.terms[i + 1] && ts.terms[i + 1].whitespace.before.match(/ - /)) { - t.tag('ClauseEnd', 'hypen-clause'); - continue; - } - } - - //disambiguate the commas now - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (t.tags.Comma) { - //if we already got it - if (t.tags.List) { - continue; - } - //like 'Hollywood, California' - if (isPlaceComma(ts, i)) { - continue; - } - //like 'cold, wet hands' - let found = isList(ts, i); - //otherwise, it's a phrasal comma, like 'you must, if you think so' - if (!found) { - t.tag('ClauseEnd', 'phrasal-comma'); - } - } - } - return ts; -}; - -module.exports = commaStep; diff --git a/src/tagger/steps/15-quotation_step.js b/src/tagger/steps/15-quotation_step.js deleted file mode 100644 index 88c648c7e..000000000 --- a/src/tagger/steps/15-quotation_step.js +++ /dev/null @@ -1,145 +0,0 @@ -'use strict'; - -const quotemarks = { - '\u0022': { - close: '\u0022', - tag: 'StraightDoubleQuotes' - }, - '\uFF02': { - close: '\uFF02', - tag: 'StraightDoubleQuotesWide' - }, - '\u0027': { - close: '\u0027', - tag: 'StraightSingleQuotes' - }, - - '\u201C': { - close: '\u201D', - tag: 'CommaDoubleQuotes' - }, - '\u2018': { - close: '\u2019', - tag: 'CommaSingleQuotes' - }, - - '\u201F': { - close: '\u201D', - tag: 'CurlyDoubleQuotesReversed' - }, - '\u201B': { - close: '\u2019', - tag: 'CurlySingleQuotesReversed' - }, - - '\u201E': { - close: '\u201D', - tag: 'LowCurlyDoubleQuotes' - }, - '\u2E42': { - close: '\u201D', - tag: 'LowCurlyDoubleQuotesReversed' - }, - - '\u201A': { - close: '\u2019', - tag: 'LowCurlySingleQuotes' - }, - - '\u00AB': { - close: '\u00BB', - tag: 'AngleDoubleQuotes' - }, - '\u2039': { - close: '\u203A', - tag: 'AngleSingleQuotes' - }, - - // Prime 'non quotation' - '\u2035': { - close: '\u2032', - tag: 'PrimeSingleQuotes' - }, - '\u2036': { - close: '\u2033', - tag: 'PrimeDoubleQuotes' - }, - '\u2037': { - close: '\u2034', - tag: 'PrimeTripleQuotes' - }, - - // Prime 'quotation' variation - '\u301D': { - close: '\u301E', - tag: 'PrimeDoubleQuotes' - }, - '\u0060': { - close: '\u00B4', - tag: 'PrimeSingleQuotes' - }, - - '\u301F': { - close: '\u301E', - tag: 'LowPrimeDoubleQuotesReversed' - } -}; - -// Convert the close quote to a regex. -Object.keys(quotemarks).forEach((open) => { - quotemarks[open].regex = new RegExp(quotemarks[open].close + '[;:,.]*'); - quotemarks[open].open = open; -}); - -// Improve open match detection. -const startQuote = new RegExp('[' + Object.keys(quotemarks).join('') + ']'); - -//tag a inline quotation as such -const quotation_step = ts => { - // Isolate the text so it doesn't change. - const terms = ts.terms.slice(0); //.map(e => e.text); - for (let i = 0; i < terms.length; i++) { - - let t = ts.terms[i]; - if (startQuote.test(t.whitespace.before)) { - // Get the match and split it into groups - let quotes = t.whitespace.before.match(startQuote).shift().split(''); - // Get close and tag info. - quotes = quotes.map(mark => quotemarks[mark]); - // Look for the ending - for (let o = 0; o < ts.terms.length; o++) { - // max-length don't go-on forever - if (!terms[i + o] || o > 28) { - break; - } - // Find the close. - let index = -1; - for(let qi = 0; qi < quotes.length; qi += 1) { - if (quotes[qi].regex.test(terms[i + o].whitespace.after) === true) { - index = qi; - break; - } - } - if (index !== -1) { - // Remove the found - const quote = quotes.splice(index, 1).pop(); - - if (quote.regex.test(ts.terms[i + o].normal)) { - ts.terms[i + o].whitespace.after.replace(quote.regex, ''); - } - // Tag the things. - t.tag('StartQuotation', 'quotation_open'); - ts.terms[i + o].tag('EndQuotation', 'quotation_close'); - ts.slice(i, i + o + 1).tag('Quotation', 'quotation_step'); - // Compensate for multiple close quotes ('"Really"') - o -= 1; - if (!quotes.length) { - break; - } - } - } - } - } - return ts; -}; -module.exports = quotation_step; diff --git a/src/tagger/steps/16-possessive_step.js b/src/tagger/steps/16-possessive_step.js deleted file mode 100644 index 7c8cf58f9..000000000 --- a/src/tagger/steps/16-possessive_step.js +++ /dev/null @@ -1,117 +0,0 @@ -'use strict'; -//decide if an apostrophe s is a contraction or not -// 'spencer's nice' -> 'spencer is nice' -// 'spencer's house' -> 'spencer's house' - -const singleQuotes = [ - ['\u0027', '\u0027'], // Straight Single Quotes - ['\u2018', '\u2019'], // Comma Single Quotes - ['\u201B', '\u2019'], // Curly Single Quotes Reversed - ['\u201A', '\u2019'], // Low Curly Single Quotes - ['\u2035', '\u2032'], // Prime Single Quotes Alt - ['\u0060', '\u00B4'] // Prime Single Quotes -]; -//these are always contractions -const blacklist = [ - 'it\'s', - 'that\'s' -]; - -// Get all types of single quote. -const apostrophes = '\'‘’‛‚‵′`´'; -const afterWord = new RegExp('([a-z]s[' + apostrophes + '])\\W*$'); // [^\w]* match 0 or more of any char that is NOT alphanumeric -const hasApostrophe = new RegExp('[' + apostrophes + ']'); -const trailers = new RegExp('[^' + apostrophes + '\\w]+$'); - -const quoteRegex = {}; -singleQuotes.forEach(quote => { - quoteRegex[quote[0]] = new RegExp(quote[1] + '[^' + quote[1] + '\\w]*$'); -}); - -// Compensate for different `'`s in the blacklist -blacklist.map(item => new RegExp( - item.replace('\'', '[' + apostrophes + ']') -)); - -// A possessive means `'s` describes ownership -// Not a contraction, like it's -> `it is` -const is_possessive = function(terms, text, index) { - const thisWord = terms.get(index); - const nextWord = terms.get(index + 1); - const stepWord = terms.get(index + 2); - - //our booleans: - // `blacklist` are always contractions, not possessive - const inBlacklist = blacklist.map(r => text.match(r)).find(m => m); - // If no apostrophe s or s apostrophe - const endTick = hasApostrophe.test(thisWord.whitespace.after); - // "spencers'" - this is always possessive - eg "flanders'" - const hasPronoun = thisWord.tags.Pronoun; - - if (inBlacklist || hasPronoun || !endTick) { - return false; - } - if (afterWord.test(text) || nextWord === undefined) { - return true; - } - // Next word is 'house' - if (nextWord.tags.Noun === true || thisWord.tags.ClauseEnd === true) { - return true; - } - //rocket's red glare - if (stepWord !== undefined && nextWord.tags.Adjective && stepWord.tags.Noun) { - return true; - } - return false; -}; - -// Tag each term as possessive, if it should -const possessiveStep = function(ts) { - let expectingClosers = []; - for(let i = 0; i < ts.length; i++) { - const term = ts.get(i); - let text = term.text; - - // First detect open quotes before detecting apostrophes - if (typeof quoteRegex[text[0]] !== 'undefined') { - // Add the expected closing quotes to our inspection array. - expectingClosers[expectingClosers.length] = quoteRegex[text[0]]; - text = text.slice(1); - } - - // Pre checking for quotes. e.g: Carlos'.’. -> Carlos'.’ - text = text.replace(trailers, ''); - // If the string ends with an expected closer. - let closer = -1; - for(let qi = 0; qi < expectingClosers.length; qi += 1) { - if (expectingClosers[qi].test(text) === true) { - closer = qi; - break; - } - } - if (closer !== -1) { - text = text.replace(expectingClosers[closer], ''); - delete expectingClosers[closer]; - } - - // Post checking for quotes. e.g: Carlos'. -> Carlos' - text = text.replace(trailers, ''); - if (is_possessive(ts, text, i)) { - // If it's not already a noun, co-erce it to one - if (!term.tags['Noun']) { - term.tag('Noun', 'possessive_pass'); - } - term.tag('Possessive', 'possessive_pass'); - - // If it's been detected as a `Contraction` - if (term.tags.Contraction === true) { - // Remove the `Contraction` tag and silent_terms - term.unTag('Contraction'); - ts.terms.splice(i + 1, 1); - term.silent_term = ''; - } - } - } - return ts; -}; -module.exports = possessiveStep; diff --git a/src/tagger/steps/17-acronym_step.js b/src/tagger/steps/17-acronym_step.js deleted file mode 100644 index 0f937e06e..000000000 --- a/src/tagger/steps/17-acronym_step.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -//tag 'FBI' as letters-representing-words. -//we guess if letters are an acronym in the Term class. -const acronym_step = function(ts) { - ts.terms.forEach((t) => { - if (t.isAcronym()) { - t.tag('Acronym', 'acronym-step'); - } - }); - return ts; -}; - -module.exports = acronym_step; diff --git a/src/tagger/steps/18-person_step.js b/src/tagger/steps/18-person_step.js deleted file mode 100644 index d220a4f0e..000000000 --- a/src/tagger/steps/18-person_step.js +++ /dev/null @@ -1,184 +0,0 @@ -'use strict'; - -//sort-out things like 'theresa may', or 'will jones'. -const person_step = function(ts) { - //mr Putin - ts.match('(mr|mrs|ms|dr) (#TitleCase|#Possessive)+').tag('#Person', 'mr-putin'); - - //a bunch of ambiguous first names - let maybeNoun = '(rose|robin|dawn|ray|holly|bill|joy|viola|penny|sky|violet|daisy|melody|kelvin|hope|mercedes|olive|jewel|faith|van|charity|miles|lily|summer|dolly|rod|dick|cliff|lane|reed|kitty|art|jean|trinity)'; - if (ts.has(maybeNoun)) { - ts.match('(#Determiner|#Adverb|#Pronoun|#Possessive) [' + maybeNoun + ']').tag('Noun', 'the-ray'); - ts.match(maybeNoun + ' (#Person|#Acronym|#TitleCase)').canBe('#Person').tag('Person', 'ray-smith'); - } - //verbs or people-names - let maybeVerb = '(pat|wade|ollie|will|rob|buck|bob|mark|jack)'; - if (ts.has(maybeVerb)) { - ts.match('(#Modal|#Adverb) [' + maybeVerb + ']').tag('Verb', 'would-mark'); - ts.match(maybeVerb + ' (#Person|#TitleCase)').tag('Person', 'rob-smith'); - } - //adjectives or people-names - let maybeAdj = '(misty|rusty|dusty|rich|randy)'; - if (ts.has(maybeAdj)) { - ts.match('#Adverb [' + maybeAdj + ']').tag('Adjective', 'really-rich'); - ts.match(maybeAdj + ' (#Person|#TitleCase)').tag('Person', 'randy-smith'); - } - //dates as people names - let maybeDate = '(april|june|may|jan|august|eve)'; - if (ts.has(maybeDate)) { - ts.match(String(maybeDate) + ' (#Person|#TitleCase)').canBe('#Person').tag('Person', 'june-smith'); - ts.match('(in|during|on|by|before|#Date) [' + maybeDate + ']').canBe('#Date').tag('Date', 'in-june'); - ts.match(maybeDate + ' (#Date|#Value)').canBe('#Date').tag('Date', 'june-5th'); - } - //place-names as people-names - let maybePlace = '(paris|alexandria|houston|kobe|salvador|sydney)'; - if (ts.has(maybePlace)) { - ts.match('(in|near|at|from|to|#Place) [' + maybePlace + ']').canBe('#Place').tag('Place', 'in-paris'); - ts.match('[' + maybePlace + '] #Place').canBe('#Place').tag('Place', 'paris-france'); - ts.match('[' + maybePlace + '] #Person').canBe('#Person').tag('Person', 'paris-hilton'); - } - //this one is tricky - if (ts.match('al')) { - ts.match('al (#Person|#TitleCase)').canBe('#Person').tag('#Person', 'al-borlen'); - ts.match('#TitleCase al #TitleCase').canBe('#Person').tag('#Person', 'arabic-al-arabic'); - } - //ambiguous honorifics - ts.match('(private|general|major|corporal|lord|lady|secretary|premier) #Honorific? #Person').terms(0).tag('Honorific', 'ambg-honorifics'); - //first general.. - ts.match('(1st|2nd|first|second) #Honorific').terms(0).tag('Honorific', 'ordinal-honorific'); - - // let firstNames = '()'; - // let names = ts.match(firstNames); - // if (names.found) { - // //prolly not a name: - // if (ts.has('(#Determiner|#Adverb|#Pronoun|#Possessive) ' + firstNames)) { - // names.unTag('Person', 'the-bill'); - // } else { - // //probably a name here: - // let name = ts.match('(#Honorific|#Person) ' + firstNames); - // if (!name.found) { - // name = ts.match(firstNames + ' (#Person|#Honorific|#TitleCase)'); - // } - // if (name.found && name.has('(#Place|#Date|#Organization)') === false) { - // name.tag('Person', 'dr-bill'); - // names.tag('FirstName', 'ambiguous-name'); - // } - // } - // } - //tighter-matches for other ambiguous names: - // ts.match('(al|) #Acronym? #LastName').firstTerm().tag('#FirstName', 'ambig-lastname'); - - //methods requiring a firstname match - if (ts.has('#FirstName')) { - // Firstname x (dangerous) - let tmp = ts.match('#FirstName #Noun').ifNo('^#Possessive').ifNo('#ClauseEnd .'); - tmp.lastTerm().canBe('#LastName').tag('#LastName', 'firstname-noun'); - //ferdinand de almar - ts.match('#FirstName de #Noun').canBe('#Person').tag('#Person', 'firstname-de-noun'); - //Osama bin Laden - ts.match('#FirstName (bin|al) #Noun').canBe('#Person').tag('#Person', 'firstname-al-noun'); - //John L. Foo - ts.match('#FirstName #Acronym #TitleCase').tag('Person', 'firstname-acronym-titlecase'); - //Andrew Lloyd Webber - ts.match('#FirstName #FirstName #TitleCase').tag('Person', 'firstname-firstname-titlecase'); - //Mr Foo - ts.match('#Honorific #FirstName? #TitleCase').tag('Person', 'Honorific-TitleCase'); - //John Foo - ts.match('#FirstName #TitleCase #TitleCase?').match('#Noun+').tag('Person', 'firstname-titlecase'); - //peter the great - ts.match('#FirstName the #Adjective').tag('Person', 'correction-determiner5'); - //very common-but-ambiguous lastnames - ts.match('#FirstName (green|white|brown|hall|young|king|hill|cook|gray|price)').tag('#Person', 'firstname-maybe'); - //Joe K. Sombrero - ts.match('#FirstName #Acronym #Noun') - .ifNo('#Date') - .tag('#Person', 'n-acro-noun') - .lastTerm() - .tag('#LastName', 'n-acro-noun'); - // Dwayne 'the rock' Johnson - ts.match('#FirstName [#Determiner? #Noun] #LastName') - .tag('#NickName', 'first-noun-last') - .tag('#Person', 'first-noun-last'); - - //john bodego's - ts.match('#FirstName (#Singular|#Possessive)') - .ifNo('#Date') - .ifNo('#NickName') - .tag('#Person', 'first-possessive') - .lastTerm() - .tag('#LastName', 'first-possessive'); - } - - //methods requiring a lastname match - if (ts.has('#LastName')) { - // x Lastname - ts.match('#Noun #LastName') - .firstTerm() - .canBe('#FirstName') - .tag('#FirstName', 'noun-lastname'); - //ambiguous-but-common firstnames - ts.match('(will|may|april|june|said|rob|wade|ray|rusty|drew|miles|jack|chuck|randy|jan|pat|cliff|bill) #LastName') - .firstTerm() - .tag('#FirstName', 'maybe-lastname'); - //Jani K. Smith - ts.match('#TitleCase #Acronym? #LastName') - .ifNo('#Date') - .tag('#Person', 'title-acro-noun') - .lastTerm() - .tag('#LastName', 'title-acro-noun'); - //is foo Smith - ts.match('#Copula (#Noun|#PresentTense) #LastName') - .term(1) - .tag('#FirstName', 'copula-noun-lastname'); - } - - //methods requiring a titlecase - if (ts.has('#TitleCase')) { - ts.match('#Acronym #TitleCase') - .canBe('#Person') - .tag('#Person', 'acronym-titlecase'); - //ludwig van beethovan - ts.match('#TitleCase (van|al|bin) #TitleCase') - .canBe('#Person') - .tag('Person', 'correction-titlecase-van-titlecase'); - ts.match('#TitleCase (de|du) la? #TitleCase') - .canBe('#Person') - .tag('Person', 'correction-titlecase-van-titlecase'); - //Morgan Shlkjsfne - ts.match('#Person #TitleCase') - .match('#TitleCase #Noun') - .canBe('#Person') - .tag('Person', 'correction-person-titlecase'); - //pope francis - ts.match('(lady|queen|sister) #TitleCase') - .ifNo('#Date') - .ifNo('#Honorific') - .tag('#FemaleName', 'lady-titlecase'); - ts.match('(king|pope|father) #TitleCase') - .ifNo('#Date') - .tag('#MaleName', 'correction-poe'); - } - - //j.k Rowling - ts.match('#Noun van der? #Noun') - .canBe('#Person') - .tag('#Person', 'von der noun'); - //king of spain - ts.match('(king|queen|prince|saint|lady) of? #Noun') - .canBe('#Person') - .tag('#Person', 'king-of-noun'); - //mr X - ts.match('#Honorific #Acronym').tag('Person', 'Honorific-TitleCase'); - //peter II - ts.match('#Person #Person the? #RomanNumeral').tag('Person', 'correction-roman-numeral'); - - //'Professor Fink', 'General McCarthy' - ts.match('#Honorific #Person').tag('Person', 'Honorific-Person'); - - //remove single 'mr' - ts.match('^#Honorific$').unTag('Person', 'single-honorific'); - - return ts; -}; - -module.exports = person_step; diff --git a/src/tagger/steps/19-organization_step.js b/src/tagger/steps/19-organization_step.js deleted file mode 100644 index 1f7cc9432..000000000 --- a/src/tagger/steps/19-organization_step.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; -//orgwords like 'bank' in 'Foo Bank' -let orgWords = require('../../world/more-data/orgWords'); - -//could this word be an organization -const maybeOrg = function(t) { - //must be a noun - if (!t.tags.Noun) { - return false; - } - //can't be these things - if (t.tags.Pronoun || t.tags.Comma || t.tags.Possessive || t.tags.Place) { - return false; - } - //must be one of these - if (t.tags.TitleCase || t.tags.Organization || t.tags.Acronym) { - return true; - } - return false; -}; - -const organization_step = ts => { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (orgWords.hasOwnProperty(t.root) === true) { - //eg. Toronto University - let lastTerm = ts.terms[i - 1]; - if (lastTerm && maybeOrg(lastTerm)) { - lastTerm.tag('Organization', 'org-word-1'); - t.tag('Organization', 'org-word-2'); - continue; - } - //eg. University of Toronto - let nextTerm = ts.terms[i + 1]; - if (nextTerm && nextTerm.normal === 'of') { - if (ts.terms[i + 2] && maybeOrg(ts.terms[i + 2])) { - t.tag('Organization', 'org-of-word-1'); - nextTerm.tag('Organization', 'org-of-word-2'); - ts.terms[i + 2].tag('Organization', 'org-of-word-3'); - continue; - } - } - } - } - if (ts.has('#Acronym')) { - ts.match('the #Acronym').not('(iou|fomo|yolo|diy|dui|nimby)').lastTerm().tag('Organization', 'the-acronym'); - ts.match('#Acronym').match('#Possessive').tag('Organization', 'possessive-acronym'); - } - return ts; -}; -module.exports = organization_step; diff --git a/src/tagger/steps/20-parentheses_step.js b/src/tagger/steps/20-parentheses_step.js deleted file mode 100644 index ff4392747..000000000 --- a/src/tagger/steps/20-parentheses_step.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -//tag the words between '(' and ')' as #Parentheses -const parenthesesStep = function(ts) { - ts.terms.forEach((t, i) => { - if (t.tags.StartBracket) { - for(let o = i; o < ts.terms.length; o += 1) { - if (ts.terms[o].tags.EndBracket === true) { - ts.slice(i, o + 1).tag('Parentheses'); - break; - } - } - } - }); - return ts; -}; -module.exports = parenthesesStep; diff --git a/src/tagger/steps/21-plural_step.js b/src/tagger/steps/21-plural_step.js deleted file mode 100644 index f95e684ff..000000000 --- a/src/tagger/steps/21-plural_step.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -const isPlural = require('../../subset/nouns/isPlural'); - -const pluralStep = function(ts) { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (t.tags.Noun) { - //skip existing fast - if (t.tags.Singular || t.tags.Plural) { - continue; - } - //check if it's plural - let plural = isPlural(t, t.world); //can be null if unknown - if (plural === true) { - t.tag('Plural', 'pluralStep'); - } else if (plural === false) { - t.tag('Singular', 'pluralStep'); - } - } - } - return ts; -}; - -module.exports = pluralStep; diff --git a/src/tagger/steps/22-value_step.js b/src/tagger/steps/22-value_step.js deleted file mode 100644 index 4b8be6345..000000000 --- a/src/tagger/steps/22-value_step.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; -//regs- -const numericCardinal = /^\$?[0-9,](\.[0-9])?/; -const isOrdinal = /[0-9](st|nd|rd|th)$/; -// const hasText = /^[a-z]/; - -const value_step = function(ts) { - for(let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (t.tags.Value === true) { - //ordinal/cardinal - if (t.tags.Ordinal === undefined && t.tags.Cardinal === undefined) { - if (numericCardinal.test(t.normal) === true) { - t.tag('Cardinal', 'cardinal-val-regex'); - t.tag('NumericValue', 'NumericValue-regex'); - } else if (isOrdinal.test(t.normal) === true) { - t.tag('Ordinal', 'ordinal-value-regex'); - t.tag('NumericValue', 'NumericValue-regex'); - } - } - } - } - //5 books - ts.match('#Cardinal [#Plural]').tag('Unit', 'cardinal-plural'); - //5th book - ts.match('#Ordinal [#Singular]').tag('Unit', 'ordinal-singular'); - //1 book - ts.match('(one|first|1|1st) [#Singular]').tag('Unit', 'one-singular'); - return ts; -}; - -module.exports = value_step; diff --git a/src/tagger/steps/23-corrections.js b/src/tagger/steps/23-corrections.js deleted file mode 100644 index 658cb72ff..000000000 --- a/src/tagger/steps/23-corrections.js +++ /dev/null @@ -1,300 +0,0 @@ -'use strict'; - -//mostly pos-corections here -const corrections = function(ts) { - //ambig prepositions/conjunctions - if (ts.has('so')) { - //so funny - ts.match('so #Adjective').match('so').tag('Adverb', 'so-adv'); - //so the - ts.match('so #Noun').match('so').tag('Conjunction', 'so-conj'); - //do so - ts.match('do so').match('so').tag('Noun', 'so-noun'); - } - if (ts.has('all')) { - //all students - ts.match('[all] #Determiner? #Noun').tag('Adjective', 'all-noun'); - //it all fell apart - ts.match('[all] #Verb').tag('Adverb', 'all-verb'); - } - //the ambiguous word 'that' and 'which' - if (ts.has('(that|which)')) { - //remind john that - ts.match('#Verb #Adverb? #Noun (that|which)').lastTerm().tag('Preposition', 'that-prep'); - //that car goes - ts.match('that #Noun #Verb').firstTerm().tag('Determiner', 'that-determiner'); - //work, which has been done. - ts.match('#Comma [which] (#Pronoun|#Verb)').tag('Preposition', 'which-copula'); - //things that provide - // ts.match('#Plural (that|which) #Adverb? #Verb').term(1).tag('Preposition', 'noun-that'); - } - //Determiner-signals - if (ts.has('#Determiner')) { - //the wait to vote - ts.match('(the|this) [#Verb] #Preposition .').tag('Noun', 'correction-determiner1'); - //the swim - ts.match('(the|those|these) (#Infinitive|#PresentTense|#PastTense)').term(1).tag('Noun', 'correction-determiner2'); - //a staggering cost - ts.match('(a|an) [#Gerund]').tag('Adjective', 'correction-a|an'); - ts.match('(a|an) #Adjective (#Infinitive|#PresentTense)').term(2).tag('Noun', 'correction-a|an2'); - //some pressing issues - ts.match('some [#Verb] #Plural').tag('Noun', 'correction-determiner6'); - //the test string - ts.match('#Determiner [#Infinitive] #Noun').tag('Noun', 'correction-determiner7'); - //the orange. - ts.match('#Determiner #Adjective$').not('(#Comparative|#Superlative)').term(1).tag('Noun', 'the-adj-1'); - //the orange is - ts.match('#Determiner [#Adjective] (#Copula|#PastTense|#Auxiliary)').tag('Noun', 'the-adj-2'); - //the nice swim - ts.match('(the|this|those|these) #Adjective [#Verb]').tag('Noun', 'the-adj-verb'); - //the truly nice swim - ts.match('(the|this|those|these) #Adverb #Adjective [#Verb]').tag('Noun', 'correction-determiner4'); - //a stream runs - ts.match('(the|this|a|an) [#Infinitive] #Adverb? #Verb').tag('Noun', 'correction-determiner5'); - //a sense of - ts.match('#Determiner [#Verb] of').tag('Noun', 'the-verb-of'); - //the threat of force - ts.match('#Determiner #Noun of [#Verb]').tag('Noun', 'noun-of-noun'); - //a close - ts.match('#Determiner #Adverb? [close]').tag('Adjective', 'a-close'); - //did a 900, paid a 20 - ts.match('#Verb (a|an) [#Value]').tag('Singular', 'a-value'); - //a tv show - ts.match('(a|an) #Noun [#Infinitive]').tag('Noun', 'a-noun-inf'); - } - - //like - if (ts.has('like')) { - ts.match('just [like]').tag('Preposition', 'like-preposition'); - //folks like her - ts.match('#Noun [like] #Noun').tag('Preposition', 'noun-like'); - //look like - ts.match('#Verb [like]').tag('Adverb', 'verb-like'); - //exactly like - ts.match('#Adverb like').not('(really|generally|typically|usually|sometimes|often) like').lastTerm().tag('Adverb', 'adverb-like'); - } - - if (ts.has('#Value')) { - //half a million - ts.match('half a? #Value').tag('Value', 'half-a-value'); //quarter not ready - ts.match('#Value and a (half|quarter)').tag('Value', 'value-and-a-half'); - //all values are either ordinal or cardinal - // ts.match('#Value').match('!#Ordinal').tag('#Cardinal', 'not-ordinal'); - //money - ts.match('#Value+ #Currency').tag('Money', 'value-currency').lastTerm().tag('Unit', 'money-unit'); - ts.match('#Money and #Money #Currency?').tag('Money', 'money-and-money'); - //1 800 PhoneNumber - ts.match('1 #Value #PhoneNumber').tag('PhoneNumber', '1-800-Value'); - //(454) 232-9873 - ts.match('#NumericValue #PhoneNumber').tag('PhoneNumber', '(800) PhoneNumber'); - //two hundredth - ts.match('#TextValue+').match('#Cardinal+ #Ordinal').tag('Ordinal', 'two-hundredth'); - } - - if (ts.has('#Noun')) { - //'more' is not always an adverb - ts.match('more #Noun').tag('Noun', 'more-noun'); - //the word 'second' - ts.match('[second] #Noun').not('#Honorific').unTag('Unit').tag('Ordinal', 'second-noun'); - //he quickly foo - ts.match('#Noun #Adverb [#Noun]').tag('Verb', 'correction'); - //fix for busted-up phrasalVerbs - ts.match('#Noun [#Particle]').tag('Preposition', 'repair-noPhrasal'); - //John & Joe's - ts.match('#Noun (&|n) #Noun').tag('Organization', 'Noun-&-Noun'); - //Aircraft designer - ts.match('#Noun #Actor').tag('Actor', 'thing-doer'); - //this rocks - ts.match('(this|that) [#Plural]').tag('PresentTense', 'this-verbs'); - //by a bear. - ts.match('#Determiner #Infinitive$').lastTerm().tag('Noun', 'a-inf'); - //the western line - ts.match('#Determiner [(western|eastern|northern|southern|central)] #Noun').tag('Noun', 'western-line'); - ts.match('(#Determiner|#Value) [(linear|binary|mobile|lexical|technical|computer|scientific|formal)] #Noun').tag('Noun', 'technical-noun'); - //organization - if (ts.has('#Organization')) { - ts.match('#Organization of the? #TitleCase').tag('Organization', 'org-of-place'); - ts.match('#Organization #Country').tag('Organization', 'org-country'); - ts.match('(world|global|international|national|#Demonym) #Organization').tag('Organization', 'global-org'); - } - if (ts.has('#Possessive')) { - //my buddy - ts.match('#Possessive [#FirstName]').unTag('Person', 'possessive-name'); - //spencer kelly's - ts.match('#FirstName #Acronym? #Possessive').notIf('#Comma').match('#FirstName #Acronym? #LastName').tag('Possessive'); - //Super Corp's fundraiser - ts.match('#Organization+ #Possessive').notIf('#Comma').tag('Possessive'); - //Los Angeles's fundraiser - ts.match('#Place+ #Possessive').notIf('#Comma').tag('Possessive'); - } - } - - if (ts.has('#Verb')) { - //still make - ts.match('[still] #Verb').tag('Adverb', 'still-verb'); - //'u' as pronoun - ts.match('[u] #Verb').tag('Pronoun', 'u-pronoun-1'); - //is no walk - ts.match('is no [#Verb]').tag('Noun', 'is-no-verb'); - //different views than - ts.match('[#Verb] than').tag('Noun', 'correction'); - //her polling - ts.match('#Possessive [#Verb]').tag('Noun', 'correction-possessive'); - //there are reasons - ts.match('there (are|were) #Adjective? [#PresentTense]').tag('Plural', 'there-are'); - //jack seems guarded - ts.match('#Singular (seems|appears) #Adverb? [#PastTense$]').tag('Adjective', 'seems-filled'); - - if (ts.has('(who|what|where|why|how|when)')) { - //the word 'how' - ts.match('^how').tag('QuestionWord', 'how-question').tag('QuestionWord', 'how-question'); - ts.match('how (#Determiner|#Copula|#Modal|#PastTense)').term(0).tag('QuestionWord', 'how-is'); - // //the word 'which' - ts.match('^which').tag('QuestionWord', 'which-question').tag('QuestionWord', 'which-question'); - ts.match('which . (#Noun)+ #Pronoun').term(0).tag('QuestionWord', 'which-question2'); - ts.match('which').tag('QuestionWord', 'which-question3'); - //where - - //how he is driving - let word = ts.match('#QuestionWord #Noun #Copula #Adverb? (#Verb|#Adjective)').firstTerm(); - word.unTag('QuestionWord').tag('Conjunction', 'how-he-is-x'); - //when i go fishing - word = ts.match('#QuestionWord #Noun #Adverb? #Infinitive not? #Gerund').firstTerm(); - word.unTag('QuestionWord').tag('Conjunction', 'when i go fishing'); - } - - if (ts.has('#Copula')) { - //is eager to go - ts.match('#Copula #Adjective to #Verb').match('#Adjective to').tag('Verb', 'correction'); - //is mark hughes - ts.match('#Copula [#Infinitive] #Noun').tag('Noun', 'is-pres-noun'); - - ts.match('[#Infinitive] #Copula').tag('Noun', 'infinitive-copula'); - //sometimes adverbs - 'pretty good','well above' - ts.match('#Copula (pretty|dead|full|well) (#Adjective|#Noun)').notIf('#Comma').tag('#Copula #Adverb #Adjective', 'sometimes-adverb'); - //sometimes not-adverbs - ts.match('#Copula [(just|alone)$]').tag('Adjective', 'not-adverb'); - //jack is guarded - ts.match('#Singular is #Adverb? [#PastTense$]').tag('Adjective', 'is-filled'); - } - //went to sleep - // ts.match('#Verb to #Verb').lastTerm().tag('Noun', 'verb-to-verb'); - //support a splattering of auxillaries before a verb - let advb = '(#Adverb|not)+?'; - if (ts.has(advb)) { - //had walked - ts.match(`(has|had) ${advb} #PastTense`).not('#Verb$').tag('Auxiliary', 'had-walked'); - //was walking - ts.match(`#Copula ${advb} #Gerund`).not('#Verb$').tag('Auxiliary', 'copula-walking'); - //been walking - ts.match(`(be|been) ${advb} #Gerund`).not('#Verb$').tag('Auxiliary', 'be-walking'); - //would walk - ts.match(`(#Modal|did) ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'modal-verb'); - //would have had - ts.match(`#Modal ${advb} have ${advb} had ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'would-have'); - //would be walking - ts.match(`(#Modal) ${advb} be ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'would-be'); - //would been walking - ts.match(`(#Modal|had|has) ${advb} been ${advb} #Verb`).not('#Verb$').tag('Auxiliary', 'would-be'); - //infinitive verbs suggest plural nouns - 'XYZ walk to the store' - // r.match(`#Singular+ #Infinitive`).match('#Singular+').tag('Plural', 'infinitive-make-plural'); - } - //fall over - ts.match('#PhrasalVerb #PhrasalVerb').lastTerm().tag('Particle', 'phrasal-particle'); - if (ts.has('#Gerund')) { - //walking is cool - ts.match('#Gerund #Adverb? not? #Copula').firstTerm().tag('Activity', 'gerund-copula'); - //walking should be fun - ts.match('#Gerund #Modal').firstTerm().tag('Activity', 'gerund-modal'); - //running-a-show - ts.match('#Gerund #Determiner [#Infinitive]').tag('Noun', 'running-a-show'); - //setting records - // ts.match('#Gerund [#PresentTense]').tag('Plural', 'setting-records'); - } - //will be cool -> Copula - if (ts.has('will #Adverb? not? #Adverb? be')) { - //will be running (not copula - if (ts.has('will #Adverb? not? #Adverb? be #Gerund') === false) { - //tag it all - ts.match('will not? be').tag('Copula', 'will-be-copula'); - //for more complex forms, just tag 'be' - ts.match('will #Adverb? not? #Adverb? be #Adjective').match('be').tag('Copula', 'be-copula'); - } - } - } - - if (ts.has('#Adjective')) { - //still good - ts.match('still #Adjective').match('still').tag('Adverb', 'still-advb'); - //big dreams, critical thinking - ts.match('#Adjective [#PresentTense]').tag('Noun', 'adj-presentTense'); - //will secure our - ts.match('will [#Adjective]').tag('Verb', 'will-adj'); - //cheering hard - dropped -ly's - ts.match('#PresentTense (hard|quick|long|bright|slow)').lastTerm().tag('Adverb', 'lazy-ly'); - //his fine - ts.match('(his|her|its) [#Adjective]').tag('Noun', 'his-fine'); - // - ts.match('#Noun #Adverb? [left]').tag('PastTense', 'left-verb'); - } - - if (ts.has('#TitleCase')) { - //FitBit Inc - ts.match('#TitleCase (ltd|co|inc|dept|assn|bros)').tag('Organization', 'org-abbrv'); - //Foo District - ts - .match('#TitleCase+ (district|region|province|county|prefecture|municipality|territory|burough|reservation)') - .tag('Region', 'foo-district'); - //District of Foo - ts - .match('(district|region|province|municipality|territory|burough|state) of #TitleCase') - .tag('Region', 'district-of-Foo'); - } - - if (ts.has('#Hyphenated')) { - //air-flow - ts.match('#Hyphenated #Hyphenated').match('#Noun #Verb').tag('Noun', 'hyphen-verb'); - let hyphen = ts.match('#Hyphenated+'); - if (hyphen.has('#Expression')) { - //ooh-wee - hyphen.tag('Expression', 'ooh-wee'); - } - } - - if (ts.has('#Place')) { - //West Norforlk - ts.match('(west|north|south|east|western|northern|southern|eastern)+ #Place').tag('Region', 'west-norfolk'); - //some us-state acronyms (exlude: al, in, la, mo, hi, me, md, ok..) - ts.match('#City [#Acronym]').match('(al|ak|az|ar|ca|ct|dc|fl|ga|id|il|nv|nh|nj|ny|oh|or|pa|sc|tn|tx|ut|vt|pr)').tag('Region', 'us-state'); - } - //misc: - //foot/feet - ts.match('(foot|feet)').tag('Noun', 'foot-noun'); - ts.match('#Value (foot|feet)').term(1).tag('Unit', 'foot-unit'); - //'u' as pronoun - ts.match('#Conjunction [u]').tag('Pronoun', 'u-pronoun-2'); - //'a/an' can mean 1 - "a hour" - ts.match('(a|an) (#Duration|hundred|thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion)').ifNo('#Plural').term(0).tag('Value', 'a-is-one'); - //swear-words as non-expression POS - //nsfw - ts.match('holy (shit|fuck|hell)').tag('Expression', 'swears-expression'); - ts.match('#Determiner (shit|damn|hell)').term(1).tag('Noun', 'swears-noun'); - ts.match('(shit|damn|fuck) (#Determiner|#Possessive|them)').term(0).tag('Verb', 'swears-verb'); - ts.match('#Copula fucked up?').not('#Copula').tag('Adjective', 'swears-adjective'); - //6 am - ts.match('#Holiday (day|eve)').tag('Holiday', 'holiday-day'); - //timezones - ts.match('(standard|daylight|summer|eastern|pacific|central|mountain) standard? time').tag('Time', 'timezone'); - //canadian dollar, Brazilian pesos - ts.match('#Demonym #Currency').tag('Currency', 'demonym-currency'); - //about to go - ts.match('about to #Adverb? #Verb').match('about to').tag(['Auxiliary', 'Verb'], 'about-to'); - //Doctor john smith jr - ts.match('#Honorific #Person').tag('Person', 'honorific-person'); - ts.match('#Person (jr|sr|md)').tag('Person', 'person-honorific'); - //right of way - ts.match('(right|rights) of .').tag('Noun', 'right-of'); - return ts; -}; - -module.exports = corrections; diff --git a/src/tagger/steps/24-proper_noun.js b/src/tagger/steps/24-proper_noun.js deleted file mode 100644 index 3e50dfcf8..000000000 --- a/src/tagger/steps/24-proper_noun.js +++ /dev/null @@ -1,15 +0,0 @@ - -//a specificly-named thing, that should be capitalized -const properNoun = function(ts) { - if (ts.has('#Person') === true) { - ts.match('#FirstName #Person+').tag('ProperNoun'); - ts.match('#Person+ #LastName').tag('ProperNoun'); - } - if (ts.has('#Place') === true) { - ts.match('(#City|#Region|#Country)').tag('ProperNoun'); - } - ts.match('#Organization').tag('ProperNoun'); - ts.match('#Month').tag('ProperNoun'); - return ts; -}; -module.exports = properNoun; diff --git a/src/tagger/steps/25-custom.js b/src/tagger/steps/25-custom.js deleted file mode 100644 index 5ce3a4c82..000000000 --- a/src/tagger/steps/25-custom.js +++ /dev/null @@ -1,10 +0,0 @@ - -//patterns are .match() statements to be run after the tagger -const posthoc = function(ts) { - const patterns = ts.world.patterns; - Object.keys(patterns).forEach((k) => { - ts.match(k).tag(patterns[k], 'post-hoc: ' + k); - }); - return ts; -}; -module.exports = posthoc; diff --git a/src/tagger/steps/contraction/01-irregulars.js b/src/tagger/steps/contraction/01-irregulars.js deleted file mode 100644 index d3096fe5c..000000000 --- a/src/tagger/steps/contraction/01-irregulars.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; -const fixContraction = require('./fix'); - -const irregulars = { - wanna: ['want', 'to'], - gonna: ['going', 'to'], - im: ['i', 'am'], - alot: ['a', 'lot'], - - dont: ['do', 'not'], - dun: ['do', 'not'], - - ive: ['i', 'have'], - - "won't": ['will', 'not'], - wont: ['will', 'not'], - - "can't": ['can', 'not'], - cant: ['can', 'not'], - cannot: ['can', 'not'], - - // aint: ['is', 'not'], //or 'are' - // "ain't": ['is', 'not'], - "shan't": ['should', 'not'], - imma: ['I', 'will'], - - "where'd": ['where', 'did'], - whered: ['where', 'did'], - "when'd": ['when', 'did'], - whend: ['when', 'did'], - "how'd": ['how', 'did'], - howd: ['how', 'did'], - "what'd": ['what', 'did'], - whatd: ['what', 'did'], - "let's": ['let', 'us'], - - //multiple word contractions - dunno: ['do', 'not', 'know'], - brb: ['be', 'right', 'back'], - gtg: ['got', 'to', 'go'], - irl: ['in', 'real', 'life'], - tbh: ['to', 'be', 'honest'], - imo: ['in', 'my', 'opinion'], - til: ['today', 'i', 'learned'], - rn: ['right', 'now'], - twas: ['it', 'was'], - '@': ['at'] -}; - -//check irregulars -const checkIrregulars = ts => { - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - if (irregulars[t.normal]) { - let fix = irregulars[t.normal]; - ts = fixContraction(ts, fix, i); - i += fix.length - 1; - } - } - return ts; -}; -module.exports = checkIrregulars; diff --git a/src/tagger/steps/contraction/02-isWasHas.js b/src/tagger/steps/contraction/02-isWasHas.js deleted file mode 100644 index a60742738..000000000 --- a/src/tagger/steps/contraction/02-isWasHas.js +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; -const fixContraction = require('./fix'); -const splitContraction = require('./split'); - -//these are always contractions -const blacklist = { - 'that\'s': true, - 'there\'s': true -}; -const are = { - we: true, - they: true, - you: true -}; - -// "'s" may be a contraction or a possessive -// 'spencer's house' vs 'spencer's good' -const isPossessive = (ts, i) => { - let t = ts.terms[i]; - let next_t = ts.terms[i + 1]; - //a pronoun can't be possessive - "he's house" - if (t.tags.Pronoun || t.tags.QuestionWord) { - return false; - } - if (blacklist[t.normal]) { - return false; - } - //if end of sentence, it is possessive - "was spencer's" - if (!next_t) { - return true; - } - //an infinitive is probably mis-tagged - 'jamie's bite' - if (next_t.tags.Infinitive) { - return true; - } - //a gerund suggests 'is walking' - if (next_t.tags.VerbPhrase) { - return false; - } - //spencer's house - if (next_t.tags.Noun) { - return true; - } - //rocket's red glare - if (next_t.tags.Adjective && ts.terms[i + 2] && ts.terms[i + 2].tags.Noun) { - return true; - } - //an adjective suggests 'is good' - if (next_t.tags.Adjective || next_t.tags.Adverb || next_t.tags.Verb) { - return false; - } - return false; -}; - -// you ain't / i ain't. -const isAre = function(ts, i) { - let arr = ['is', 'not']; //default - //get what's it 'about' - if (ts.terms[i - 1]) { - let about = ts.terms[i - 1]; - //go back one more.. - if (about.tags.Adverb && ts.terms[i - 2]) { - about = ts.terms[i - 2]; - } - if (about.tags.Plural || are[about.normal] === true) { - arr[0] = 'are'; - } - } - return arr; -}; - -//handle ambigous contraction "'s" -const hardOne = ts => { - for (let i = 0; i < ts.terms.length; i++) { - //skip existing - if (ts.terms[i].silent_term) { - continue; - } - if (ts.terms[i].normal === 'ain\'t' || ts.terms[i].normal === 'aint') { - let arr = isAre(ts, i); - ts = fixContraction(ts, arr, i); - i += 1; - continue; - } - let parts = splitContraction(ts.terms[i]); - if (parts) { - //have we found a hard one - if (parts.end === 's') { - //spencer's house - if (isPossessive(ts, i)) { - ts.terms[i].tag('#Possessive', 'hard-contraction'); - continue; - } - let arr = [parts.start, 'is']; - if (ts.terms[i + 1]) { - let str = ts.terms[i].normal; - //he's walking -> is/was - if (ts.match(str + ' (#Negative|#Adverb|#Auxiliary)+? #Gerund').found) { - arr = [parts.start, 'is']; - } else if (ts.match(str + ' (#Negative|#Adverb|#Auxiliary)+? #Verb').found) { - //is vs has ('he's got milk') - arr = [parts.start, 'has']; - } - } - ts = fixContraction(ts, arr, i); - i += 1; - } - } - } - return ts; -}; - -module.exports = hardOne; diff --git a/src/tagger/steps/contraction/03-easyOnes.js b/src/tagger/steps/contraction/03-easyOnes.js deleted file mode 100644 index f2a2f0d9e..000000000 --- a/src/tagger/steps/contraction/03-easyOnes.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict'; -const fixContraction = require('./fix'); -const split = require('./split'); - -//the formulaic contraction types: -const easy_ends = { - ll: 'will', - // 'd': 'would', - ve: 'have', - re: 'are', - m: 'am', - 'n\'t': 'not' -//these ones are a bit tricksier: -// 't': 'not', -// 's': 'is' //or was -}; - -//unambiguous contractions, like "'ll" -const easyOnes = ts => { - for (let i = 0; i < ts.terms.length; i++) { - //skip existing - if (ts.terms[i].silent_term) { - continue; - } - let parts = split(ts.terms[i]); - if (parts) { - parts.start = parts.start.toLowerCase(); - - //make sure its an easy one - if (easy_ends[parts.end]) { - let arr = [parts.start, easy_ends[parts.end]]; - ts = fixContraction(ts, arr, i); - i += 1; - } - - //handle i'd -> 'i would' vs 'i had' - if (parts.end === 'd') { - //assume 'would' - let arr = [parts.start, 'would']; - //if next verb is past-tense, choose 'had' - if (ts.terms[i + 1] && ts.terms[i + 1].tags.PastTense) { - arr[1] = 'had'; - } - //also support '#Adverb #PastTense' - if (ts.terms[i + 2] && ts.terms[i + 2].tags.PastTense && ts.terms[i + 1].tags.Adverb) { - arr[1] = 'had'; - } - ts = fixContraction(ts, arr, i); - i += 1; - } - } - } - return ts; -}; -module.exports = easyOnes; diff --git a/src/tagger/steps/contraction/04-numberRange.js b/src/tagger/steps/contraction/04-numberRange.js deleted file mode 100644 index 5b961d606..000000000 --- a/src/tagger/steps/contraction/04-numberRange.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; -const fixContraction = require('./fix'); -const Term = require('../../../term'); - -const hasDash = function(t) { - let dashes = /(-|–|—)/; - return dashes.test(t.whitespace.before) || dashes.test(t.whitespace.after); -}; - -const numberRange = ts => { - //try to support number range, like 5-9, this way: - ts.match('#Hyphenated #Hyphenated').match('#NumericValue #NumericValue').tag('NumberRange'); - //otherwise, loop through and find them - for (let i = 0; i < ts.terms.length; i++) { - let t = ts.terms[i]; - //skip existing - if (t.silent_term) { - continue; - } - if (t.tags.TextValue) { - continue; - } - //hyphens found in whitespace - '5 - 7' - if (t.tags.Value && ts.terms[i + 1] && i > 0 && (hasDash(t) || hasDash(ts.terms[i - 1])) && ts.terms[i - 1].tags.Value) { - let to = new Term('', ts.world); - to.silent_term = 'to'; - ts.insertAt(i, to); - ts.terms[i - 1].tag('NumberRange', 'number-number1'); - ts.terms[i].tag('NumberRange', 'number-number2'); - ts.terms[i].whitespace.before = ''; - ts.terms[i].whitespace.after = ''; - ts.terms[i + 1].tag('NumberRange', 'number-number3'); - return ts; - } - //add a silent term - if (t.tags.NumberRange) { - let arr = t.text.split(/(-|–|—)/); - arr[1] = 'to'; - ts = fixContraction(ts, arr, i); - ts.terms[i].tag(['NumberRange', 'NumericValue'], 'numRange-1'); - ts.terms[i + 1].tag(['NumberRange', 'Preposition'], 'numRange-silent'); - ts.terms[i + 2].tag(['NumberRange', 'NumericValue'], 'numRange-3'); - i += 2; - } - } - return ts; -}; -module.exports = numberRange; diff --git a/src/tagger/steps/contraction/fix.js b/src/tagger/steps/contraction/fix.js deleted file mode 100644 index 561f80213..000000000 --- a/src/tagger/steps/contraction/fix.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; -const Term = require('../../../term'); - -const tags = { - not: 'Negative', - will: 'Verb', - would: 'Modal', - have: 'Verb', - are: 'Copula', - is: 'Copula', - am: 'Verb' -}; -//make sure the newly created term gets the easy tags -const easyTag = t => { - if (tags[t.silent_term]) { - t.tag(tags[t.silent_term]); - } -}; - -//add a silent term -const fixContraction = (ts, parts, i) => { - //add the interpretation to the contracted term - let one = ts.terms[i]; - one.silent_term = parts[0]; - //tag it as a contraction - one.tag('Contraction', 'tagger-contraction'); - - //add a new empty term - if (parts[1]) { - let two = new Term('', ts.world); - two.silent_term = parts[1]; - two.tag('Contraction', 'tagger-contraction'); - ts.insertAt(i + 1, two); - //ensure new term has no auto-whitspace - two.whitespace.before = ''; - two.whitespace.after = ''; - easyTag(two); - } - - //potentially it's three-contracted-terms, like 'dunno' - if (parts[2]) { - let three = new Term('', ts.world); - three.silent_term = parts[2]; - // ts.terms.push(three); - ts.insertAt(i + 2, three); - three.tag('Contraction', 'tagger-contraction'); - easyTag(three); - } - - return ts; -}; - -module.exports = fixContraction; diff --git a/src/tagger/steps/contraction/split.js b/src/tagger/steps/contraction/split.js deleted file mode 100644 index 621a62d5f..000000000 --- a/src/tagger/steps/contraction/split.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; -const contraction = /^([a-z]+)'([a-z][a-z]?)$/i; -const possessive = /[a-z]s'$/i; - -const allowed = { - re: 1, - ve: 1, - ll: 1, - t: 1, - s: 1, - d: 1, - m: 1 -}; - -/** interpret a terms' contraction */ -const splitContraction = t => { - //handle this irregular one (shared trailing n) - if (t.normal === 'can\'t') { - return { - start: 'can', - end: 'n\'t' - }; - } - let parts = t.normal.match(contraction); - if (parts && parts[1] && allowed[parts[2]] === 1) { - //handle n't - if (parts[2] === 't' && parts[1].match(/[a-z]n$/)) { - parts[1] = parts[1].replace(/n$/, ''); - parts[2] = 'n\'t'; //dunno.. - } - //fix titlecase - if (t.tags.TitleCase === true) { - parts[1] = parts[1].replace(/^[a-z]/, x => x.toUpperCase()); - } - return { - start: parts[1], - end: parts[2] - }; - } - // "flanders' house" - if (possessive.test(t.text) === true) { - return { - start: t.normal.replace(/s'?$/, ''), - end: '' - }; - } - return null; -}; -module.exports = splitContraction; diff --git a/src/tagger/steps/rules/emoji_regex.js b/src/tagger/steps/rules/emoji_regex.js deleted file mode 100644 index c906db000..000000000 --- a/src/tagger/steps/rules/emoji_regex.js +++ /dev/null @@ -1,3 +0,0 @@ -//yep, -//https://github.com/mathiasbynens/emoji-regex/blob/master/index.js -module.exports = /(?:0\u20E3\n1\u20E3|2\u20E3|3\u20E3|4\u20E3|5\u20E3|6\u20E3|7\u20E3|8\u20E3|9\u20E3|#\u20E3|\*\u20E3|\uD83C(?:\uDDE6\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF2|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFD|\uDDFF)|\uDDE7\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFC|\uDDFE|\uDDFF)|\uDDE8\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDE9\uD83C(?:\uDDEA|\uDDEC|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDFF)|\uDDEA\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDED|\uDDF7|\uDDF8|\uDDF9|\uDDFA)|\uDDEB\uD83C(?:\uDDEE|\uDDEF|\uDDF0|\uDDF2|\uDDF4|\uDDF7)|\uDDEC\uD83C(?:\uDDE6|\uDDE7|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDEE|\uDDF1|\uDDF2|\uDDF3|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFC|\uDDFE)|\uDDED\uD83C(?:\uDDF0|\uDDF2|\uDDF3|\uDDF7|\uDDF9|\uDDFA)|\uDDEE\uD83C(?:\uDDE8|\uDDE9|\uDDEA|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF6|\uDDF7|\uDDF8|\uDDF9)|\uDDEF\uD83C(?:\uDDEA|\uDDF2|\uDDF4|\uDDF5)|\uDDF0\uD83C(?:\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDF2|\uDDF3|\uDDF5|\uDDF7|\uDDFC|\uDDFE|\uDDFF)|\uDDF1\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDEE|\uDDF0|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFE)|\uDDF2\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF5|\uDDF6|\uDDF7|\uDDF8|\uDDF9|\uDDFA|\uDDFB|\uDDFC|\uDDFD|\uDDFE|\uDDFF)|\uDDF3\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEB|\uDDEC|\uDDEE|\uDDF1|\uDDF4|\uDDF5|\uDDF7|\uDDFA|\uDDFF)|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C(?:\uDDE6|\uDDEA|\uDDEB|\uDDEC|\uDDED|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF7|\uDDF8|\uDDF9|\uDDFC|\uDDFE)|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C(?:\uDDEA|\uDDF4|\uDDF8|\uDDFA|\uDDFC)|\uDDF8\uD83C(?:\uDDE6|\uDDE7|\uDDE8|\uDDE9|\uDDEA|\uDDEC|\uDDED|\uDDEE|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF8|\uDDF9|\uDDFB|\uDDFD|\uDDFE|\uDDFF)|\uDDF9\uD83C(?:\uDDE6|\uDDE8|\uDDE9|\uDDEB|\uDDEC|\uDDED|\uDDEF|\uDDF0|\uDDF1|\uDDF2|\uDDF3|\uDDF4|\uDDF7|\uDDF9|\uDDFB|\uDDFC|\uDDFF)|\uDDFA\uD83C(?:\uDDE6|\uDDEC|\uDDF2|\uDDF8|\uDDFE|\uDDFF)|\uDDFB\uD83C(?:\uDDE6|\uDDE8|\uDDEA|\uDDEC|\uDDEE|\uDDF3|\uDDFA)|\uDDFC\uD83C(?:\uDDEB|\uDDF8)|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C(?:\uDDEA|\uDDF9)|\uDDFF\uD83C(?:\uDDE6|\uDDF2|\uDDFC)))|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD79\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED0\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3]|\uD83E[\uDD10-\uDD18\uDD80-\uDD84\uDDC0]/g; diff --git a/src/tagger/steps/rules/emoticon_list.js b/src/tagger/steps/rules/emoticon_list.js deleted file mode 100644 index 88c6ab6b6..000000000 --- a/src/tagger/steps/rules/emoticon_list.js +++ /dev/null @@ -1,56 +0,0 @@ -//just some of the most common emoticons -//faster than -//http://stackoverflow.com/questions/28077049/regex-matching-emoticons -module.exports = { - ':(': true, - ':)': true, - ':P': true, - ':p': true, - ':O': true, - ':3': true, - ':|': true, - ':/': true, - ':\\': true, - ':$': true, - ':*': true, - ':@': true, - ':-(': true, - ':-)': true, - ':-P': true, - ':-p': true, - ':-O': true, - ':-3': true, - ':-|': true, - ':-/': true, - ':-\\': true, - ':-$': true, - ':-*': true, - ':-@': true, - ':^(': true, - ':^)': true, - ':^P': true, - ':^p': true, - ':^O': true, - ':^3': true, - ':^|': true, - ':^/': true, - ':^\\': true, - ':^$': true, - ':^*': true, - ':^@': true, - '):': true, - '(:': true, - '$:': true, - '*:': true, - ')-:': true, - '(-:': true, - '$-:': true, - '*-:': true, - ')^:': true, - '(^:': true, - '$^:': true, - '*^:': true, - '<3': true, - ' { - tags[k].downward = []; - //look for tags with this as parent - for (let i = 0; i < keys.length; i++) { - if (tags[keys[i]].isA && tags[keys[i]].isA === k) { - tags[k].downward.push(keys[i]); - } - } - }); -}; -module.exports = addDownword; diff --git a/src/tags/conflicts.js b/src/tags/conflicts.js deleted file mode 100644 index 86aa979f4..000000000 --- a/src/tags/conflicts.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -//list of inconsistent parts-of-speech -module.exports = [ - //top-level pos are all inconsistent - [ - 'Noun', - 'Verb', - 'Adjective', - 'Adverb', - 'Determiner', - 'Conjunction', - 'Preposition', - 'QuestionWord', - 'Expression', - 'Url', - 'PhoneNumber', - 'Email', - 'Emoji' - ], - //exlusive-nouns - ['Person', 'Organization', 'Value', 'Place', 'Actor', 'Demonym', 'Pronoun'], - //acronyms - ['Acronym', 'Pronoun', 'Actor', 'Unit', 'Address'], - ['Acronym', 'Plural'], - //things that can't be plural - ['Plural', 'Singular'], - // ['Plural', 'Pronoun'], - // ['Plural', 'Person'], - // ['Plural', 'Organization'], - // ['Plural', 'Currency'], - // ['Plural', 'Ordinal'], - //exlusive-people - ['MaleName', 'FemaleName'], - ['FirstName', 'LastName', 'Honorific'], - //adjectives - ['Comparative', 'Superlative'], - //values - ['Value', 'Verb', 'Adjective'], - // ['Value', 'Year'], - ['Ordinal', 'Cardinal'], - ['TextValue', 'NumericValue'], - ['NiceNumber', 'TextValue'], - ['Ordinal', 'Currency'], //$5.50th - //verbs - ['PastTense', 'PresentTense', 'FutureTense'], - ['Pluperfect', 'Copula', 'Modal', 'Participle', 'Infinitive', 'Gerund', 'FuturePerfect', 'PerfectTense'], - ['Auxiliary', 'Noun', 'Value'], - //date - ['Month', 'WeekDay', 'Year', 'Duration', 'Holiday'], - ['Particle', 'Conjunction', 'Adverb', 'Preposition'], - ['Date', 'Verb', 'Adjective', 'Person'], - ['Date', 'Money', 'RomanNumeral', 'Fraction'], - //a/an -> 1 - ['Value', 'Determiner'], - ['Url', 'Value', 'HashTag', 'PhoneNumber', 'Emoji'], - //roman numerals - ['RomanNumeral', 'Fraction', 'NiceNumber'], - ['RomanNumeral', 'Money'], - //cases - ['UpperCase', 'TitleCase', 'CamelCase'], - //phrases - ['VerbPhrase', 'Noun', 'Adjective', 'Value'], - //QuestionWord - ['QuestionWord', 'VerbPhrase'], - //acronyms - ['Acronym', 'VerbPhrase'], -]; diff --git a/src/tags/index.js b/src/tags/index.js deleted file mode 100644 index f7e3d00c3..000000000 --- a/src/tags/index.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; -const conflicts = require('./conflicts'); -const nouns = require('./tags/nouns'); -const verbs = require('./tags/verbs'); -const values = require('./tags/values'); -const dates = require('./tags/dates'); -const misc = require('./tags/misc'); -const addDownward = require('./addDownward'); - -//used for pretty-printing on the server-side -const colors = { - Noun: 'blue', - Date: 'red', - Value: 'red', - Verb: 'green', - Auxiliary: 'green', - Negative: 'green', - VerbPhrase: 'green', - Preposition: 'cyan', - Condition: 'cyan', - Conjunction: 'cyan', - Determiner: 'cyan', - Adjective: 'magenta', - Adverb: 'cyan' -}; - -//extend tagset with new tags -const addIn = function(obj, tags) { - Object.keys(obj).forEach(k => { - tags[k] = obj[k]; - }); -}; - -//add tags to remove when tagging this one -const addConflicts = function(tags) { - Object.keys(tags).forEach(k => { - tags[k].notA = {}; - for (let i = 0; i < conflicts.length; i++) { - let arr = conflicts[i]; - if (arr.indexOf(k) !== -1) { - arr = arr.filter(a => a !== k); - arr.forEach(e => { - tags[k].notA[e] = true; - }); - } - } - tags[k].notA = Object.keys(tags[k].notA); - }); -}; - -const addColors = function(tags) { - Object.keys(tags).forEach(k => { - if (colors[k]) { - tags[k].color = colors[k]; - return; - } - if (tags[k].isA && colors[tags[k].isA]) { - tags[k].color = colors[tags[k].isA]; - return; - } - if (tags[k].isA && tags[tags[k].isA].color) { - tags[k].color = tags[tags[k].isA].color; - } - }); -}; - -const build = () => { - let tags = {}; - addIn(nouns, tags); - addIn(verbs, tags); - addIn(values, tags); - addIn(dates, tags); - addIn(misc, tags); - //downstream - addDownward(tags); - //add enemies - addConflicts(tags); - //for nice-logging - addColors(tags); - return tags; -}; -module.exports = build(); diff --git a/src/tags/tags/dates.js b/src/tags/tags/dates.js deleted file mode 100644 index 79c9e5e94..000000000 --- a/src/tags/tags/dates.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - Date: {}, //not a noun, but usually is - Month: { - isA: 'Date', - also: 'Singular' - }, - WeekDay: { - isA: 'Date', - also: 'Noun' - }, - RelativeDay: { - isA: 'Date' - }, - Year: { - isA: 'Date' - }, - Duration: { - isA: 'Date', - also: 'Noun' - }, - Time: { - isA: 'Date', - also: 'Noun' - }, - Holiday: { - isA: 'Date', - also: 'Noun' - } -}; diff --git a/src/tags/tags/misc.js b/src/tags/tags/misc.js deleted file mode 100644 index 856d88ebd..000000000 --- a/src/tags/tags/misc.js +++ /dev/null @@ -1,68 +0,0 @@ -module.exports = { - Adjective: {}, - Comparable: { - isA: 'Adjective' - }, - Comparative: { - isA: 'Adjective' - }, - Superlative: { - isA: 'Adjective' - }, - - NumberRange: { - isA: 'Contraction' - }, - Adverb: {}, - - Currency: {}, - //glue - Determiner: {}, - Conjunction: {}, - Preposition: {}, - QuestionWord: {}, - RelativeProunoun: { - isA: 'Pronoun' - }, - Expression: {}, - Abbreviation: {}, - Url: {}, - PhoneNumber: {}, - HashTag: {}, - AtMention: { - is: 'Noun' - }, - Emoji: {}, - Email: {}, - - //non-exclusive - Condition: {}, - VerbPhrase: {}, - Auxiliary: {}, - Negative: {}, - Contraction: {}, - - TitleCase: {}, - CamelCase: {}, - UpperCase: {}, - Hyphenated: {}, - Acronym: {}, - ClauseEnd: {}, - - // Quotes - Quotation: {}, - StartQuotation: { - isA: 'Quotation' - }, - EndQuotation: { - isA: 'Quotation' - }, - //parentheses - Parentheses: {}, - EndBracket: { - isA: 'Parentheses' - }, - StartBracket: { - isA: 'Parentheses' - } -}; diff --git a/src/tags/tags/nouns.js b/src/tags/tags/nouns.js deleted file mode 100644 index a4a40bd21..000000000 --- a/src/tags/tags/nouns.js +++ /dev/null @@ -1,92 +0,0 @@ -module.exports = { - Noun: {}, - // - singular - Singular: { - isA: 'Noun' - }, - //a specific thing that's capitalized - ProperNoun: { - isA: 'Noun' - }, - - // -- people - Person: { - isA: 'Singular' - }, - FirstName: { - isA: 'Person' - }, - MaleName: { - isA: 'FirstName' - }, - FemaleName: { - isA: 'FirstName' - }, - LastName: { - isA: 'Person' - }, - Honorific: { - isA: 'Noun' - }, - Place: { - isA: 'Singular' - }, - - // -- places - Country: { - isA: 'Place' - }, - City: { - isA: 'Place' - }, - Region: { - isA: 'Place' - }, - Address: { - isA: 'Place' - }, - Organization: { - isA: 'Singular' - }, - SportsTeam: { - isA: 'Organization' - }, - Company: { - isA: 'Organization' - }, - School: { - isA: 'Organization' - }, - - // - plural - Plural: { - isA: 'Noun' - }, - Uncountable: { - //(not plural or singular) - isA: 'Noun' - }, - Pronoun: { - isA: 'Noun' - }, - //a word for someone doing something -'plumber' - Actor: { - isA: 'Noun' - }, - //a gerund-as-noun - 'swimming' - Activity: { - isA: 'Noun' - }, - //'kilograms' - Unit: { - isA: 'Noun' - }, - //'Canadians' - Demonym: { - isA: 'Noun' - }, - //`john's` - Possessive: { - isA: 'Noun' - } -}; diff --git a/src/tags/tags/values.js b/src/tags/tags/values.js deleted file mode 100644 index c6f774458..000000000 --- a/src/tags/tags/values.js +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = { - Value: {}, - Ordinal: { - isA: 'Value' - }, - Cardinal: { - isA: 'Value' - }, - Multiple: { - isA: 'Value' - }, - RomanNumeral: { - isA: 'Cardinal' - }, - Fraction: { - isA: 'Value' - }, - TextValue: { - isA: 'Value' - }, - NumericValue: { - isA: 'Value' - }, - NiceNumber: { - isA: 'Value' - }, - Money: { - //isA: 'Cardinal' - }, - Percent: { - isA: 'Value' - } -}; diff --git a/src/tags/tags/verbs.js b/src/tags/tags/verbs.js deleted file mode 100644 index 27ee800cf..000000000 --- a/src/tags/tags/verbs.js +++ /dev/null @@ -1,41 +0,0 @@ -module.exports = { - Verb: { - isA: 'VerbPhrase' - }, - PresentTense: { - isA: 'Verb' - }, - Infinitive: { - isA: 'PresentTense' - }, - Gerund: { - isA: 'PresentTense' - }, - PastTense: { - isA: 'Verb' - }, - PerfectTense: { - isA: 'Verb' - }, - FuturePerfect: { - isA: 'Verb' - }, - Pluperfect: { - isA: 'Verb' - }, - Copula: { - isA: 'Verb' - }, - Modal: { - isA: 'Verb' - }, - Participle: { - isA: 'Verb' - }, - Particle: { - isA: 'Verb' - }, - PhrasalVerb: { - isA: 'Verb' - } -}; diff --git a/src/term/index.js b/src/term/index.js deleted file mode 100644 index 4776029d8..000000000 --- a/src/term/index.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; -const fns = require('./paths').fns; -const build_whitespace = require('./whitespace'); -const makeUID = require('./makeUID'); -//normalization -const addNormal = require('./methods/normalize/normalize').addNormal; -const addRoot = require('./methods/normalize/root'); - -const Term = function(str, world) { - this.tags = {}; - this._text = fns.ensureString(str); - - // this.world = world; - Object.defineProperty(this, 'world', { - enumerable: false, // hide it from for..in - value: world - }); - // this.world = function() { - // return world; - // }; - //seperate whitespace from the text - let parsed = build_whitespace(this._text); - this.whitespace = parsed.whitespace; - this._text = parsed.text; - this.parent = null; - this.silent_term = ''; - this.lumped = false; - //normalize the _text - addNormal(this); - addRoot(this); - //has this term been modified - this.dirty = false; - //make a unique id for this term - this.uid = makeUID(this.normal); - - //getters/setters - Object.defineProperty(this, 'text', { - get: function() { - return this._text; - }, - set: function(txt) { - txt = txt || ''; - this._text = txt.trim(); - this.dirty = true; - // if (this._text !== txt) { - // console.log('|' + txt + '|'); - // console.log(build_whitespace(txt)); - // this.whitespace = build_whitespace(txt); - // console.log(this.whitespace); - // } - this.normalize(); - } - }); - //bit faster than .constructor.name or w/e - Object.defineProperty(this, 'isA', { - get: function() { - return 'Term'; - } - }); -}; - -/**run each time a new text is set */ -Term.prototype.normalize = function() { - addNormal(this); - addRoot(this); - return this; -}; -/** where in the sentence is it? zero-based. */ -Term.prototype.index = function() { - let ts = this.parentTerms; - if (!ts) { - return null; - } - return ts.terms.indexOf(this); -}; -/** make a copy with no originals to the original */ -Term.prototype.clone = function() { - let term = new Term(this._text, this.world); - term.tags = fns.copy(this.tags); - term.whitespace = fns.copy(this.whitespace); - term.silent_term = this.silent_term; - return term; -}; - -require('./methods/misc')(Term); -require('./methods/out')(Term); -require('./methods/tag')(Term); -require('./methods/case')(Term); -require('./methods/punctuation')(Term); - -module.exports = Term; diff --git a/src/term/makeUID.js b/src/term/makeUID.js deleted file mode 100644 index 5b17861c0..000000000 --- a/src/term/makeUID.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; -//this is a not-well-thought-out way to reduce our dependence on `object===object` original stuff -//generates a unique id for this term -//may need to change when the term really-transforms? not sure. -const uid = (str) => { - let nums = ''; - for(let i = 0; i < 5; i++) { - nums += parseInt(Math.random() * 9, 10); - } - return str + '-' + nums; -}; -module.exports = uid; diff --git a/src/term/methods/bestTag.js b/src/term/methods/bestTag.js deleted file mode 100644 index 97696db8b..000000000 --- a/src/term/methods/bestTag.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; -// const tagSet = require('../paths').tags; -const boringTags = { - Auxiliary: 1, - Possessive: 1, - TitleCase: 1, - ClauseEnd: 1, - Comma: 1, - CamelCase: 1, - UpperCase: 1, - Hyphenated: 1, - VerbPhrase: 1, - EndBracket: 1, - StartBracket: 1, - Parentheses: 1, - Quotation: 1, -}; - -const bestTag = function(t) { - const tagSet = t.world.tags; - let tags = Object.keys(t.tags); - tags = tags.sort(); //alphabetical, first - //then sort by #of parent tags - tags = tags.sort((a, b) => { - //bury the tags we dont want - if (!tagSet[a]) { - return 1; - } - if (boringTags[b] || !tagSet[b]) { - return -1; - } - if (tagSet[a].downward.length > tagSet[b].downward.length) { - return 1; - } - return 1; - }); - return tags[0]; -}; -module.exports = bestTag; diff --git a/src/term/methods/case.js b/src/term/methods/case.js deleted file mode 100644 index a3d9f1c38..000000000 --- a/src/term/methods/case.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -const addMethods = Term => { - const methods = { - toUpperCase: function() { - this.text = this._text.toUpperCase(); - this.tag('#UpperCase', 'toUpperCase'); - return this; - }, - toLowerCase: function() { - this.text = this._text.toLowerCase(); - this.unTag('#TitleCase'); - this.unTag('#UpperCase'); - return this; - }, - toTitleCase: function() { - this.text = this._text.replace(/^ *[a-z]/, x => x.toUpperCase()); - this.tag('#TitleCase', 'toTitleCase'); - return this; - }, - //(camelCase() is handled in `./terms` ) - - /** is it titlecased because it deserves it? Like a person's name? */ - needsTitleCase: function() { - const titleCases = [ - 'Person', - 'Place', - 'Organization', - 'Acronym', - 'UpperCase', - 'Currency', - 'RomanNumeral', - 'Month', - 'WeekDay', - 'Holiday', - 'Demonym' - ]; - for (let i = 0; i < titleCases.length; i++) { - if (this.tags[titleCases[i]]) { - return true; - } - } - //specific words that keep their titlecase - //https://en.wikipedia.org/wiki/Capitonym - const irregulars = ['i', 'god', 'allah']; - for (let i = 0; i < irregulars.length; i++) { - if (this.normal === irregulars[i]) { - return true; - } - } - return false; - } - }; - //hook them into result.proto - Object.keys(methods).forEach(k => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; diff --git a/src/term/methods/misc.js b/src/term/methods/misc.js deleted file mode 100644 index e6075ba82..000000000 --- a/src/term/methods/misc.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; -const isAcronym = require('./normalize/isAcronym'); -const bestTag = require('./bestTag'); - -//regs- -const hasVowel = /[aeiouy]/i; -const hasLetter = /[a-z]/; -const hasNumber = /[0-9]/; - -const addMethods = (Term) => { - - const methods = { - /** which tag best-represents this term?*/ - bestTag: function () { - return bestTag(this); - }, - - /** is this term like F.B.I. or NBA */ - isAcronym: function () { - return isAcronym(this._text); - }, - /** check if it is word-like in english */ - isWord: function () { - let t = this; - //assume a contraction produces a word-word - if (t.silent_term) { - return true; - } - //no letters or numbers - if (/[a-z|A-Z|0-9]/.test(t.text) === false) { - return false; - } - //has letters, but with no vowels - if (t.normal.length > 3 && hasLetter.test(t.normal) === true && hasVowel.test(t.normal) === false && t.isAcronym() === false) { - return false; - } - //has numbers but not a 'value' - if (hasNumber.test(t.normal) === true && t.tags.hasOwnProperty('Value') === false) { - //s4e - if (/[a-z][0-9][a-z]/.test(t.normal) === true) { - return false; - } - //ensure it looks like a 'value' eg '-$4,231.00' - // if (/^([$-])*?([0-9,\.])*?([s\$%])*?$/.test(t.normal) === false) { - // return false; - // } - } - return true; - } - }; - //hook them into result.proto - Object.keys(methods).forEach((k) => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; diff --git a/src/term/methods/normalize/isAcronym.js b/src/term/methods/normalize/isAcronym.js deleted file mode 100644 index db1bd6d01..000000000 --- a/src/term/methods/normalize/isAcronym.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; -//regs - -const periodAcronym = /([A-Z]\.)+[A-Z]?,?$/; -const oneLetterAcronym = /^[A-Z]\.,?$/; -const noPeriodAcronym = /[A-Z]{2}('s|,)?$/; - -/** does it appear to be an acronym, like FBI or M.L.B. */ -const isAcronym = function(str) { - //like N.D.A - if (periodAcronym.test(str) === true) { - return true; - } - //like 'F.' - if (oneLetterAcronym.test(str) === true) { - return true; - } - //like NDA - if (noPeriodAcronym.test(str) === true) { - return true; - } - return false; -}; -module.exports = isAcronym; diff --git a/src/term/methods/normalize/normalize.js b/src/term/methods/normalize/normalize.js deleted file mode 100644 index 3b9f4295e..000000000 --- a/src/term/methods/normalize/normalize.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; -const killUnicode = require('./unicode'); -const isAcronym = require('./isAcronym'); - -//some basic operations on a string to reduce noise -exports.normalize = function(str) { - str = str || ''; - str = str.toLowerCase(); - str = str.trim(); - let original = str; - //(very) rough ASCII transliteration - bjŏrk -> bjork - str = killUnicode(str); - //#tags, @mentions - str = str.replace(/^[#@]/, ''); - //punctuation - str = str.replace(/[,;.!?]+$/, ''); - // coerce single curly quotes - str = str.replace(/[\u0027\u0060\u00B4\u2018\u2019\u201A\u201B\u2032\u2035\u2039\u203A]+/g, '\''); - // coerce double curly quotes - str = str.replace(/[\u0022\u00AB\u00BB\u201C\u201D\u201E\u201F\u2033\u2034\u2036\u2037\u2E42\u301D\u301E\u301F\uFF02]+/g, '"'); - //coerce Unicode ellipses - str = str.replace(/\u2026/g, '...'); - //en-dash - str = str.replace(/\u2013/g, '-'); - //lookin'->looking (make it easier for conjugation) - if (/[a-z][^aeiou]in['’]$/.test(str) === true) { - str = str.replace(/in['’]$/, 'ing'); - } - //turn re-enactment to reenactment - if (/^(re|un)-?[^aeiou]./.test(str) === true) { - str = str.replace('-', ''); - } - //strip leading & trailing grammatical punctuation - if (/^[:;]/.test(str) === false) { - str = str.replace(/\.{3,}$/g, ''); - str = str.replace(/['",\.!:;\?\)]+$/g, ''); - str = str.replace(/^['"\(]+/g, ''); - } - //do this again.. - str = str.trim(); - //oh shucks, - if (str === '') { - str = original; - } - return str; -}; - -exports.addNormal = function(term) { - let str = term._text || ''; - str = exports.normalize(str); - //compact acronyms - if (isAcronym(term._text)) { - str = str.replace(/\./g, ''); - } - //nice-numbers - str = str.replace(/([0-9]),([0-9])/g, '$1$2'); - term.normal = str; -}; - -// console.log(normalize('Dr. V Cooper')); diff --git a/src/term/methods/normalize/root.js b/src/term/methods/normalize/root.js deleted file mode 100644 index dc91017d1..000000000 --- a/src/term/methods/normalize/root.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; -// -const rootForm = function(term) { - let str = term.normal || term.silent_term || ''; - //handle apostrophes and stuff (go further than normalize()) - str = str.replace(/'s\b/, ''); - str = str.replace(/'$/, ''); - term.root = str; -}; - -module.exports = rootForm; diff --git a/src/term/methods/normalize/unicode.js b/src/term/methods/normalize/unicode.js deleted file mode 100644 index 11dc9e3fa..000000000 --- a/src/term/methods/normalize/unicode.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; -//a hugely-ignorant, and widely subjective transliteration of latin, cryllic, greek unicode characters to english ascii. -//approximate visual (not semantic or phonetic) relationship between unicode and ascii characters -//http://en.wikipedia.org/wiki/List_of_Unicode_characters -//https://docs.google.com/spreadsheet/ccc?key=0Ah46z755j7cVdFRDM1A2YVpwa1ZYWlpJM2pQZ003M0E -let compact = { - '!': '¡', - '?': '¿Ɂ', - '"': '“”"❝❞', - '\'': '‘‛❛❜', - '-': '—–', - 'a': 'ªÀÁÂÃÄÅàáâãäåĀāĂ㥹ǍǎǞǟǠǡǺǻȀȁȂȃȦȧȺΆΑΔΛάαλАДадѦѧӐӑӒӓƛɅæ', - 'b': 'ßþƀƁƂƃƄƅɃΒβϐϦБВЪЬбвъьѢѣҌҍҔҕƥƾ', - 'c': '¢©ÇçĆćĈĉĊċČčƆƇƈȻȼͻͼͽϲϹϽϾϿЄСсєҀҁҪҫ', - 'd': 'ÐĎďĐđƉƊȡƋƌǷ', - 'e': 'ÈÉÊËèéêëĒēĔĕĖėĘęĚěƎƏƐǝȄȅȆȇȨȩɆɇΈΕΞΣέεξϱϵ϶ЀЁЕЭеѐёҼҽҾҿӖӗӘәӚӛӬӭ', - 'f': 'ƑƒϜϝӺӻҒғӶӷſ', - 'g': 'ĜĝĞğĠġĢģƓǤǥǦǧǴǵ', - 'h': 'ĤĥĦħƕǶȞȟΉΗЂЊЋНнђћҢңҤҥҺһӉӊ', - 'I': 'ÌÍÎÏ', - 'i': 'ìíîïĨĩĪīĬĭĮįİıƖƗȈȉȊȋΊΐΪίιϊІЇії', - 'j': 'ĴĵǰȷɈɉϳЈј', - 'k': 'ĶķĸƘƙǨǩΚκЌЖКжкќҚқҜҝҞҟҠҡ', - 'l': 'ĹĺĻļĽľĿŀŁłƚƪǀǏǐȴȽΙӀӏ', - 'm': 'ΜϺϻМмӍӎ', - 'n': 'ÑñŃńŅņŇňʼnŊŋƝƞǸǹȠȵΝΠήηϞЍИЙЛПийлпѝҊҋӅӆӢӣӤӥπ', - 'o': 'ÒÓÔÕÖØðòóôõöøŌōŎŏŐőƟƠơǑǒǪǫǬǭǾǿȌȍȎȏȪȫȬȭȮȯȰȱΌΘΟθοσόϕϘϙϬϭϴОФоѲѳӦӧӨөӪӫ¤ƍΏ', - 'p': 'ƤƿΡρϷϸϼРрҎҏÞ', - 'q': 'Ɋɋ', - 'r': 'ŔŕŖŗŘřƦȐȑȒȓɌɍЃГЯгяѓҐґ', - 's': 'ŚśŜŝŞşŠšƧƨȘșȿςϚϛϟϨϩЅѕ', - 't': 'ŢţŤťŦŧƫƬƭƮȚțȶȾΓΤτϮϯТт҂Ҭҭ', - 'u': 'µÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųƯưƱƲǓǔǕǖǗǘǙǚǛǜȔȕȖȗɄΰμυϋύϑЏЦЧцџҴҵҶҷӋӌӇӈ', - 'v': 'νѴѵѶѷ', - 'w': 'ŴŵƜωώϖϢϣШЩшщѡѿ', - 'x': '×ΧχϗϰХхҲҳӼӽӾӿ', - 'y': 'ÝýÿŶŷŸƳƴȲȳɎɏΎΥΫγψϒϓϔЎУучўѰѱҮүҰұӮӯӰӱӲӳ', - 'z': 'ŹźŻżŽžƩƵƶȤȥɀΖζ' -}; -//decompress data into two hashes -let unicode = {}; -Object.keys(compact).forEach(function (k) { - compact[k].split('').forEach(function (s) { - unicode[s] = k; - }); -}); - -const killUnicode = (str) => { - let chars = str.split(''); - chars.forEach((s, i) => { - if (unicode[s]) { - chars[i] = unicode[s]; - } - }); - return chars.join(''); -}; -module.exports = killUnicode; -// console.log(killUnicode('bjŏȒk—Ɏó')); diff --git a/src/term/methods/out/client.js b/src/term/methods/out/client.js deleted file mode 100644 index 3e03a3894..000000000 --- a/src/term/methods/out/client.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -const paths = require('../../paths'); -const fns = paths.fns; -const tagset = paths.tags; - -//a nicer logger for the client-side -const clientSide = (t) => { - let color = 'silver'; - let tags = Object.keys(t.tags); - for(let i = 0; i < tags.length; i++) { - if (tagset[tags[i]] && tagset[tags[i]].color) { - color = tagset[tags[i]].color; - break; - } - } - let word = fns.leftPad(t.text, 12); - word += ' ' + tags; - console.log('%c ' + word, 'color: ' + color); -}; -module.exports = clientSide; diff --git a/src/term/methods/out/index.js b/src/term/methods/out/index.js deleted file mode 100644 index 3d37f674b..000000000 --- a/src/term/methods/out/index.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; -const renderHtml = require('./renderHtml'); -const clientDebug = require('./client'); -const serverDebug = require('./server'); - -const methods = { - /** a pixel-perfect reproduction of the input, with whitespace preserved */ - text: function(r) { - return (r.whitespace.before || '') + r._text + (r.whitespace.after || ''); - }, - /** a lowercased, punctuation-cleaned, whitespace-trimmed version of the word */ - normal: function(r) { - return r.normal; - }, - /** even-more normalized than normal */ - root: function(r) { - return r.root || r.normal; - }, - /** the &encoded term in a span element, with POS as classNames */ - html: function(r) { - return renderHtml(r); - }, - /** a simplified response for Part-of-Speech tagging*/ - tags: function(r) { - return { - text: r.text, - normal: r.normal, - tags: Object.keys(r.tags) - }; - }, - /** check-print information for the console */ - debug: function(t) { - if (typeof window === 'object') { - clientDebug(t); - } else { - serverDebug(t); - } - } -}; - -const addMethods = Term => { - //hook them into result.proto - Term.prototype.out = function(fn) { - if (!methods[fn]) { - fn = 'text'; - } - return methods[fn](this); - }; - return Term; -}; - -module.exports = addMethods; diff --git a/src/term/methods/out/renderHtml.js b/src/term/methods/out/renderHtml.js deleted file mode 100644 index 32c300942..000000000 --- a/src/term/methods/out/renderHtml.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; -//turn xml special characters into apersand-encoding. -//i'm not sure this is perfectly safe. -const escapeHtml = (s) => { - const HTML_CHAR_MAP = { - '<': '<', - '>': '>', - '&': '&', - '"': '"', - '\'': ''', - ' ': ' ' - }; - return s.replace(/[<>&"' ]/g, function(ch) { - return HTML_CHAR_MAP[ch]; - }); -}; - -//remove html elements already in the text -//not tested! -//http://stackoverflow.com/questions/295566/sanitize-rewrite-html-on-the-client-side -const sanitize = (html) => { - const tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*'; - const tagOrComment = new RegExp( - '<(?:' - // Comment body. - + '!--(?:(?:-*[^->])*--+|-?)' - // Special "raw text" elements whose content should be elided. - + '|script\\b' + tagBody + '>[\\s\\S]*?[\\s\\S]*?', - 'gi'); - let oldHtml; - do { - oldHtml = html; - html = html.replace(tagOrComment, ''); - } while (html !== oldHtml); - return html.replace(/ tag !== 'Term'); - classes = classes.map(c => 'nl-' + c); - classes = classes.join(' '); - let text = sanitize(t.text); - text = escapeHtml(text); - let el = '' + text + ''; - return escapeHtml(t.whitespace.before) + el + escapeHtml(t.whitespace.after); -}; - -module.exports = renderHtml; diff --git a/src/term/methods/out/server.js b/src/term/methods/out/server.js deleted file mode 100644 index 76fc050b0..000000000 --- a/src/term/methods/out/server.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; -const fns = require('../../paths').fns; - -//pretty-print a term on the nodejs console -const serverDebug = function(t) { - let tags = Object.keys(t.tags) - .map(tag => { - return fns.printTag(tag); - }) - .join(', '); - let word = t.text; - word = '\'' + fns.yellow(word || '-') + '\''; - let silent = ''; - if (t.silent_term) { - silent = '[' + t.silent_term + ']'; - } - word = fns.leftPad(word, 20); - word += fns.leftPad(silent, 8); - console.log(' ' + word + ' ' + ' - ' + tags); -}; -module.exports = serverDebug; diff --git a/src/term/methods/punctuation.js b/src/term/methods/punctuation.js deleted file mode 100644 index eb772cb10..000000000 --- a/src/term/methods/punctuation.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; -// const endPunct = /([^\/,:;.()!?]{0,1})([\/,:;.()!?]+)$/i; -const endPunct = /([a-z0-9 ])([,:;.!?]+)$/i; //old - -const addMethods = Term => { - const methods = { - /** the punctuation at the end of this term*/ - getPunctuation: function() { - let m = this.text.match(endPunct); - if (m) { - return m[2]; - } - m = this.whitespace.after.match(endPunct); - if (m) { - return m[2]; - } - return null; - }, - - setPunctuation: function(punct) { - this.killPunctuation(); - this.text += punct; - if (punct === ',') { - this.tags.Comma = true; - } - return this; - }, - - /** check if the term ends with a comma */ - hasComma: function() { - if (this.getPunctuation() === ',') { - return true; - } - return false; - }, - - killPunctuation: function() { - this.text = this._text.replace(endPunct, '$1'); - delete this.tags.Comma; - delete this.tags.ClauseEnd; - return this; - } - }; - //hook them into result.proto - Object.keys(methods).forEach(k => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; diff --git a/src/term/methods/tag/canBe.js b/src/term/methods/tag/canBe.js deleted file mode 100644 index 48dfe01fc..000000000 --- a/src/term/methods/tag/canBe.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -//recursively-check compatibility of this tag and term -const canBe = function(term, tag) { - const tagset = term.world.tags; - //fail-fast - if (tagset[tag] === undefined) { - return true; - } - //loop through tag's contradictory tags - let enemies = tagset[tag].notA || []; - for (let i = 0; i < enemies.length; i++) { - if (term.tags[enemies[i]] === true) { - return false; - } - } - if (tagset[tag].isA !== undefined) { - return canBe(term, tagset[tag].isA); //recursive - } - return true; -}; - -module.exports = canBe; diff --git a/src/term/methods/tag/index.js b/src/term/methods/tag/index.js deleted file mode 100644 index 1f5108a99..000000000 --- a/src/term/methods/tag/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; -const setTag = require('./setTag'); -const unTag = require('./unTag'); -const canBe = require('./canBe'); - -//symbols used in sequential taggers which mean 'do nothing' -//.tag('#Person #Place . #City') -const ignore = { - '.': true -}; -const addMethods = (Term) => { - - const methods = { - /** set the term as this part-of-speech */ - tag: function(tag, reason) { - if (ignore[tag] !== true) { - setTag(this, tag, reason); - } - }, - /** remove this part-of-speech from the term*/ - unTag: function(tag, reason) { - if (ignore[tag] !== true) { - unTag(this, tag, reason); - } - }, - /** is this tag compatible with this word */ - canBe: function (tag) { - tag = tag || ''; - if (typeof tag === 'string') { - //everything can be '.' - if (ignore[tag] === true) { - return true; - } - tag = tag.replace(/^#/, ''); - } - return canBe(this, tag); - } - }; - - //hook them into term.prototype - Object.keys(methods).forEach((k) => { - Term.prototype[k] = methods[k]; - }); - return Term; -}; - -module.exports = addMethods; diff --git a/src/term/methods/tag/setTag.js b/src/term/methods/tag/setTag.js deleted file mode 100644 index 4f1f15f9c..000000000 --- a/src/term/methods/tag/setTag.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -//set a term as a particular Part-of-speech -const path = require('../../paths'); -const log = path.log; -const fns = path.fns; -const unTag = require('./unTag'); -// const tagset = path.tags; -// const tagset = require('../../../tagset'); - -const putTag = (term, tag, reason) => { - const tagset = term.world.tags; - tag = tag.replace(/^#/, ''); - //already got this - if (term.tags[tag] === true) { - return; - } - term.tags[tag] = true; - log.tag(term, tag, reason); - - //extra logic per-each POS - if (tagset[tag]) { - //drop any conflicting tags - let enemies = tagset[tag].notA || []; - for (let i = 0; i < enemies.length; i++) { - if (term.tags[enemies[i]] === true) { - unTag(term, enemies[i], reason); - } - } - //apply implicit tags - if (tagset[tag].isA) { - let doAlso = tagset[tag].isA; - if (term.tags[doAlso] !== true) { - putTag(term, doAlso, ' --> ' + tag); //recursive - } - } - } -}; - -//give term this tag -const wrap = function(term, tag, reason) { - if (!term || !tag) { - return; - } - const tagset = term.world.tags; - //handle multiple tags - if (fns.isArray(tag)) { - tag.forEach(t => putTag(term, t, reason)); //recursive - return; - } - putTag(term, tag, reason); - //add 'extra' tag (for some special tags) - if (tagset[tag] && tagset[tag].also !== undefined) { - putTag(term, tagset[tag].also, reason); - } -}; - -module.exports = wrap; diff --git a/src/term/methods/tag/unTag.js b/src/term/methods/tag/unTag.js deleted file mode 100644 index fcd4a7c70..000000000 --- a/src/term/methods/tag/unTag.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -//set a term as a particular Part-of-speech -const path = require('../../paths'); -const log = path.log; - -//remove a tag from a term -const unTag = (term, tag, reason) => { - const tagset = term.world.tags; - if (term.tags[tag]) { - log.unTag(term, tag, reason); - delete term.tags[tag]; - - //delete downstream tags too - if (tagset[tag]) { - let also = tagset[tag].downward; - for (let i = 0; i < also.length; i++) { - unTag(term, also[i], ' - - - '); - } - } - } -}; - -const wrap = (term, tag, reason) => { - if (!term || !tag) { - return; - } - //support '*' flag - remove all-tags - if (tag === '*') { - term.tags = {}; - return; - } - //remove this tag - unTag(term, tag, reason); - return; -}; -module.exports = wrap; diff --git a/src/term/paths.js b/src/term/paths.js deleted file mode 100644 index 229a93713..000000000 --- a/src/term/paths.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - fns: require('../fns'), - log: require('../log'), - tags: require('../tags') -}; diff --git a/src/term/whitespace.js b/src/term/whitespace.js deleted file mode 100644 index 7b2871a0b..000000000 --- a/src/term/whitespace.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; -//punctuation regs- are we having fun yet? -const before = /^(\s|-+|\.\.+|\/|"|\u0022|\uFF02|\u0027|\u201C|\u2018|\u201F|\u201B|\u201E|\u2E42|\u201A|\u00AB|\u2039|\u2035|\u2036|\u2037|\u301D|\u0060|\u301F)+/u; -// const after = /(\s+|-+|\.\.+|"|\u0022|\uFF02|\u0027|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4)+$/u; -const afterSoft = /(\s+|-+|\.\.+|"|\u0022|\uFF02|\u0027|\u201D|\u2019|\u00BB|\u203A|\u2032|\u2033|\u2034|\u301E|\u00B4)+[,;.!? ]*$/u; -const minusNumber = /^( *)-(\$|€|¥|£)?([0-9])/; - -//seperate the 'meat' from the trailing/leading whitespace. -//works in concert with ./src/text/tokenize.js -const build_whitespace = (str) => { - let whitespace = { - before: '', - after: '' - }; - //get before punctuation/whitespace - //mangle 'far - fetched', but don't mangle '-2' - let m = str.match(minusNumber); - if (m !== null) { - whitespace.before = m[1]; - str = str.replace(/^ */, ''); - } else { - m = str.match(before); - if (m !== null) { - whitespace.before = m[0]; - str = str.replace(before, ''); - } - } - //get after punctuation/whitespace - m = str.match(afterSoft); - if (m !== null) { - str = str.replace(afterSoft, ''); - whitespace.after = m[0]; - } - return { - whitespace: whitespace, - text: str - }; -}; -module.exports = build_whitespace; diff --git a/src/terms/build.js b/src/terms/build.js deleted file mode 100644 index 5f39bc85a..000000000 --- a/src/terms/build.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; -const Term = require('../term'); -const wordlike = /\S/; -const isBoundary = /^[!?.]+$/; - -const notWord = { - '.': true, - '-': true, //dash - '–': true, //en-dash - '—': true, //em-dash - '--': true, - '...': true -}; - -const hasHyphen = function(str) { - //dont split 're-do' - if (/^(re|un)-?[^aeiou]./.test(str) === true) { - return false; - } - //letter-number - let reg = /^([a-z`"'/]+)(-|–|—)([a-z0-9].*)/i; - if (reg.test(str) === true) { - return true; - } - //number-letter - // reg = /^([0-9]+)(-|–|—)([a-z].*)/i; - // if (reg.test(str) === true) { - // return true; - // } - //support weird number-emdash combo '2010–2011' - let reg2 = /^([0-9]+)(–|—)([0-9].*)/i; - if (reg2.test(str)) { - return true; - } - return false; -}; - -//support splitting terms like "open/closed" -const hasSlash = function(word) { - const reg = /[a-z]\/[a-z]/; - if (reg.test(word)) { - //only one slash though - if (word.split(/\//g).length === 2) { - return true; - } - } - return false; -}; - -//turn a string into an array of terms (naiive for now, lumped later) -const fromString = function(str, world) { - let result = []; - let arr = []; - //start with a naiive split - str = str || ''; - if (typeof str === 'number') { - str = String(str); - } - const firstSplit = str.split(/(\S+)/); - for (let i = 0; i < firstSplit.length; i++) { - const word = firstSplit[i]; - if (hasHyphen(word) === true) { - //support multiple-hyphenated-terms - const hyphens = word.split(/[-–—]/); - for (let o = 0; o < hyphens.length; o++) { - if (o === hyphens.length - 1) { - arr.push(hyphens[o]); - } else { - arr.push(hyphens[o] + '-'); - } - } - } else if (hasSlash(word) === true) { - const slashes = word.split(/\//); - arr.push(slashes[0]); - arr.push('/' + slashes[1]); - } else { - arr.push(word); - } - } - //greedy merge whitespace+arr to the right - let carry = ''; - for (let i = 0; i < arr.length; i++) { - //if it's more than a whitespace - if ( - wordlike.test(arr[i]) === true && - notWord.hasOwnProperty(arr[i]) === false && - isBoundary.test(arr[i]) === false - ) { - result.push(carry + arr[i]); - carry = ''; - } else { - carry += arr[i]; - } - } - //handle last one - if (carry && result.length > 0) { - result[result.length - 1] += carry; //put it on the end - } - return result.map(t => new Term(t, world)); -}; -module.exports = fromString; diff --git a/src/terms/getters.js b/src/terms/getters.js deleted file mode 100644 index b8d82aa90..000000000 --- a/src/terms/getters.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -//getters/setters for the Terms class -module.exports = { - - parent: { - get: function() { - return this.refText || this; - }, - set: function(r) { - this.refText = r; - return this; - } - }, - - parentTerms: { - get: function() { - return this.refTerms || this; - }, - set: function(r) { - this.refTerms = r; - return this; - } - }, - - dirty: { - get: function() { - for(let i = 0; i < this.terms.length; i++) { - if (this.terms[i].dirty === true) { - return true; - } - } - return false; - }, - set: function(dirt) { - this.terms.forEach((t) => { - t.dirty = dirt; - }); - } - }, - - refTerms: { - get: function() { - return this._refTerms || this; - }, - set: function(ts) { - this._refTerms = ts; - return this; - } - }, - found: { - get: function() { - return this.terms.length > 0; - } - }, - length: { - get: function() { - return this.terms.length; - } - }, - isA: { - get: function() { - return 'Terms'; - } - }, - whitespace: { - get: function() { - return { - before: (str) => { - this.firstTerm().whitespace.before = str; - return this; - }, - after: (str) => { - this.lastTerm().whitespace.after = str; - return this; - }, - }; - } - }, - - -}; diff --git a/src/terms/index.js b/src/terms/index.js deleted file mode 100644 index d0f5b7a95..000000000 --- a/src/terms/index.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; -const build = require('./build'); -const getters = require('./getters'); -let w = require('../world'); - -//Terms is an array of Term objects, and methods that wrap around them -const Terms = function(arr, world, refText, refTerms) { - this.terms = arr; - this.world = world || w; - this.refText = refText; - this._refTerms = refTerms; - this.get = n => { - return this.terms[n]; - }; - //apply getters - let keys = Object.keys(getters); - for (let i = 0; i < keys.length; i++) { - Object.defineProperty(this, keys[i], getters[keys[i]]); - } -}; - -Terms.fromString = function(str, world) { - let termArr = build(str, world); - let ts = new Terms(termArr, world, null); - //give each term a original to this ts - ts.terms.forEach(t => { - t.parentTerms = ts; - }); - return ts; -}; - -// Terms = require('./methods/lookup')(Terms); -require('./match')(Terms); -require('./methods/tag')(Terms); -require('./methods/loops')(Terms); -require('./match/not')(Terms); -require('./methods/delete')(Terms); -require('./methods/insert')(Terms); -require('./methods/misc')(Terms); -require('./methods/out')(Terms); -require('./methods/replace')(Terms); -require('./methods/split')(Terms); -require('./methods/transform')(Terms); -require('./methods/lump')(Terms); -module.exports = Terms; diff --git a/src/terms/match/index.js b/src/terms/match/index.js deleted file mode 100644 index 21d4aec8a..000000000 --- a/src/terms/match/index.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; -const syntax = require('./lib/syntax'); -const startHere = require('./lib/startHere'); -const Text = require('../../text'); -const match = require('./lib'); - -const matchMethods = Terms => { - const methods = { - //support regex-like whitelist-match - match: function (reg, verbose) { - //fail-fast #1 - if (this.terms.length === 0) { - return new Text([], this.world, this.parent); - } - //fail-fast #2 - if (!reg) { - return new Text([], this.world, this.parent); - } - let matches = match(this, reg, verbose); - matches = matches.map(a => { - return new Terms(a, this.world, this.refText, this.refTerms); - }); - return new Text(matches, this.world, this.parent); - }, - - /**return first match */ - matchOne: function (str) { - //fail-fast - if (this.terms.length === 0) { - return null; - } - let regs = syntax(str); - for (let t = 0; t < this.terms.length; t++) { - //don't loop through if '^' - if (regs[0] && regs[0].starting && t > 0) { - break; - } - let m = startHere(this, t, regs); - if (m) { - return m; - } - } - return null; - }, - - /**return first match */ - has: function (str) { - return this.matchOne(str) !== null; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = matchMethods; diff --git a/src/terms/match/lib/applyCaptureGroup.js b/src/terms/match/lib/applyCaptureGroup.js deleted file mode 100644 index 754f3590d..000000000 --- a/src/terms/match/lib/applyCaptureGroup.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; -//applies the reg capture group setting to the term -const applyCaptureGroup = (term, reg) => { - if (reg.capture) { - term.captureGroup = true; - } else { - term.captureGroup = undefined; - } -}; -module.exports = applyCaptureGroup; \ No newline at end of file diff --git a/src/terms/match/lib/captureGroup.js b/src/terms/match/lib/captureGroup.js deleted file mode 100644 index a2a8b3ca6..000000000 --- a/src/terms/match/lib/captureGroup.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; -//take all the matches, and if there is a [capture group], only return that. -const onlyCaptureGroup = function(matches) { - let results = []; - matches.forEach((terms) => { - //if there's no capture group, we good. - if (terms.filter(t => t.captureGroup === true).length === 0) { - results.push(terms); - return; - } - //otherwise, just return them as seperate subsets - let current = []; - for(let i = 0; i < terms.length; i += 1) { - if (terms[i].captureGroup) { - current.push(terms[i]); - } else if (current.length > 0) { - results.push(current); - current = []; - } - } - if (current.length > 0) { - results.push(current); - } - }); - return results; -}; -module.exports = onlyCaptureGroup; diff --git a/src/terms/match/lib/fastPass.js b/src/terms/match/lib/fastPass.js deleted file mode 100644 index cebdf1621..000000000 --- a/src/terms/match/lib/fastPass.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; -// -//find easy reasons to skip running the full match on this -const fastPass = (ts, regs) => { - for (let i = 0; i < regs.length; i++) { - let reg = regs[i]; - let found = false; - //we can't cheat on these fancy rules: - if (reg.optional === true || reg.negative === true || reg.minMax !== undefined) { - continue; - } - //look-for missing term-matches - if (reg.normal !== undefined) { - for (let o = 0; o < ts.terms.length; o++) { - if (ts.terms[o].normal === reg.normal || ts.terms[o].silent_term === reg.normal) { - found = true; - break; - } - //we can't handle lumped-terms with this method - if (ts.terms[o].lumped === true) { - return false; - } - } - if (found === false) { - return true; - } - } - //look for missing tags - if (reg.tag !== undefined) { - for (let o = 0; o < ts.terms.length; o++) { - if (ts.terms[o].tags[reg.tag] === true) { - found = true; - break; - } - } - if (found === false) { - return true; - } - } - } - return false; -}; -module.exports = fastPass; diff --git a/src/terms/match/lib/index.js b/src/terms/match/lib/index.js deleted file mode 100644 index 2829446db..000000000 --- a/src/terms/match/lib/index.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; -const syntax = require('./syntax'); -const startHere = require('./startHere'); -const fastPass = require('./fastPass'); -const handleCaptureGroup = require('./captureGroup'); - -//ensure we have atleast one non-optional demand -// const isTautology = function(regs) { -// for (let i = 0; i < regs.length; i++) { -// if (!regs[i].optional && !regs[i].astrix && !regs[i].anyOne) { -// return false; -// } -// } -// return true; -// }; - -//make a reg syntax from a text object -const findFromTerms = function(ts) { - if (!ts) { - return []; - } - let arr = ts.terms.map(t => { - return { - id: t.uid - }; - }); - return arr; -}; -// -const match = (ts, reg, verbose) => { - //parse for backwards-compatibility - if (typeof reg === 'string') { - reg = syntax(reg); - } else if (reg && reg.isA === 'Text') { - reg = findFromTerms(reg.list[0]); - } else if (reg && reg.isA === 'Terms') { - reg = findFromTerms(reg); - } - if (!reg || reg.length === 0) { - return []; - } - //do a fast-pass for easy negatives - if (fastPass(ts, reg, verbose) === true) { - return []; - } - //ok, start long-match - let matches = []; - for (let t = 0; t < ts.terms.length; t += 1) { - //don't loop through if '^' - if (t > 0 && reg[0] && reg[0].starting) { - break; - } - let m = startHere(ts, t, reg, verbose); - if (m && m.length > 0) { - matches.push(m); - //handle capture-groups subset - // let hasCapture=matches - //ok, don't try to match these again. - let skip = m.length - 1; - t += skip; //this could use some work - } - } - //handle capture-group subset - matches = handleCaptureGroup(matches); - return matches; -}; -module.exports = match; diff --git a/src/terms/match/lib/isMatch.js b/src/terms/match/lib/isMatch.js deleted file mode 100644 index da9aadf80..000000000 --- a/src/terms/match/lib/isMatch.js +++ /dev/null @@ -1,70 +0,0 @@ -'use strict'; -const applyCaptureGroup = require('./applyCaptureGroup'); - -//compare 1 term to one reg -const perfectMatch = (term, reg) => { - if (!term || !reg) { - return false; - } - //support '.' - any - if (reg.anyOne === true) { - return true; - } - //pos-match - if (reg.tag !== undefined) { - return term.tags[reg.tag]; - } - //id-match - if (reg.id !== undefined) { - return reg.id === term.uid; - } - //text-match - if (reg.normal !== undefined) { - return reg.normal === term.normal || reg.normal === term.silent_term; - } - //suffix matches '-nny' - if (reg.suffix === true && reg.partial !== undefined) { - const len = term.normal.length; - return term.normal.substr(len - reg.partial.length, len) === reg.partial; - } - //prefix matches 'fun-' - if (reg.prefix === true && reg.partial !== undefined) { - return term.normal.substr(0, reg.partial.length) === reg.partial; - } - //infix matches '-nn-' - if (reg.infix === true && reg.partial) { - return term.normal.indexOf(reg.partial) !== -1; - } - //full-on regex-match '/a*?/' - if (reg.regex !== undefined) { - return reg.regex.test(term.normal) || reg.regex.test(term.text); - } - //one-of term-match - if (reg.oneOf !== undefined) { - for (let i = 0; i < reg.oneOf.tagArr.length; i++) { - if (term.tags.hasOwnProperty(reg.oneOf.tagArr[i]) === true) { - return true; - } - } - return reg.oneOf.terms.hasOwnProperty(term.normal) || reg.oneOf.terms.hasOwnProperty(term.silent_term); - } - return false; -}; - -//wrap above method, to support '!' negation -const isMatch = (term, reg, verbose) => { - if (!term || !reg) { - return false; - } - let found = perfectMatch(term, reg, verbose); - //reverse it for .not() - if (reg.negative) { - found = !Boolean(found); - } - if (found) { - //only apply capture group settings to matches - applyCaptureGroup(term, reg); - } - return found; -}; -module.exports = isMatch; diff --git a/src/terms/match/lib/lumpMatch.js b/src/terms/match/lib/lumpMatch.js deleted file mode 100644 index 8990ec474..000000000 --- a/src/terms/match/lib/lumpMatch.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -const almostMatch = (reg_str, term) => { - let want = term.normal.substr(0, reg_str.length); - return want === reg_str; -}; - -// match ['john', 'smith'] regs, when the term is lumped -const lumpMatch = function(term, regs, reg_i) { - let reg_str = regs[reg_i].normal; - //is this a partial match? 'tony'& 'tony hawk' - if (reg_str !== undefined && almostMatch(reg_str, term)) { - //try to grow it - reg_i = reg_i + 1; - for (reg_i; reg_i < regs.length; reg_i++) { - reg_str += ' ' + regs[reg_i].normal; - // is it now perfect? - if (reg_str === term.normal) { - return reg_i; - } - // is it still almost? - if (almostMatch(reg_str, term) === false) { - return null; - } - } - } - return null; -}; - -module.exports = lumpMatch; diff --git a/src/terms/match/lib/paths.js b/src/terms/match/lib/paths.js deleted file mode 100644 index af7293c6a..000000000 --- a/src/terms/match/lib/paths.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../../paths'); diff --git a/src/terms/match/lib/startHere.js b/src/terms/match/lib/startHere.js deleted file mode 100644 index 97cc5d94e..000000000 --- a/src/terms/match/lib/startHere.js +++ /dev/null @@ -1,172 +0,0 @@ -'use strict'; -const lumpMatch = require('./lumpMatch'); -const isMatch = require('./isMatch'); -const applyCaptureGroup = require('./applyCaptureGroup'); - -// match everything until this point - '*' -const greedyUntil = (ts, i, reg) => { - for (; i < ts.length; i++) { - if (isMatch(ts.terms[i], reg)) { - return i; - } - } - return null; -}; - -//keep matching this reg as long as possible -const greedyOf = (ts, i, reg, until) => { - for (; i < ts.length; i++) { - let t = ts.terms[i]; - //found next reg ('until') - if (until && isMatch(t, until)) { - return i; - } - //stop here - if (!isMatch(t, reg)) { - return i; - } - } - return i; -}; - -//try and match all regs, starting at this term -const startHere = (ts, startAt, regs, verbose) => { - let term_i = startAt; - //check each regex-thing - for (let reg_i = 0; reg_i < regs.length; reg_i++) { - let term = ts.terms[term_i]; - let reg = regs[reg_i]; - let next_reg = regs[reg_i + 1]; - - if (!term) { - //we didn't need it anyways - if (reg.optional === true) { - continue; - } - return null; - } - - //catch '^' errors - if (reg.starting === true && term_i > 0) { - return null; - } - - //catch '$' errors - if (reg.ending === true && term_i !== ts.length - 1 && !reg.minMax) { - return null; - } - - //support '*' - if (reg.astrix === true) { - //just grab until the end.. - if (!next_reg) { - let terms = ts.terms.slice(startAt, ts.length); - //apply capture group settings for all wildcard terms - for (let wildcardTerm_i = term_i - startAt; wildcardTerm_i < terms.length; wildcardTerm_i++) { - applyCaptureGroup(terms[wildcardTerm_i], reg); - } - return terms; - } - let foundAt = greedyUntil(ts, term_i, regs[reg_i + 1]); - if (!foundAt) { - return null; - } - //apply capture group settings for all wildcard terms - for (let wildcardTerm_i = term_i; wildcardTerm_i < foundAt; wildcardTerm_i++) { - applyCaptureGroup(ts.terms[wildcardTerm_i], reg) - } - term_i = foundAt + 1; - reg_i += 1; - continue; - } - - //support '#Noun{x,y}' - if (regs[reg_i].minMax !== undefined) { - let min = regs[reg_i].minMax.min || 0; - let max = regs[reg_i].minMax.max; - let until = regs[reg_i + 1]; - for (let i = 0; i < max; i++) { - //ergh, please clean this loop up.. - let t = ts.terms[term_i + i]; - if (!t) { - return null; - } - //end here - if (isMatch(t, reg) === false) { - return null; - } - //should we be greedier? - if (i < min - 1) { - continue; //gotta keep going! - } - //we can end here, after the minimum - if (!until) { - term_i += 1; - break; - } - // we're greedy-to-now - if (i >= min && isMatch(t, until)) { - break; - } - //end with a greedy-match for next term - let nextT = ts.terms[term_i + i + 1]; - if (nextT && isMatch(nextT, until)) { - term_i += i + 2; - reg_i += 1; - break; - } else if (i === max - 1) { - //we've maxed-out - return null; - } - } - continue; - } - - //if optional, check next one - if (reg.optional === true) { - let until = regs[reg_i + 1]; - term_i = greedyOf(ts, term_i, reg, until); - continue; - } - - //check a perfect match - if (isMatch(term, reg, verbose)) { - term_i += 1; - //try to greedy-match '+' - if (reg.consecutive === true) { - let until = regs[reg_i + 1]; - term_i = greedyOf(ts, term_i, reg, until); - } - continue; - } - - if (term.silent_term && !term.normal) { - //skip over silent contraction terms - //we will continue on it, but not start on it - if (reg_i === 0) { - return null; - } - //try the next term, but with this regex again - term_i += 1; - reg_i -= 1; - continue; - } - - //handle partial-matches of lumped terms - let lumpUntil = lumpMatch(term, regs, reg_i, verbose); - if (lumpUntil !== null) { - reg_i = lumpUntil; - term_i += 1; - continue; - } - - //was it optional anways? - if (reg.optional === true) { - continue; - } - return null; - } - return ts.terms.slice(startAt, term_i); -}; - -module.exports = startHere; diff --git a/src/terms/match/lib/syntax.js b/src/terms/match/lib/syntax.js deleted file mode 100644 index 54ca45d8e..000000000 --- a/src/terms/match/lib/syntax.js +++ /dev/null @@ -1,171 +0,0 @@ -'use strict'; -// parse a search lookup term find the regex-like syntax in this term -const fns = require('./paths').fns; -//regs- -const range = /\{[0-9,]+\}$/; - -//trim char#0 -const noFirst = function(str) { - return str.substr(1, str.length); -}; -const noLast = function(str) { - return str.substring(0, str.length - 1); -}; - -//turn 'regex-like' search string into parsed json -const parse_term = function(term) { - term = term || ''; - term = term.trim(); - - let reg = {}; - //order matters here - - //1-character hasta be a text-match - if (term.length === 1 && term !== '.' && term !== '*') { - reg.normal = term.toLowerCase(); - return reg; - } - //negation ! flag - if (term.charAt(0) === '!') { - term = noFirst(term); - reg.negative = true; - } - //leading ^ flag - if (term.charAt(0) === '^') { - term = noFirst(term); - reg.starting = true; - } - //trailing $ flag means ending - if (term.charAt(term.length - 1) === '$') { - term = noLast(term); - reg.ending = true; - } - //optional flag - if (term.charAt(term.length - 1) === '?') { - term = noLast(term); - reg.optional = true; - } - //atleast-one-but-greedy flag - if (term.charAt(term.length - 1) === '+') { - term = noLast(term); - reg.consecutive = true; - } - //prefix/suffix/infix matches - if (term.charAt(term.length - 1) === '_') { - term = noLast(term); - reg.prefix = true; - //try both '-match-' - if (term.charAt(0) === '_') { - term = noFirst(term); - reg.prefix = undefined; - reg.infix = true; - } - reg.partial = term; - term = ''; - } else if (term.charAt(0) === '_') { - term = noFirst(term); - reg.suffix = true; - reg.partial = term; - term = ''; - } - //min/max any '{1,3}' - if (term.charAt(term.length - 1) === '}' && range.test(term) === true) { - let m = term.match(/\{([0-9])*,? ?([0-9]+)\}/); - reg.minMax = { - min: parseInt(m[1], 10) || 0, - max: parseInt(m[2], 10) - }; - term = term.replace(range, ''); - } - //pos flag - if (term.charAt(0) === '#') { - term = noFirst(term); - reg.tag = fns.titleCase(term); - term = ''; - } - //support /regex/ mode - if (term.charAt(0) === '/' && term.charAt(term.length - 1) === '/') { - term = noLast(term); - term = noFirst(term); - //actually make the regex - reg.regex = new RegExp(term, 'i'); - term = ''; - } - //one_of options flag - if (term.charAt(0) === '(' && term.charAt(term.length - 1) === ')') { - term = noLast(term); - term = noFirst(term); - let arr = term.split(/\|/g); - reg.oneOf = { - terms: {}, - tagArr: [] - }; - arr.forEach(str => { - //try a tag match - if (str.charAt(0) === '#') { - let tag = str.substr(1, str.length); - tag = fns.titleCase(tag); - reg.oneOf.tagArr.push(tag); - } else { - reg.oneOf.terms[str] = true; - } - }); - term = ''; - } - //a period means any one term - if (term === '.') { - reg.anyOne = true; - term = ''; - } - //a * means anything until sentence end - if (term === '*') { - reg.astrix = true; - term = ''; - } - if (term !== '') { - //support \ encoding of #[]()*+?^ - term = term.replace(/\\([\\#\*\.\[\]\(\)\+\?\^])/g, ''); - reg.normal = term.toLowerCase(); - } - return reg; -}; - -//turn a match string into an array of objects -const parse_all = function(input) { - input = input || ''; - let regs = input.split(/ +/); - //bundle-up multiple-words inside parentheses - for(let i = 0; i < regs.length; i += 1) { - if (regs[i].indexOf('(') !== -1 && regs[i].indexOf(')') === -1) { - let nextWord = regs[i + 1]; - if (nextWord && nextWord.indexOf('(') === -1 && nextWord.indexOf(')') !== -1) { - regs[i + 1] = regs[i] + ' ' + regs[i + 1]; - regs[i] = ''; - } - } - } - regs = regs.filter((f) => f); - let captureOn = false; - regs = regs.map((reg) => { - let hasEnd = false; - //support [#Noun] capture-group syntax - if (reg.charAt(0) === '[') { - reg = noFirst(reg); - captureOn = true; - } - if (reg.charAt(reg.length - 1) === ']') { - reg = noLast(reg); - captureOn = false; - hasEnd = true; - } - reg = parse_term(reg); - if (captureOn === true || hasEnd === true) { - reg.capture = true; - } - return reg; - }); - return regs; -}; - -module.exports = parse_all; -// console.log(JSON.stringify(parse_all('the (canadian|united states|british) senate'), null, 2)); diff --git a/src/terms/match/not.js b/src/terms/match/not.js deleted file mode 100644 index d2283cb71..000000000 --- a/src/terms/match/not.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict'; -// -const syntax = require('./lib/syntax'); -const startHere = require('./lib/startHere'); -const Text = require('../../text'); - -const addfns = Terms => { - const fns = { - //blacklist from a {word:true} object - notObj: function(r, obj) { - let matches = []; - let current = []; - r.terms.forEach(t => { - //TODO? support multi-word blacklists - //we should blacklist this term - if (obj.hasOwnProperty(t.normal)) { - if (current.length) { - matches.push(current); - } - current = []; - } else { - current.push(t); - } - }); - //add remainder - if (current.length) { - matches.push(current); - } - matches = matches.map(a => { - return new Terms(a, r.world, r.refText, r.refTerms); - }); - return new Text(matches, r.world, r.parent); - }, - - //blacklist from a match string - notString: function(r, want, verbose) { - let matches = []; - let regs = syntax(want); - let terms = []; - //try the match starting from each term - for (let i = 0; i < r.terms.length; i++) { - let bad = startHere(r, i, regs, verbose); - if (bad && bad.length > 0) { - //reset matches - if (terms.length > 0) { - matches.push(terms); - terms = []; - } - //skip these terms now - i += bad.length - 1; - continue; - } - terms.push(r.terms[i]); - } - //remaining ones - if (terms.length > 0) { - matches.push(terms); - } - matches = matches.map(a => { - return new Terms(a, r.world, r.refText, r.refTerms); - }); - // return matches - return new Text(matches, r.world, r.parent); - } - }; - //blacklist from a [word, word] array - fns.notArray = function(r, arr) { - let obj = arr.reduce((h, a) => { - h[a] = true; - return h; - }, {}); - return fns.notObj(r, obj); - }; - fns.notText = function(r, m) { - let arr = m.out('array'); //i guess this is fine.. - return fns.notArray(r, arr); - }; - - /**return everything but these matches*/ - Terms.prototype.not = function(want, verbose) { - //support [word, word] blacklist - if (typeof want === 'object') { - let type = Object.prototype.toString.call(want); - if (type === '[object Array]') { - return fns.notArray(this, want, verbose); - } - if (type === '[object Object]') { - if (want.isA === 'Text') { - return fns.notText(this, want, verbose); - } else { - return fns.notObj(this, want, verbose); - } - } - } - if (typeof want === 'string') { - return fns.notString(this, want, verbose); - } - return this; - }; - return Terms; -}; - -module.exports = addfns; diff --git a/src/terms/methods/delete.js b/src/terms/methods/delete.js deleted file mode 100644 index cb1691448..000000000 --- a/src/terms/methods/delete.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; -const mutate = require('../mutate'); - -const addMethod = (Terms) => { - - //hook it into Terms.proto - Terms.prototype.delete = function (reg) { - //don't touch parent if empty - if (!this.found) { - return this; - } - //remove all selected - if (!reg) { - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - return this; - } - //only remove a portion of this - let found = this.match(reg); - if (found.found) { - let r = mutate.deleteThese(this, found); - return r; - } - return this.parentTerms; - }; - - return Terms; -}; - -module.exports = addMethod; diff --git a/src/terms/methods/insert.js b/src/terms/methods/insert.js deleted file mode 100644 index ee370f46a..000000000 --- a/src/terms/methods/insert.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; -const mutate = require('../mutate'); - -//whitespace -const addSpaceAt = (ts, i) => { - if (!ts.terms.length || !ts.terms[i]) { - return ts; - } - ts.terms[i].whitespace.before = ' '; - return ts; -}; - -const insertMethods = (Terms) => { - - //accept any sorta thing - const ensureTerms = function(input, world) { - if (input.isA === 'Terms') { - return input; - } - if (input.isA === 'Term') { - return new Terms([input], world); - } - //handle a string - let ts = Terms.fromString(input, world); - ts.tagger(); - return ts; - }; - - const methods = { - - insertBefore: function (input, tag) { - let original_l = this.terms.length; - let ts = ensureTerms(input, this.world); - if (tag) { - ts.tag(tag); - } - let index = this.index(); - //pad a space on parent - addSpaceAt(this.parentTerms, index); - if (index > 0) { - addSpaceAt(ts, 0); //if in middle of sentence - } - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, ts); - //also copy them to current selection - if (this.terms.length === original_l) { - this.terms = ts.terms.concat(this.terms); - } - return this; - }, - - insertAfter: function (input, tag) { - let original_l = this.terms.length; - let ts = ensureTerms(input, this.world); - if (tag) { - ts.tag(tag); - } - let index = this.terms[this.terms.length - 1].index(); - //beginning whitespace to ts - addSpaceAt(ts, 0); - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index + 1, ts); - //also copy them to current selection - if (this.terms.length === original_l) { - this.terms = this.terms.concat(ts.terms); - } - return this; - }, - - insertAt: function (index, input, tag) { - if (index < 0) { - index = 0; - } - let original_l = this.terms.length; - let ts = ensureTerms(input, this.world); - //tag that thing too - if (tag) { - ts.tag(tag); - } - if (index > 0) { - addSpaceAt(ts, 0); //if in middle of sentence - } - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, ts); - //also copy them to current selection - if (this.terms.length === original_l) { - //splice the new terms into this (yikes!) - Array.prototype.splice.apply(this.terms, [index, 0].concat(ts.terms)); - } - //beginning whitespace to ts - if (index === 0) { - this.terms[0].whitespace.before = ''; - ts.terms[ts.terms.length - 1].whitespace.after = ' '; - } - return this; - } - - }; - - //hook them into result.proto - Object.keys(methods).forEach((k) => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = insertMethods; diff --git a/src/terms/methods/loops.js b/src/terms/methods/loops.js deleted file mode 100644 index 39fe958c1..000000000 --- a/src/terms/methods/loops.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; -//these methods are simply term-methods called in a loop - -const addMethods = (Terms) => { - - const foreach = [ - // ['tag'], - // ['unTag'], - // ['canBe'], - ['toUpperCase', 'UpperCase'], - ['toLowerCase'], - ['toTitleCase', 'TitleCase'], - // ['toCamelCase', 'CamelCase'], - ]; - - foreach.forEach((arr) => { - let k = arr[0]; - let tag = arr[1]; - let myFn = function () { - let args = arguments; - this.terms.forEach((t) => { - t[k].apply(t, args); - }); - if (tag) { - this.tag(tag, k); - } - return this; - }; - Terms.prototype[k] = myFn; - }); - return Terms; -}; - -module.exports = addMethods; diff --git a/src/terms/methods/lump/combine.js b/src/terms/methods/lump/combine.js deleted file mode 100644 index 2445e95a3..000000000 --- a/src/terms/methods/lump/combine.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; -const Term = require('../../../term'); -//merge two term objects.. carefully - -const makeText = (a, b) => { - let text = a.whitespace.before + a.text + a.whitespace.after; - text += b.whitespace.before + b.text + b.whitespace.after; - return text; -}; - -const combine = function(s, i) { - let a = s.terms[i]; - let b = s.terms[i + 1]; - if (!b) { - return; - } - let text = makeText(a, b); - s.terms[i] = new Term(text, a.context); - s.terms[i].normal = a.normal + ' ' + b.normal; - s.terms[i].lumped = true; - s.terms[i].parentTerms = s.terms[i + 1].parentTerms; - s.terms[i + 1] = null; - s.terms = s.terms.filter((t) => t !== null); - return; -}; - -module.exports = combine; diff --git a/src/terms/methods/lump/index.js b/src/terms/methods/lump/index.js deleted file mode 100644 index 474ead6e2..000000000 --- a/src/terms/methods/lump/index.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; -const combine = require('./combine'); -const mutate = require('../../mutate'); - -//merge-together our current match into one term -const combineThem = function(ts, tags) { - let len = ts.terms.length; - for(let i = 0; i < len; i++) { - combine(ts, 0); - } - let lumped = ts.terms[0]; - lumped.tags = tags; - return lumped; -}; - -const lumpMethods = (Terms) => { - - Terms.prototype.lump = function () { - //collect the tags up - let index = this.index(); - let tags = {}; - this.terms.forEach((t) => { - Object.keys(t.tags).forEach((tag) => tags[tag] = true); - }); - //just lump the whole-thing together - if (this.parentTerms === this) { - let lumped = combineThem(this, tags); - this.terms = [lumped]; - return this; - } - //otherwise lump just part of it. delete/insert. - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - //merge-together our current match into one term - let lumped = combineThem(this, tags); - //put it back (in the same place) - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, lumped); - return this; - }; - - return Terms; -}; - -module.exports = lumpMethods; diff --git a/src/terms/methods/misc.js b/src/terms/methods/misc.js deleted file mode 100644 index 08e1d44c6..000000000 --- a/src/terms/methods/misc.js +++ /dev/null @@ -1,117 +0,0 @@ -'use strict'; -const tagger = require('../../tagger'); - -const miscMethods = Terms => { - const methods = { - tagger: function() { - tagger(this); - return this; - }, - firstTerm: function() { - return this.terms[0]; - }, - lastTerm: function() { - return this.terms[this.terms.length - 1]; - }, - all: function() { - return this.parent; - }, - data: function() { - return { - text: this.out('text'), - normal: this.out('normal') - }; - }, - term: function(n) { - return this.terms[n]; - }, - first: function() { - let t = this.terms[0]; - return new Terms([t], this.world, this.refText, this.refTerms); - }, - last: function() { - let t = this.terms[this.terms.length - 1]; - return new Terms([t], this.world, this.refText, this.refTerms); - }, - slice: function(start, end) { - let terms = this.terms.slice(start, end); - return new Terms(terms, this.world, this.refText, this.refTerms); - }, - index: function() { - let parent = this.parentTerms; - let first = this.terms[0]; - if (!parent || !first) { - return null; //maybe.. - } - for (let i = 0; i < parent.terms.length; i++) { - if (first === parent.terms[i]) { - return i; - } - } - return null; - }, - termIndex: function() { - let first = this.terms[0]; - let ref = this.refText || this; - if (!ref || !first) { - return null; //maybe.. - } - let n = 0; - for (let i = 0; i < ref.list.length; i++) { - let ts = ref.list[i]; - for (let o = 0; o < ts.terms.length; o++) { - if (ts.terms[o] === first) { - return n; - } - n += 1; - } - } - return n; - }, - //number of characters in this match - chars: function() { - return this.terms.reduce((i, t) => { - i += t.whitespace.before.length; - i += t.text.length; - i += t.whitespace.after.length; - return i; - }, 0); - }, - //just .length - wordCount: function() { - return this.terms.length; - }, - /** punctuation */ - setPunctuation: function(punct) { - let last = this.terms[this.terms.length - 1]; - last.setPunctuation(punct); - }, - getPunctuation: function() { - let lastTerm = this.last().terms[0]; - if (!lastTerm) { - return ''; - } - return lastTerm.getPunctuation() || ''; - }, - //this has term-order logic, so has to be here - toCamelCase: function() { - this.toTitleCase(); - this.terms.forEach((t, i) => { - if (i !== 0) { - t.whitespace.before = ''; - } - t.whitespace.after = ''; - }); - this.tag('#CamelCase', 'toCamelCase'); - return this; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = miscMethods; diff --git a/src/terms/methods/out.js b/src/terms/methods/out.js deleted file mode 100644 index af3911d9c..000000000 --- a/src/terms/methods/out.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; -const fns = require('../paths').fns; - -const methods = { - text: function(ts) { - return ts.terms.reduce((str, t) => { - str += t.out('text'); - return str; - }, ''); - }, - //like 'text', but no leading/trailing whitespace - match: function(ts) { - let str = ''; - let len = ts.terms.length; - for (let i = 0; i < len; i++) { - if (i > 0) { - str += ts.terms[i].whitespace.before; - } - str += ts.terms[i].text.replace(/[,.?!]$/, ''); //remove comma - if (i < len - 1) { - str += ts.terms[i].whitespace.after; - } - } - return str; - }, - - normal: function(ts) { - let terms = ts.terms.filter(t => { - return t.text; - }); - terms = terms.map(t => { - return t.normal; //+ punct; - }); - return terms.join(' '); - }, - - grid: function(ts) { - let str = ' '; - str += ts.terms.reduce((s, t) => { - s += fns.leftPad(t.text, 11); - return s; - }, ''); - return str + '\n\n'; - }, - - color: function(ts) { - return ts.terms.reduce((s, t) => { - s += fns.printTerm(t); - return s; - }, ''); - }, - csv: function(ts) { - return ts.terms.map(t => t.normal.replace(/,/g, '')).join(','); - }, - - newlines: function(ts) { - return ts.terms - .reduce((str, t) => { - str += t.out('text').replace(/\n/g, ' '); - return str; - }, '') - .replace(/^\s/, ''); - }, - /** no punctuation, fancy business **/ - root: function(ts) { - return ts.terms.map(t => t.silent_term || t.root).join(' ').toLowerCase(); - }, - - html: function(ts) { - return ts.terms.map(t => t.render.html()).join(' '); - }, - debug: function(ts) { - ts.terms.forEach(t => { - t.out('debug'); - }); - }, - custom: function(ts, obj) { - return ts.terms.map((t) => { - return Object.keys(obj).reduce((h, k) => { - if (obj[k] && t[k]) { - if (typeof t[k] === 'function') { - h[k] = t[k](); - } else { - h[k] = t[k]; - } - } - return h; - }, {}); - }); - } -}; -methods.plaintext = methods.text; -methods.normalize = methods.normal; -methods.normalized = methods.normal; -methods.colors = methods.color; -methods.tags = methods.terms; - -const renderMethods = Terms => { - Terms.prototype.out = function(fn) { - if (typeof fn === 'string') { - if (methods[fn]) { - return methods[fn](this); - } - } else if (fns.isObject(fn) === true) { //support .out({}) - return methods.custom(this, fn); - } - return methods.text(this); - }; - //check method - Terms.prototype.debug = function() { - return methods.debug(this); - }; - return Terms; -}; - -module.exports = renderMethods; diff --git a/src/terms/methods/replace.js b/src/terms/methods/replace.js deleted file mode 100644 index 0056d5059..000000000 --- a/src/terms/methods/replace.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; -const mutate = require('../mutate'); - -const replaceMethods = Terms => { - const methods = { - /**swap this for that */ - replace: function(str1, str2, keepTags) { - //in this form, we 'replaceWith' - if (str2 === undefined) { - return this.replaceWith(str1, keepTags); - } - this.match(str1).replaceWith(str2, keepTags); - return this; - }, - - /**swap this for that */ - replaceWith: function(str, keepTags) { - let newTs = Terms.fromString(str, this.world); - newTs.tagger(); - //if instructed, apply old tags to new terms - if (keepTags) { - this.terms.forEach((t, i) => { - let tags = Object.keys(t.tags); - if (newTs.terms[i] !== undefined) { - tags.forEach(tg => newTs.terms[i].tag(tg, 'from-memory')); - } - }); - } - //keep its ending punctation.. - let endPunct = this.getPunctuation(); - //grab the insertion place.. - let index = this.index(); - this.parentTerms = mutate.deleteThese(this.parentTerms, this); - this.parentTerms.terms = mutate.insertAt(this.parentTerms.terms, index, newTs); - this.terms = newTs.terms; - //add-in the punctuation at the end.. - if (this.terms.length > 0) { - this.terms[this.terms.length - 1].whitespace.after += endPunct; - } - return this; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = replaceMethods; diff --git a/src/terms/methods/split.js b/src/terms/methods/split.js deleted file mode 100644 index a1e0f293d..000000000 --- a/src/terms/methods/split.js +++ /dev/null @@ -1,117 +0,0 @@ -'use strict'; - -//break apart a termlist into (before, match after) -const breakUpHere = (terms, ts) => { - let firstTerm = ts.terms[0]; - let len = ts.terms.length; - for (let i = 0; i < terms.length; i++) { - if (terms[i] === firstTerm) { - return { - before: terms.slice(0, i), - match: terms.slice(i, i + len), - after: terms.slice(i + len, terms.length) - }; - } - } - return { - after: terms - }; -}; - -const splitMethods = Terms => { - const methods = { - /** at the end of the match, split the terms **/ - splitAfter: function(reg, verbose) { - let ms = this.match(reg, verbose); //Array[ts] - let termArr = this.terms; - let all = []; - ms.list.forEach(lookFor => { - let section = breakUpHere(termArr, lookFor); - if (section.before && section.match) { - all.push(section.before.concat(section.match)); - } - termArr = section.after; - }); - //add the remaining - if (termArr.length) { - all.push(termArr); - } - //make them termlists - all = all.map(ts => { - let parent = this.refText; //|| this; - return new Terms(ts, this.world, parent, this.refTerms); - }); - return all; - }, - - /** return only before & after the match**/ - splitOn: function(reg, verbose) { - let ms = this.match(reg, verbose); //Array[ts] - let termArr = this.terms; - let all = []; - ms.list.forEach(lookFor => { - let section = breakUpHere(termArr, lookFor); - if (section.before) { - all.push(section.before); - } - if (section.match) { - all.push(section.match); - } - termArr = section.after; - }); - //add the remaining - if (termArr.length) { - all.push(termArr); - } - //make them termlists - all = all.filter(a => a && a.length); - all = all.map(ts => new Terms(ts, this.world, ts.refText, this.refTerms)); - return all; - }, - - /** at the start of the match, split the terms**/ - splitBefore: function(reg, verbose) { - let ms = this.match(reg, verbose); //Array[ts] - let termArr = this.terms; - let all = []; - ms.list.forEach(lookFor => { - let section = breakUpHere(termArr, lookFor); - if (section.before) { - all.push(section.before); - } - if (section.match) { - all.push(section.match); - } - termArr = section.after; - }); - //add the remaining - if (termArr.length) { - all.push(termArr); - } - //cleanup-step: merge all (middle) matches with the next one - for (let i = 0; i < all.length; i++) { - for (let o = 0; o < ms.length; o++) { - if (ms.list[o].terms[0] === all[i][0]) { - if (all[i + 1]) { - all[i] = all[i].concat(all[i + 1]); - all[i + 1] = []; - } - } - } - } - //make them termlists - all = all.filter(a => a && a.length); - all = all.map(ts => new Terms(ts, ts.world, ts.refText, this.refTerms)); - return all; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = splitMethods; -exports = splitMethods; diff --git a/src/terms/methods/tag.js b/src/terms/methods/tag.js deleted file mode 100644 index 832df0505..000000000 --- a/src/terms/methods/tag.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -const addMethod = Terms => { - const methods = { - tag: function(tag, reason) { - let tags = []; - if (typeof tag === 'string') { - tags = tag.split(' '); - } - //fancy version: - if (tags.length > 1) { - //do indepenent tags for each term: - this.terms.forEach((t, i) => { - t.tag(tags[i], reason); - }); - return this; - } - //non-fancy version: - this.terms.forEach(t => { - t.tag(tag, reason); - }); - return this; - }, - - unTag: function(tag, reason) { - let tags = []; - if (typeof tag === 'string') { - tags = tag.split(' '); - } - //fancy version: - if (tags.length > 1) { - //do indepenent tags for each term: - this.terms.forEach((t, i) => { - t.unTag(tags[i], reason); - }); - return this; - } - //non-fancy version: - this.terms.forEach(t => { - t.unTag(tag, reason); - }); - return this; - }, - - //which terms are consistent with this tag - canBe: function(tag) { - let terms = this.terms.filter(t => t.canBe(tag)); - return new Terms(terms, this.world, this.refText, this.refTerms); - } - }; - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = addMethod; diff --git a/src/terms/methods/transform.js b/src/terms/methods/transform.js deleted file mode 100644 index 2f4123d17..000000000 --- a/src/terms/methods/transform.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -const transforms = Terms => { - const methods = { - clone: function() { - // this.world = this.world.clone(); - let terms = this.terms.map(t => { - return t.clone(); - }); - return new Terms(terms, this.world, this.refText, null); //, this.refTerms - }, - hyphenate: function() { - this.terms.forEach((t, i) => { - if (i !== this.terms.length - 1) { - t.whitespace.after = '-'; - } - if (i !== 0) { - t.whitespace.before = ''; - } - }); - return this; - }, - dehyphenate: function() { - this.terms.forEach(t => { - if (t.whitespace.after === '-') { - t.whitespace.after = ' '; - } - }); - return this; - }, - trim: function() { - if (this.length <= 0) { - return this; - } - this.terms[0].whitespace.before = ''; - this.terms[this.terms.length - 1].whitespace.after = ''; - return this; - } - }; - - //hook them into result.proto - Object.keys(methods).forEach(k => { - Terms.prototype[k] = methods[k]; - }); - return Terms; -}; - -module.exports = transforms; diff --git a/src/terms/mutate.js b/src/terms/mutate.js deleted file mode 100644 index d3c55b7b6..000000000 --- a/src/terms/mutate.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; -// -const getTerms = (needle) => { - let arr = []; - if (needle.isA === 'Terms') { - arr = needle.terms; - } else if (needle.isA === 'Text') { - arr = needle.flatten().list[0].terms; - } else if (needle.isA === 'Term') { - arr = [needle]; - } - return arr; -}; - -//remove them -exports.deleteThese = (source, needle) => { - let arr = getTerms(needle); - source.terms = source.terms.filter((t) => { - for (let i = 0; i < arr.length; i++) { - if (t === arr[i]) { - return false; - } - } - return true; - }); - return source; -}; - -//add them -exports.insertAt = (terms, i, needle) => { - needle.dirty = true; - let arr = getTerms(needle); - //handle whitespace - if (i > 0 && arr[0] && !arr[0].whitespace.before) { - arr[0].whitespace.before = ' '; - } - //gnarly splice - //-( basically - terms.splice(i+1, 0, arr) ) - Array.prototype.splice.apply(terms, [i, 0].concat(arr)); - return terms; -}; diff --git a/src/terms/paths.js b/src/terms/paths.js deleted file mode 100644 index 6eba3e673..000000000 --- a/src/terms/paths.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - fns: require('../fns'), - Term: require('../term') -}; diff --git a/src/text/build.js b/src/text/build.js deleted file mode 100644 index af103c825..000000000 --- a/src/text/build.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -const Text = require('./index'); -const tokenize = require('./tokenize'); -const paths = require('./paths'); -const Terms = paths.Terms; -const fns = paths.fns; - -const fromString = (str, world) => { - let sentences = []; - //allow pre-tokenized input - if (fns.isArray(str)) { - sentences = str; - } else { - str = fns.ensureString(str); - sentences = tokenize(str); - } - let list = sentences.map(s => Terms.fromString(s, world)); - - let doc = new Text(list, world); - //give each ts a ref to the result - doc.list.forEach(ts => { - ts.refText = doc; - }); - return doc; -}; -module.exports = fromString; diff --git a/src/text/getters.js b/src/text/getters.js deleted file mode 100644 index 72291f312..000000000 --- a/src/text/getters.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - /** did it find anything? */ - found: function() { - return this.list.length > 0; - }, - /** just a handy wrap*/ - parent: function() { - return this.original || this; - }, - /** how many Texts are there?*/ - length: function() { - return this.list.length; - }, - /** nicer than constructor.call.name or whatever*/ - isA: function() { - return 'Text'; - }, - /** the whitespace before and after this match*/ - whitespace: function() { - return { - before: str => { - this.list.forEach(ts => { - ts.whitespace.before(str); - }); - return this; - }, - after: str => { - this.list.forEach(ts => { - ts.whitespace.after(str); - }); - return this; - } - }; - } -}; diff --git a/src/text/index.js b/src/text/index.js deleted file mode 100644 index c9c1e25a2..000000000 --- a/src/text/index.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; -//a Text is an array of termLists -const getters = require('./getters'); - -function Text(arr, world, original) { - this.list = arr || []; - if (typeof world === 'function') { - world = world(); - } - this.world = () => { - return world; - }; - this.original = original; - //apply getters - let keys = Object.keys(getters); - for (let i = 0; i < keys.length; i++) { - Object.defineProperty(this, keys[i], { - get: getters[keys[i]] - }); - } -} -module.exports = Text; - -Text.addMethods = function(cl, obj) { - let fns = Object.keys(obj); - for (let i = 0; i < fns.length; i++) { - cl.prototype[fns[i]] = obj[fns[i]]; - } -}; - -//make a sub-class of this class easily -Text.makeSubset = function(methods, find) { - let Subset = function(arr, world, original) { - Text.call(this, arr, world, original); - }; - //inheritance - Subset.prototype = Object.create(Text.prototype); - Text.addMethods(Subset, methods); - Subset.find = find; - return Subset; -}; - -//apply instance methods -require('./methods/misc')(Text); -require('./methods/loops')(Text); -require('./methods/match')(Text); -require('./methods/out')(Text); -require('./methods/sort')(Text); -require('./methods/split')(Text); -require('./methods/normalize')(Text); -require('./subsets')(Text); - -//apply subset methods -const subset = { - acronyms: require('../subset/acronyms'), - adjectives: require('../subset/adjectives'), - adverbs: require('../subset/adverbs'), - contractions: require('../subset/contractions'), - dates: require('../subset/dates'), - nouns: require('../subset/nouns'), - people: require('../subset/people'), - sentences: require('../subset/sentences'), - terms: require('../subset/terms'), - possessives: require('../subset/possessives'), - values: require('../subset/values'), - verbs: require('../subset/verbs'), - ngrams: require('../subset/ngrams'), - startGrams: require('../subset/ngrams/startGrams'), - endGrams: require('../subset/ngrams/endGrams') -}; -Object.keys(subset).forEach(k => { - Text.prototype[k] = function(num, arg) { - let sub = subset[k]; - let m = sub.find(this, num, arg); - return new subset[k](m.list, this.world, this.parent); - }; -}); -//aliases -Text.prototype.words = Text.prototype.terms; diff --git a/src/text/methods/loops.js b/src/text/methods/loops.js deleted file mode 100644 index 4a5a75f4b..000000000 --- a/src/text/methods/loops.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; -//this methods are simply loops around each termList object. -const methods = [ - 'toTitleCase', - 'toUpperCase', - 'toLowerCase', - 'toCamelCase', - - 'hyphenate', - 'dehyphenate', - 'trim', - - 'insertBefore', - 'insertAfter', - 'insertAt', - - 'replace', - 'replaceWith', - - 'delete', - 'lump', - - 'tagger', - - // 'tag', - 'unTag', -]; - -const addMethods = (Text) => { - methods.forEach((k) => { - Text.prototype[k] = function () { - for(let i = 0; i < this.list.length; i++) { - this.list[i][k].apply(this.list[i], arguments); - } - return this; - }; - }); - - //add an extra optimisation for tag method - Text.prototype.tag = function() { - //fail-fast optimisation - if (this.list.length === 0) { - return this; - } - for(let i = 0; i < this.list.length; i++) { - this.list[i].tag.apply(this.list[i], arguments); - } - return this; - }; -}; - -module.exports = addMethods; diff --git a/src/text/methods/match/index.js b/src/text/methods/match/index.js deleted file mode 100644 index 4d228995f..000000000 --- a/src/text/methods/match/index.js +++ /dev/null @@ -1,169 +0,0 @@ -'use strict'; -const syntaxParse = require('../../../terms/match/lib/syntax'); -const Terms = require('../../../terms'); - -const splitMethods = Text => { - //support "#Noun word" regex-matches - const matchReg = function(r, reg, verbose) { - //parse the 'regex' into some json - let list = []; - reg = syntaxParse(reg); - r.list.forEach(ts => { - //an array of arrays - let matches = ts.match(reg, verbose); - matches.list.forEach(ms => { - list.push(ms); - }); - }); - let parent = r.parent || r; - return new Text(list, r.world(), parent); - }; - - //support {word:true} whitelist - const matchObj = function(r, obj) { - let matches = []; - r.list.forEach(ts => { - ts.terms.forEach(t => { - if (obj.hasOwnProperty(t.normal) === true) { - matches.push(t); - } - }); - }); - matches = matches.map(t => { - return new Terms([t], r.world(), r, t.parentTerms); - }); - return new Text(matches, r.world(), r.parent); - }; - - //support [word, word] whitelist - const matchArr = function(r, arr) { - //its faster this way - let obj = arr.reduce((h, a) => { - h[a] = true; - return h; - }, {}); - return matchObj(r, obj); - }; - - //take a Text object as a match - const matchTextObj = function(r, m) { - let arr = m.out('array'); //i guess this is fine.. - return matchArr(r, arr); - }; - - const methods = { - /** do a regex-like search through terms and return a subset */ - match: function(reg, verbose) { - //fail-fast - if (this.list.length === 0 || reg === undefined || reg === null) { - let parent = this.parent || this; - return new Text([], this.world(), parent); - } - //match "#Noun word" regex - if (typeof reg === 'string' || typeof reg === 'number') { - return matchReg(this, reg, verbose); - } - //match [word, word] whitelist - let type = Object.prototype.toString.call(reg); - if (type === '[object Array]') { - return matchArr(this, reg); - } - //match {word:true} whitelist - if (type === '[object Object]') { - if (reg.isA === 'Text') { - return matchTextObj(this, reg); - } else { - return matchObj(this, reg); - } - } - return this; - }, - - not: function(reg, verbose) { - let list = []; - this.list.forEach(ts => { - let found = ts.not(reg, verbose); - list = list.concat(found.list); - }); - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - if: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === true) { - list.push(this.list[i]); - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - ifNo: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === false) { - list.push(this.list[i]); - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - has: function(reg) { - for (let i = 0; i < this.list.length; i++) { - if (this.list[i].has(reg) === true) { - return true; - } - } - return false; - }, - - /**find a match, and return everything infront of it*/ - before: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - let m = this.list[i].matchOne(reg); - if (m) { - let index = m[0].index(); - let found = this.list[i].slice(0, index); - if (found.length > 0) { - list.push(found); - } - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - }, - - /**find a match, and return everything after of it*/ - after: function(reg) { - let list = []; - for (let i = 0; i < this.list.length; i++) { - let m = this.list[i].matchOne(reg); - if (m) { - let lastTerm = m[m.length - 1]; - let index = lastTerm.index(); - let found = this.list[i].slice(index + 1, this.list[i].length); - if (found.length > 0) { - list.push(found); - } - } - } - let parent = this.parent || this; - return new Text(list, this.world(), parent); - } - }; - //alias 'and' - methods.and = methods.match; - methods.notIf = methods.ifNo; - methods.only = methods.if; - methods.onlyIf = methods.if; - - //hook them into result.proto - Text.addMethods(Text, methods); - return Text; -}; - -module.exports = splitMethods; diff --git a/src/text/methods/misc.js b/src/text/methods/misc.js deleted file mode 100644 index 75cac880d..000000000 --- a/src/text/methods/misc.js +++ /dev/null @@ -1,199 +0,0 @@ -'use strict'; -const Terms = require('../../terms'); - -const miscMethods = Text => { - const methods = { - all: function() { - return this.parent; - }, - index: function() { - return this.list.map(ts => ts.index()); - }, - wordCount: function() { - return this.terms().length; - }, - data: function() { - return this.list.map(ts => ts.data()); - }, - /* javascript array loop-wrappers */ - map: function(fn) { - return this.list.map((ts, i) => { - let text = new Text([ts], this.world); - return fn(text, i); - }); - }, - forEach: function(fn) { - this.list.forEach((ts, i) => { - let text = new Text([ts], this.world); - fn(text, i); - }); - return this; - }, - filter: function(fn) { - let list = this.list.filter((ts, i) => { - let text = new Text([ts], this.world); - return fn(text, i); - }); - return new Text(list, this.world); - }, - reduce: function(fn, h) { - return this.list.reduce((_h, ts) => { - let text = new Text([ts], this.world); - return fn(_h, text); - }, h); - }, - find: function(fn) { - for (let i = 0; i < this.list.length; i++) { - let ts = this.list[i]; - let text = new Text([ts], this.world); - if (fn(text)) { - return text; - } - } - return undefined; - }, - /**copy data properly so later transformations will have no effect*/ - clone: function() { - let list = this.list.map(ts => { - return ts.clone(); - }); - return new Text(list, this.world); //this.lexicon, this.parent - }, - - /** get the nth term of each result*/ - term: function(n) { - let list = this.list.map(ts => { - let arr = []; - let el = ts.terms[n]; - if (el) { - arr = [el]; - } - return new Terms(arr, this.world, this.refText, this.refTerms); - }); - return new Text(list, this.world, this.parent); - }, - firstTerm: function() { - return this.match('^.'); - }, - lastTerm: function() { - return this.match('.$'); - }, - - /** grab a subset of the results*/ - slice: function(start, end) { - this.list = this.list.slice(start, end); - return this; - }, - - /** use only the nth result*/ - get: function(n) { - //return an empty result - if ((!n && n !== 0) || !this.list[n]) { - return new Text([], this.world, this.parent); - } - let ts = this.list[n]; - return new Text([ts], this.world, this.parent); - }, - /**use only the first result */ - first: function(n) { - if (!n && n !== 0) { - return this.get(0); - } - return new Text(this.list.slice(0, n), this.world, this.parent); - }, - /**use only the last result */ - last: function(n) { - if (!n && n !== 0) { - return this.get(this.list.length - 1); - } - let end = this.list.length; - let start = end - n; - return new Text(this.list.slice(start, end), this.world, this.parent); - }, - - concat: function() { - //any number of params - for (let i = 0; i < arguments.length; i++) { - let p = arguments[i]; - if (typeof p === 'object') { - //Text() - if (p.isA === 'Text' && p.list) { - this.list = this.list.concat(p.list); - } - //Terms() - if (p.isA === 'Terms') { - this.list.push(p); - } - } - } - return this; - }, - - /** make it into one sentence/termlist */ - flatten: function() { - let terms = []; - this.list.forEach(ts => { - terms = terms.concat(ts.terms); - }); - //dont create an empty ts - if (!terms.length) { - return new Text(null, this.world, this.parent); - } - let ts = new Terms(terms, this.world, this, null); - return new Text([ts], this.world, this.parent); - }, - - /** see if these terms can become this tag*/ - canBe: function(tag) { - this.list.forEach(ts => { - ts.terms = ts.terms.filter(t => { - return t.canBe(tag); - }); - }); - return this; - }, - - /** sample part of the array */ - random: function(n) { - n = n || 1; - let r = Math.floor(Math.random() * this.list.length); - let arr = this.list.slice(r, r + n); - //if we're off the end, add some from the start - if (arr.length < n) { - let diff = n - arr.length; - if (diff > r) { - diff = r; //prevent it from going full-around - } - arr = arr.concat(this.list.slice(0, diff)); - } - return new Text(arr, this.world, this.parent); - }, - setPunctuation: function(punct) { - this.list.forEach((ts) => ts.setPunctuation(punct)); - return this; - }, - getPunctuation: function(num) { - //support num param - if (num || num === 0) { - if (!this.list[num]) { - return ''; - } - return this.list[num].getPunctuation(); - } - return this.list.map((ts) => ts.getPunctuation()); - }, - //jquery-like api aliases - offset: function() { - return this.out('offset'); - }, - text: function() { - return this.out('text'); - } - }; - //aliases - methods.eq = methods.get; - methods.join = methods.flatten; - Text.addMethods(Text, methods); -}; - -module.exports = miscMethods; diff --git a/src/text/methods/normalize.js b/src/text/methods/normalize.js deleted file mode 100644 index add65d5ee..000000000 --- a/src/text/methods/normalize.js +++ /dev/null @@ -1,153 +0,0 @@ -'use strict'; -const unicode = require('../../term/methods/normalize/unicode'); -// -const defaults = { - whitespace: true, - case: true, - numbers: true, - punctuation: true, - unicode: true, - contractions: true, - acronyms: true, - - parentheses: false, - possessives: false, - plurals: false, - verbs: false, - honorifics: false, -}; - -const methods = { - /** make only one space between each word */ - whitespace: r => { - r.terms().list.forEach((ts, i) => { - let t = ts.terms[0]; - if (i > 0 && !t.silent_term) { - t.whitespace.before = ' '; - } else if (i === 0) { - t.whitespace.before = ''; - } - t.whitespace.after = ''; - //add normalized quotation symbols - if (t.tags.StartQuotation === true) { - t.whitespace.before += '"'; - } - if (t.tags.EndQuotation === true) { - t.whitespace.after = '"' + t.whitespace.after; - } - }); - return r; - }, - - /** make first-word titlecase, and people, places titlecase */ - case: r => { - r.list.forEach(ts => { - ts.terms.forEach((t, i) => { - if (i === 0 || t.tags.Person || t.tags.Place || t.tags.Organization) { - // ts.toTitleCase() //fixme: too weird here. - } else { - ts.toLowerCase(); - } - }); - }); - return r; - }, - - /** turn 'five' to 5, and 'fifth' to 5th*/ - numbers: r => { - r.values().toNumber(); - return r; - }, - - /** remove commas, semicolons - but keep sentence-ending punctuation*/ - punctuation: r => { - r.list.forEach(ts => { - if (!ts.terms.length) { - return; - } - - //first-term punctuation - ts.terms[0]._text = ts.terms[0]._text.replace(/^¿/, ''); - //middle-terms - for (let i = 0; i < ts.terms.length - 1; i++) { - let t = ts.terms[i]; - //remove non-sentence-ending stuff - t._text = t._text.replace(/[:;,]$/, ''); - } - //replace !!! with ! - let last = ts.terms[ts.terms.length - 1]; - last._text = last._text.replace(/\.+$/, '.'); - last._text = last._text.replace(/!+$/, '!'); - last._text = last._text.replace(/\?+!?$/, '?'); //support '?!' - }); - return r; - }, - - // turn Björk into Bjork - unicode: r => { - r.list.forEach((ts) => { - ts.terms.forEach((t) => { - t.text = unicode(t.text); - }); - }); - return r; - }, - - //expand all contractions - contractions: r => { - r.contractions().expand(); - return r; - }, - //remove periods from acronyms, like F.B.I. - acronyms: r => { - r.acronyms().stripPeriods(); - return r; - }, - //turn david's → david - possessives: r => { - r.possessives().strip(); - return r; - }, - //strip out parts in (brackets) - parentheses: r => { - r.parentheses().delete(); - return r; - }, - //turn sandwhiches → sandwhich - plurals: r => { //todo:this has a non-cooperative bug - r.nouns().toSingular(); - return r; - }, - //turn ate → eat - verbs: r => { - r.verbs().toInfinitive(); - return r; - }, - - //turn 'Sergeant Pepper to 'Pepper' - honorifics: r => { - r = r.delete('#Honorific'); - return r; - } -}; - -const addMethods = Text => { - Text.prototype.normalize = function (options) { - let doc = this; - //set defaults - options = options || {}; - let obj = Object.assign({}, defaults); - let keys = Object.keys(options); - keys.forEach((k) => { - obj[k] = options[k]; - }); - //do each type of normalization - Object.keys(obj).forEach(fn => { - if (obj[fn] && methods[fn] !== undefined) { - doc = methods[fn](doc); - } - }); - return doc; - }; -}; -module.exports = addMethods; diff --git a/src/text/methods/out/index.js b/src/text/methods/out/index.js deleted file mode 100644 index 38c0dc139..000000000 --- a/src/text/methods/out/index.js +++ /dev/null @@ -1,161 +0,0 @@ -'use strict'; -const topk = require('./topk'); -const offset = require('./offset'); -const termIndex = require('./indexes'); -const fns = require('../paths').fns; - -const methods = { - text: r => { - return r.list.reduce((str, ts) => { - str += ts.out('text'); - return str; - }, ''); - }, - match: r => { - return r.list.reduce((str, ts) => { - str += ts.out('match'); - return str; - }, ''); - }, - normal: r => { - return r.list - .map(ts => { - let str = ts.out('normal'); - let last = ts.last(); - if (last) { - let punct = ts.getPunctuation(); - if (punct === '.' || punct === '!' || punct === '?') { - str += punct; - } - } - return str; - }) - .join(' '); - }, - root: r => { - return r.list - .map(ts => { - return ts.out('root'); - }) - .join(' '); - }, - /** output where in the original output string they are*/ - offsets: r => { - return offset(r); - }, - /** output the tokenized location of this match*/ - index: r => { - return termIndex(r); - }, - grid: r => { - return r.list.reduce((str, ts) => { - str += ts.out('grid'); - return str; - }, ''); - }, - color: r => { - return r.list.reduce((str, ts) => { - str += ts.out('color'); - return str; - }, ''); - }, - array: r => { - return r.list.map(ts => { - return ts.out('normal'); - }); - }, - csv: r => { - return r.list - .map(ts => { - return ts.out('csv'); - }) - .join('\n'); - }, - newlines: r => { - return r.list - .map(ts => { - return ts.out('newlines'); - }) - .join('\n'); - }, - json: r => { - return r.list.reduce((arr, ts) => { - let terms = ts.terms.map(t => { - return { - text: t.text, - normal: t.normal, - tags: t.tag - }; - }); - arr.push(terms); - return arr; - }, []); - }, - html: r => { - let html = r.list.reduce((str, ts) => { - let sentence = ts.terms.reduce((sen, t) => { - sen += '\n ' + t.out('html'); - return sen; - }, ''); - return (str += '\n ' + sentence + '\n '); - }, ''); - return ' ' + html + '\n'; - }, - terms: r => { - let arr = []; - r.list.forEach(ts => { - ts.terms.forEach(t => { - arr.push({ - text: t.text, - normal: t.normal, - tags: Object.keys(t.tags) - }); - }); - }); - return arr; - }, - debug: r => { - console.log('===='); - r.list.forEach(ts => { - console.log(' --'); - ts.debug(); - }); - return r; - }, - topk: r => { - return topk(r); - }, - custom: (r, obj) => { - return r.list.map((ts) => ts.out(obj)); - } -}; -methods.plaintext = methods.text; -methods.normalized = methods.normal; -methods.colors = methods.color; -methods.tags = methods.terms; -methods.offset = methods.offsets; -methods.idexes = methods.index; -methods.frequency = methods.topk; -methods.freq = methods.topk; -methods.arr = methods.array; - - - -const addMethods = Text => { - Text.prototype.out = function(fn) { - if (typeof fn === 'string') { - if (methods[fn]) { - return methods[fn](this); - } - } else if (fns.isObject(fn) === true) { //support .out({}) - return methods.custom(this, fn); - } - return methods.text(this); - }; - Text.prototype.debug = function() { - return methods.debug(this); - }; - return Text; -}; - -module.exports = addMethods; diff --git a/src/text/methods/out/indexes.js b/src/text/methods/out/indexes.js deleted file mode 100644 index ec7b9c212..000000000 --- a/src/text/methods/out/indexes.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -//find where in the original text this match is found, by term-counts -const termIndex = (r) => { - let result = []; - //find the ones we want - let want = {}; - r.terms().list.forEach((ts) => { - want[ts.terms[0].uid] = true; - }); - - //find their counts - let sum = 0; - let parent = r.all(); - parent.list.forEach((ts, s) => { - ts.terms.forEach((t, i) => { - if (want[t.uid] !== undefined) { - result.push({ - text: t.text, - normal: t.normal, - term: sum, - sentence: s, - sentenceTerm: i - }); - } - sum += 1; - }); - }); - - return result; -}; -module.exports = termIndex; diff --git a/src/text/methods/out/offset.js b/src/text/methods/out/offset.js deleted file mode 100644 index 2b3ad3c04..000000000 --- a/src/text/methods/out/offset.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; -/** say where in the original output string they are found*/ - -const findOffset = (parent, term) => { - let sum = 0; - for(let i = 0; i < parent.list.length; i++) { - for(let o = 0; o < parent.list[i].terms.length; o++) { - let t = parent.list[i].terms[o]; - if (t.uid === term.uid) { - return sum; - } else { - sum += t.whitespace.before.length + t._text.length + t.whitespace.after.length; - } - } - } - return null; -}; - -//like 'text' for the middle, and 'normal' for the start+ends -//used for highlighting the actual words, without whitespace+punctuation -const trimEnds = function(ts) { - let terms = ts.terms; - if (terms.length <= 2) { - return ts.out('normal'); - } - //the start - let str = terms[0].normal; - //the middle - for(let i = 1; i < terms.length - 1; i++) { - let t = terms[i]; - str += t.whitespace.before + t.text + t.whitespace.after; - } - //the end - str += ' ' + terms[ts.terms.length - 1].normal; - return str; -}; - -//map over all-dem-results -const allOffset = (r) => { - let parent = r.all(); - return r.list.map((ts) => { - let words = []; - for(let i = 0; i < ts.terms.length; i++) { - words.push(ts.terms[i].normal); - } - let nrml = trimEnds(ts); - let txt = ts.out('text'); - let startAt = findOffset(parent, ts.terms[0]); - let beforeWord = ts.terms[0].whitespace.before; - let wordStart = startAt + beforeWord.length; - return { - text: txt, - normal: ts.out('normal'), - //where we begin - offset: startAt, - length: txt.length, - wordStart: wordStart, - wordEnd: wordStart + nrml.length, - // wordLength: words.join(' ').length - }; - }); -}; -module.exports = allOffset; diff --git a/src/text/methods/out/topk.js b/src/text/methods/out/topk.js deleted file mode 100644 index 2769b5cf4..000000000 --- a/src/text/methods/out/topk.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -// -const topk = function (r, n) { - //count occurance - let count = {}; - r.list.forEach((ts) => { - let str = ts.out('root'); - count[str] = count[str] || 0; - count[str] += 1; - }); - //turn into an array - let all = []; - Object.keys(count).forEach((k) => { - all.push({ - normal: k, - count: count[k], - }); - }); - //add percentage - all.forEach((o) => { - o.percent = parseFloat(((o.count / r.list.length) * 100).toFixed(2)); - }); - //sort by freq - all = all.sort((a, b) => { - if (a.count > b.count) { - return -1; - } - return 1; - }); - if (n) { - all = all.splice(0, n); - } - return all; -}; - -module.exports = topk; diff --git a/src/text/methods/paths.js b/src/text/methods/paths.js deleted file mode 100644 index 5abb79ca5..000000000 --- a/src/text/methods/paths.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../paths'); diff --git a/src/text/methods/sort/index.js b/src/text/methods/sort/index.js deleted file mode 100644 index 05b0a44a4..000000000 --- a/src/text/methods/sort/index.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict'; -const sorter = require('./methods'); - -const addMethods = (Text) => { - - const fns = { - - /**reorder result.list alphabetically */ - sort: function (method) { - //default sort - method = method || 'alphabetical'; - method = method.toLowerCase(); - if (!method || method === 'alpha' || method === 'alphabetical') { - return sorter.alpha(this, Text); - } - if (method === 'chron' || method === 'chronological') { - return sorter.chron(this, Text); - } - if (method === 'length') { - return sorter.lengthFn(this, Text); - } - if (method === 'freq' || method === 'frequency') { - return sorter.freq(this, Text); - } - if (method === 'wordcount') { - return sorter.wordCount(this, Text); - } - return this; - }, - - /**reverse the order of result.list */ - reverse: function () { - this.list = this.list.reverse(); - return this; - }, - - unique: function () { - let obj = {}; - this.list = this.list.filter((ts) => { - let str = ts.out('root'); - if (obj.hasOwnProperty(str)) { - return false; - } - obj[str] = true; - return true; - }); - return this; - } - }; - //hook them into result.proto - Text.addMethods(Text, fns); - return Text; -}; - -module.exports = addMethods; diff --git a/src/text/methods/sort/methods.js b/src/text/methods/sort/methods.js deleted file mode 100644 index bf95dadc6..000000000 --- a/src/text/methods/sort/methods.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -//perform sort on pre-computed values -const sortEm = function(arr) { - arr = arr.sort((a, b) => { - if (a.index > b.index) { - return 1; - } - if (a.index === b.index) { - return 0; - } - return -1; - }); - //return ts objects - return arr.map((o) => o.ts); -}; - -//alphabetical sorting of a termlist array -exports.alpha = function(r) { - r.list.sort((a, b) => { - //#1 performance speedup - if (a === b) { - return 0; - } - //#2 performance speedup - if (a.terms[0] && b.terms[0]) { - if (a.terms[0].root > b.terms[0].root) { - return 1; - } - if (a.terms[0].root < b.terms[0].root) { - return -1; - } - } - //regular compare - if (a.out('root') > b.out('root')) { - return 1; - } - return -1; - }); - return r; -}; - -//the order they were recieved (chronological~) -exports.chron = function(r) { - //pre-compute indexes - let tmp = r.list.map((ts) => { - return { - ts: ts, - index: ts.termIndex() - }; - }); - r.list = sortEm(tmp); - return r; -}; - -//shortest matches first -exports.lengthFn = function(r) { - //pre-compute indexes - let tmp = r.list.map((ts) => { - return { - ts: ts, - index: ts.chars() - }; - }); - r.list = sortEm(tmp).reverse(); - return r; -}; - -//count the number of terms in each match -exports.wordCount = function(r) { - //pre-compute indexes - let tmp = r.list.map((ts) => { - return { - ts: ts, - index: ts.length - }; - }); - r.list = sortEm(tmp); - return r; -}; - -//sort by frequency (like topk) -exports.freq = function(r) { - //get counts - let count = {}; - r.list.forEach((ts) => { - let str = ts.out('root'); - count[str] = count[str] || 0; - count[str] += 1; - }); - //pre-compute indexes - let tmp = r.list.map((ts) => { - let num = count[ts.out('root')] || 0; - return { - ts: ts, - index: num * -1 //quick-reverse it - }; - }); - r.list = sortEm(tmp); - return r; -}; diff --git a/src/text/methods/split.js b/src/text/methods/split.js deleted file mode 100644 index 392a660f5..000000000 --- a/src/text/methods/split.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -const splitMethods = (Text) => { - - const methods = { - /** turn result into two seperate results */ - splitAfter: function(reg, verbose) { - let list = []; - this.list.forEach((ts) => { - ts.splitAfter(reg, verbose).forEach((mts) => { - list.push(mts); - }); - }); - this.list = list; - return this; - }, - /** turn result into two seperate results */ - splitBefore: function(reg, verbose) { - let list = []; - this.list.forEach((ts) => { - ts.splitBefore(reg, verbose).forEach((mts) => { - list.push(mts); - }); - }); - this.list = list; - return this; - }, - /** turn result into two seperate results */ - splitOn: function(reg, verbose) { - let list = []; - this.list.forEach((ts) => { - ts.splitOn(reg, verbose).forEach((mts) => { - list.push(mts); - }); - }); - this.list = list; - return this; - }, - }; - - //hook them into result.proto - Text.addMethods(Text, methods); - return Text; -}; - -module.exports = splitMethods; diff --git a/src/text/paths.js b/src/text/paths.js deleted file mode 100644 index 5abb79ca5..000000000 --- a/src/text/paths.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../paths'); diff --git a/src/text/subsets.js b/src/text/subsets.js deleted file mode 100644 index d01d94693..000000000 --- a/src/text/subsets.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; -const isQuestion = require('../subset/sentences/isQuestion'); -const addSubsets = Text => { - //these subsets have no instance methods, so are simply a 'find' method. - const subsets = { - clauses: function (n) { - let r = this.splitAfter('#ClauseEnd'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - hashTags: function (n) { - let r = this.match('#HashTag').terms(); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - organizations: function (n) { - let r = this.splitAfter('#Comma'); - r = r.match('#Organization+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - phoneNumbers: function (n) { - let r = this.splitAfter('#Comma'); - r = r.match('#PhoneNumber+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - places: function (n) { - let r = this.splitAfter('#Comma'); - r = r.match('#Place+'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - quotations: function (n) { - let matches = this.match('#Quotation+'); - let found = []; - matches.list.forEach((ts) => { - let open = 0; - let start = null; - //handle nested quotes - 'startQuote->startQuote->endQuote->endQuote' - ts.terms.forEach((t, i) => { - if (t.tags.StartQuotation === true) { - if (open === 0) { - start = i; - } - open += 1; - } - if (open > 0 && t.tags.EndQuotation === true) { - open -= 1; - } - if (open === 0 && start !== null) { - found.push(ts.slice(start, i + 1)); - start = null; - } - }); - //maybe we messed something up.. - if (start !== null) { - found.push(ts.slice(start, ts.terms.length)); - } - }); - matches.list = found; - if (typeof n === 'number') { - matches = matches.get(n); - } - return matches; - }, - topics: function (n) { - let r = this.clauses(); - // Find people, places, and organizations - let yup = r.people(); - yup.concat(r.places()); - yup.concat(r.organizations()); - let ignore = ['someone', 'man', 'woman', 'mother', 'brother', 'sister', 'father']; - yup = yup.not(ignore); - //return them to normal ordering - yup.sort('chronological'); - // yup.unique() //? not sure - if (typeof n === 'number') { - yup = yup.get(n); - } - return yup; - }, - urls: function (n) { - let r = this.match('#Url'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - questions: function (n) { - let r = this.all(); - if (typeof n === 'number') { - r = r.get(n); - } - let list = r.list.filter(ts => isQuestion(ts)); - return new Text(list, this.world, this.parent); - }, - statements: function (n) { - let r = this.all(); - if (typeof n === 'number') { - r = r.get(n); - } - let list = r.list.filter(ts => isQuestion(ts) === false); - return new Text(list, this.world, this.parent); - }, - parentheses: function (n) { - let r = this.match('#Parentheses+'); - //split-up consecutive ones - r = r.splitAfter('#EndBracket'); - if (typeof n === 'number') { - r = r.get(n); - } - return r; - }, - }; - - Object.keys(subsets).forEach(k => { - Text.prototype[k] = subsets[k]; - }); - return Text; -}; -module.exports = addSubsets; diff --git a/src/text/tokenize.js b/src/text/tokenize.js deleted file mode 100644 index 28604f0ec..000000000 --- a/src/text/tokenize.js +++ /dev/null @@ -1,99 +0,0 @@ -//(Rule-based sentence boundary segmentation) - chop given text into its proper sentences. -// Ignore periods/questions/exclamations used in acronyms/abbreviations/numbers, etc. -// @spencermountain 2017 MIT -'use strict'; -const abbreviations = Object.keys(require('../world/more-data/abbreviations')); -// \u203D - Interrobang -// \u2E18 - Inverted Interrobang -// \u203C - Double Exclamation Mark -// \u2047 - Double Question Mark -// \u2048 - Question Exclamation Mark -// \u2049 - Exclamation Question Mark -// \u2026 - Ellipses Character - -//regs- -const abbrev_reg = new RegExp( - '\\b(' + abbreviations.join('|') + ')[.!?\u203D\u2E18\u203C\u2047-\u2049] *$', - 'i' -); -const acronym_reg = /[ .][A-Z]\.? *$/i; -const ellipses_reg = /(?:\u2026|\.{2,}) *$/; - -// Match different formats of new lines. (Mac: \r, Linux: \n, Windows: \r\n) -const new_line = /((?:\r?\n|\r)+)/; -const naiive_sentence_split = /(\S.+?[.!?\u203D\u2E18\u203C\u2047-\u2049])(?=\s+|$)/g; - -const letter_regex = /[a-z0-9\u0000-\u007F]/i; //support an all-unicode sentence, i guess -const not_ws_regex = /\S/; - -// Start with a regex: -const naiive_split = function(text) { - let all = []; - //first, split by newline - let lines = text.split(new_line); - for (let i = 0; i < lines.length; i++) { - //split by period, question-mark, and exclamation-mark - let arr = lines[i].split(naiive_sentence_split); - for (let o = 0; o < arr.length; o++) { - all.push(arr[o]); - } - } - return all; -}; - -const sentence_parser = function(text) { - text = text || ''; - text = String(text); - let sentences = []; - // First do a greedy-split.. - let chunks = []; - // Ensure it 'smells like' a sentence - if (!text || typeof text !== 'string' || not_ws_regex.test(text) === false) { - return sentences; - } - // Start somewhere: - let splits = naiive_split(text); - // Filter-out the grap ones - for (let i = 0; i < splits.length; i++) { - let s = splits[i]; - if (s === undefined || s === '') { - continue; - } - //this is meaningful whitespace - if (not_ws_regex.test(s) === false) { - //add it to the last one - if (chunks[chunks.length - 1]) { - chunks[chunks.length - 1] += s; - continue; - } else if (splits[i + 1]) { - //add it to the next one - splits[i + 1] = s + splits[i + 1]; - continue; - } - } - //else, only whitespace, no terms, no sentence - chunks.push(s); - } - - //detection of non-sentence chunks: - //loop through these chunks, and join the non-sentence chunks back together.. - for (let i = 0; i < chunks.length; i++) { - let c = chunks[i]; - //should this chunk be combined with the next one? - if (chunks[i + 1] && letter_regex.test(c) && (abbrev_reg.test(c) || acronym_reg.test(c) || ellipses_reg.test(c))) { - chunks[i + 1] = c + (chunks[i + 1] || ''); - } else if (c && c.length > 0 && letter_regex.test(c)) { - //this chunk is a proper sentence.. - sentences.push(c); - chunks[i] = ''; - } - } - //if we never got a sentence, return the given text - if (sentences.length === 0) { - return [text]; - } - return sentences; -}; - -module.exports = sentence_parser; -// console.log(sentence_parser('john f. kennedy')); diff --git a/src/transforms/adjectives/index.js b/src/transforms/adjectives/index.js new file mode 100644 index 000000000..fc8510496 --- /dev/null +++ b/src/transforms/adjectives/index.js @@ -0,0 +1,21 @@ +const fns = { + toSuperlative: require('./toSuperlative'), + toComparative: require('./toComparative'), +} + +/** conjugate an adjective into other forms */ +const conjugate = function(w) { + let res = {} + // 'greatest' + let sup = fns.toSuperlative(w) + if (sup) { + res.Superlative = sup + } + // 'greater' + let comp = fns.toComparative(w) + if (comp) { + res.Comparative = comp + } + return res +} +module.exports = conjugate diff --git a/src/transforms/adjectives/toComparative.js b/src/transforms/adjectives/toComparative.js new file mode 100644 index 000000000..46d41efad --- /dev/null +++ b/src/transforms/adjectives/toComparative.js @@ -0,0 +1,67 @@ +//turn 'quick' into 'quickly' +const do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /old$/, /oud$/, /e[ae]p$/] +const dont_rules = [/ary$/, /ous$/] + +const irregulars = { + grey: 'greyer', + gray: 'grayer', + green: 'greener', + yellow: 'yellower', + red: 'redder', + good: 'better', + well: 'better', + bad: 'worse', + sad: 'sadder', + big: 'bigger', +} + +const transforms = [ + { + reg: /y$/i, + repl: 'ier', + }, + { + reg: /([aeiou])t$/i, + repl: '$1tter', + }, + { + reg: /([aeou])de$/i, + repl: '$1der', + }, + { + reg: /nge$/i, + repl: 'nger', + }, +] + +const to_comparative = function(str) { + //known-irregulars + if (irregulars.hasOwnProperty(str)) { + return irregulars[str] + } + //known-transforms + for (let i = 0; i < transforms.length; i++) { + if (transforms[i].reg.test(str) === true) { + return str.replace(transforms[i].reg, transforms[i].repl) + } + } + //dont-patterns + for (let i = 0; i < dont_rules.length; i++) { + if (dont_rules[i].test(str) === true) { + return null + } + } + //do-patterns + for (let i = 0; i < do_rules.length; i++) { + if (do_rules[i].test(str) === true) { + return str + 'er' + } + } + //easy-one + if (/e$/.test(str) === true) { + return str + 'r' + } + return str + 'er' +} + +module.exports = to_comparative diff --git a/src/transforms/adjectives/toSuperlative.js b/src/transforms/adjectives/toSuperlative.js new file mode 100644 index 000000000..98da5683c --- /dev/null +++ b/src/transforms/adjectives/toSuperlative.js @@ -0,0 +1,71 @@ +//turn 'quick' into 'quickest' +const do_rules = [/ght$/, /nge$/, /ough$/, /ain$/, /uel$/, /[au]ll$/, /ow$/, /oud$/, /...p$/] +const dont_rules = [/ary$/] + +const irregulars = { + nice: 'nicest', + late: 'latest', + hard: 'hardest', + inner: 'innermost', + outer: 'outermost', + far: 'furthest', + worse: 'worst', + bad: 'worst', + good: 'best', + big: 'biggest', + large: 'largest', +} + +const transforms = [ + { + reg: /y$/i, + repl: 'iest', + }, + { + reg: /([aeiou])t$/i, + repl: '$1ttest', + }, + { + reg: /([aeou])de$/i, + repl: '$1dest', + }, + { + reg: /nge$/i, + repl: 'ngest', + }, + { + reg: /([aeiou])te$/i, + repl: '$1test', + }, +] + +const to_superlative = function(str) { + //irregulars + if (irregulars.hasOwnProperty(str)) { + return irregulars[str] + } + //known transforms + for (let i = 0; i < transforms.length; i++) { + if (transforms[i].reg.test(str)) { + return str.replace(transforms[i].reg, transforms[i].repl) + } + } + //dont-rules + for (let i = 0; i < dont_rules.length; i++) { + if (dont_rules[i].test(str) === true) { + return null + } + } + //do-rules + for (let i = 0; i < do_rules.length; i++) { + if (do_rules[i].test(str) === true) { + if (str.charAt(str.length - 1) === 'e') { + return str + 'st' + } + return str + 'est' + } + } + return str + 'est' +} + +module.exports = to_superlative diff --git a/src/transforms/conjugate/01-suffixes.js b/src/transforms/conjugate/01-suffixes.js new file mode 100644 index 000000000..f869f87c4 --- /dev/null +++ b/src/transforms/conjugate/01-suffixes.js @@ -0,0 +1,33 @@ +const suffixes = require('./suffixes') +const posMap = { + pr: 'PresentTense', + pa: 'PastTense', + gr: 'Gerund', + prt: 'Participle', + ar: 'Actor', +} + +const doTransform = function(str, obj) { + let found = {} + let keys = Object.keys(obj.repl) + for (let i = 0; i < keys.length; i += 1) { + let pos = keys[i] + found[posMap[pos]] = str.replace(obj.reg, obj.repl[pos]) + } + return found +} + +//look at the end of the word for clues +const checkSuffix = function(str = '') { + let c = str[str.length - 1] + if (suffixes.hasOwnProperty(c) === true) { + for (let r = 0; r < suffixes[c].length; r += 1) { + const reg = suffixes[c][r].reg + if (reg.test(str) === true) { + return doTransform(str, suffixes[c][r]) + } + } + } + return {} +} +module.exports = checkSuffix diff --git a/src/transforms/conjugate/02-generic.js b/src/transforms/conjugate/02-generic.js new file mode 100644 index 000000000..1e5d0e35b --- /dev/null +++ b/src/transforms/conjugate/02-generic.js @@ -0,0 +1,36 @@ +//non-specifc, 'hail-mary' transforms from infinitive, into other forms +const hasY = /[bcdfghjklmnpqrstvwxz]y$/ + +const generic = { + Gerund: inf => { + if (inf.charAt(inf.length - 1) === 'e') { + return inf.replace(/e$/, 'ing') + } + return inf + 'ing' + }, + + PresentTense: inf => { + if (inf.charAt(inf.length - 1) === 's') { + return inf + 'es' + } + if (hasY.test(inf) === true) { + return inf.slice(0, -1) + 'ies' + } + return inf + 's' + }, + + PastTense: inf => { + if (inf.charAt(inf.length - 1) === 'e') { + return inf + 'd' + } + if (inf.substr(-2) === 'ed') { + return inf + } + if (hasY.test(inf) === true) { + return inf.slice(0, -1) + 'ied' + } + return inf + 'ed' + }, +} + +module.exports = generic diff --git a/src/transforms/conjugate/index.js b/src/transforms/conjugate/index.js new file mode 100644 index 000000000..c2e242876 --- /dev/null +++ b/src/transforms/conjugate/index.js @@ -0,0 +1,33 @@ +const checkSuffix = require('./01-suffixes') +const genericFill = require('./02-generic') + +//we run this on every verb in the lexicon, so please keep it fast +//we assume the input word is a proper infinitive +const conjugate = function(str = '', world) { + let found = {} + // 1. look at irregulars + //the lexicon doesn't pass this in + if (world && world.irregulars) { + if (world.irregulars.verbs.hasOwnProperty(str) === true) { + found = Object.assign({}, world.irregulars.verbs[str]) + } + } + //2. rule-based regex + found = Object.assign({}, checkSuffix(str), found) + + //3. generic transformations + //'buzzing' + if (found.Gerund === undefined) { + found.Gerund = genericFill.Gerund(str) + } + //'buzzed' + if (found.PastTense === undefined) { + found.PastTense = genericFill.PastTense(str) + } + //'buzzes' + if (found.PresentTense === undefined) { + found.PresentTense = genericFill.PresentTense(str) + } + return found +} +module.exports = conjugate diff --git a/src/transforms/conjugate/suffixes.js b/src/transforms/conjugate/suffixes.js new file mode 100644 index 000000000..cb0330158 --- /dev/null +++ b/src/transforms/conjugate/suffixes.js @@ -0,0 +1,283 @@ +const endsWith = { + b: [ + { + reg: /([^aeiou][aeiou])b$/i, + repl: { + pr: '$1bs', + pa: '$1bbed', + gr: '$1bbing', + }, + }, + ], + d: [ + { + reg: /(end)$/i, + repl: { + pr: '$1s', + pa: 'ent', + gr: '$1ing', + ar: '$1er', + }, + }, + { + reg: /(eed)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + ar: '$1er', + }, + }, + { + reg: /(ed)$/i, + repl: { + pr: '$1s', + pa: '$1ded', + ar: '$1der', + gr: '$1ding', + }, + }, + { + reg: /([^aeiou][ou])d$/i, + repl: { + pr: '$1ds', + pa: '$1dded', + gr: '$1dding', + }, + }, + ], + e: [ + { + reg: /(eave)$/i, + repl: { + pr: '$1s', + pa: '$1d', + gr: 'eaving', + ar: '$1r', + }, + }, + { + reg: /(ide)$/i, + repl: { + pr: '$1s', + pa: 'ode', + gr: 'iding', + ar: 'ider', + }, + }, + { + reg: /(ake)$/i, + repl: { + pr: '$1s', + pa: 'ook', + gr: 'aking', + ar: '$1r', + }, + }, + { + reg: /(a[tg]|i[zn]|ur|nc|gl|is)e$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing', + prt: '$1en', + }, + }, + { + reg: /([bd]l)e$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing', + }, + }, + { + reg: /(om)e$/i, + repl: { + pr: '$1es', + pa: 'ame', + gr: '$1ing', + }, + }, + ], + + g: [ + { + reg: /([^aeiou][ou])g$/i, + repl: { + pr: '$1gs', + pa: '$1gged', + gr: '$1gging', + }, + }, + ], + h: [ + { + reg: /(..)([cs]h)$/i, + repl: { + pr: '$1$2es', + pa: '$1$2ed', + gr: '$1$2ing', + }, + }, + ], + k: [ + { + reg: /(ink)$/i, + repl: { + pr: '$1s', + pa: 'unk', + gr: '$1ing', + ar: '$1er', + }, + }, + ], + + m: [ + { + reg: /([^aeiou][aeiou])m$/i, + repl: { + pr: '$1ms', + pa: '$1mmed', + gr: '$1mming', + }, + }, + ], + + n: [ + { + reg: /(en)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + }, + }, + ], + p: [ + { + reg: /(e)(ep)$/i, + repl: { + pr: '$1$2s', + pa: '$1pt', + gr: '$1$2ing', + ar: '$1$2er', + }, + }, + { + reg: /([^aeiou][aeiou])p$/i, + repl: { + pr: '$1ps', + pa: '$1pped', + gr: '$1pping', + }, + }, + { + reg: /([aeiu])p$/i, + repl: { + pr: '$1ps', + pa: '$1p', + gr: '$1pping', + }, + }, + ], + + r: [ + { + reg: /([td]er)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + }, + }, + { + reg: /(er)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + }, + }, + ], + s: [ + { + reg: /(ish|tch|ess)$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing', + }, + }, + ], + + t: [ + { + reg: /(ion|end|e[nc]t)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + }, + }, + { + reg: /(.eat)$/i, + repl: { + pr: '$1s', + pa: '$1ed', + gr: '$1ing', + }, + }, + { + reg: /([aeiu])t$/i, + repl: { + pr: '$1ts', + pa: '$1t', + gr: '$1tting', + }, + }, + { + reg: /([^aeiou][aeiou])t$/i, + repl: { + pr: '$1ts', + pa: '$1tted', + gr: '$1tting', + }, + }, + ], + + w: [ + { + reg: /(..)(ow)$/i, + repl: { + pr: '$1$2s', + pa: '$1ew', + gr: '$1$2ing', + prt: '$1$2n', + }, + }, + ], + y: [ + { + reg: /([i|f|rr])y$/i, + repl: { + pr: '$1ies', + pa: '$1ied', + gr: '$1ying', + }, + }, + ], + + z: [ + { + reg: /([aeiou]zz)$/i, + repl: { + pr: '$1es', + pa: '$1ed', + gr: '$1ing', + }, + }, + ], +} + +module.exports = endsWith diff --git a/src/transforms/toInfinitive/_guess.js b/src/transforms/toInfinitive/_guess.js new file mode 100644 index 000000000..914b8158f --- /dev/null +++ b/src/transforms/toInfinitive/_guess.js @@ -0,0 +1,90 @@ +let guessVerb = { + Gerund: ['ing'], + Actor: ['erer'], + Infinitive: [ + 'ate', + 'ize', + 'tion', + 'rify', + 'then', + 'ress', + 'ify', + 'age', + 'nce', + 'ect', + 'ise', + 'ine', + 'ish', + 'ace', + 'ash', + 'ure', + 'tch', + 'end', + 'ack', + 'and', + 'ute', + 'ade', + 'ock', + 'ite', + 'ase', + 'ose', + 'use', + 'ive', + 'int', + 'nge', + 'lay', + 'est', + 'ain', + 'ant', + 'ent', + 'eed', + 'er', + 'le', + 'own', + 'unk', + 'ung', + 'en', + ], + PastTense: ['ed', 'lt', 'nt', 'pt', 'ew', 'ld'], + PresentTense: [ + 'rks', + 'cks', + 'nks', + 'ngs', + 'mps', + 'tes', + 'zes', + 'ers', + 'les', + 'acks', + 'ends', + 'ands', + 'ocks', + 'lays', + 'eads', + 'lls', + 'els', + 'ils', + 'ows', + 'nds', + 'ays', + 'ams', + 'ars', + 'ops', + 'ffs', + 'als', + 'urs', + 'lds', + 'ews', + 'ips', + 'es', + 'ts', + 'ns', + ], +} +//flip it into a lookup object +guessVerb = Object.keys(guessVerb).reduce((h, k) => { + guessVerb[k].forEach(a => (h[a] = k)) + return h +}, {}) +module.exports = guessVerb diff --git a/src/transforms/toInfinitive/_transform.js b/src/transforms/toInfinitive/_transform.js new file mode 100644 index 000000000..46df883c0 --- /dev/null +++ b/src/transforms/toInfinitive/_transform.js @@ -0,0 +1,230 @@ +//rules for turning a verb into infinitive form +let rules = { + Participle: [ + { + reg: /own$/i, + to: 'ow', + }, + { + reg: /(.)un([g|k])$/i, + to: '$1in$2', + }, + ], + + Actor: [ + { + reg: /(er)er$/i, + to: '$1', + }, + ], + + PresentTense: [ + { + reg: /(..)(ies)$/i, + to: '$1y', + }, + { + reg: /(tch|sh)es$/i, + to: '$1', + }, + { + reg: /(ss|zz)es$/i, + to: '$1', + }, + { + reg: /([tzlshicgrvdnkmu])es$/i, + to: '$1e', + }, + { + reg: /(n[dtk]|c[kt]|[eo]n|i[nl]|er|a[ytrl])s$/i, + to: '$1', + }, + { + reg: /(ow)s$/i, + to: '$1', + }, + { + reg: /(op)s$/i, + to: '$1', + }, + { + reg: /([eirs])ts$/i, + to: '$1t', + }, + { + reg: /(ll)s$/i, + to: '$1', + }, + { + reg: /(el)s$/i, + to: '$1', + }, + { + reg: /(ip)es$/i, + to: '$1e', + }, + { + reg: /ss$/i, + to: 'ss', + }, + { + reg: /s$/i, + to: '', + }, + ], + + Gerund: [ + { + reg: /pping$/i, + to: 'p', + }, + { + reg: /lling$/i, + to: 'll', + }, + { + reg: /tting$/i, + to: 't', + }, + { + reg: /dding$/i, + to: 'd', + }, + { + reg: /ssing$/i, + to: 'ss', + }, + { + reg: /(..)gging$/i, + to: '$1g', + }, + { + reg: /([^aeiou])ying$/i, + to: '$1y', + }, + { + reg: /([^ae]i.)ing$/i, + to: '$1e', + }, + { + reg: /(ea.)ing$/i, + to: '$1', + }, + { + reg: /(u[rtcb]|[bdtpkg]l|n[cg]|a[gdkvtc]|[ua]s|[dr]g|yz|o[rlsp]|cre)ing$/i, + to: '$1e', + }, + { + reg: /(ch|sh)ing$/i, + to: '$1', + }, + { + reg: /(..)ing$/i, + to: '$1', + }, + ], + + PastTense: [ + { + reg: /(ued)$/i, + to: 'ue', + }, + { + reg: /a([^aeiouy])ed$/i, + to: 'a$1e', + }, + { + reg: /([aeiou]zz)ed$/i, + to: '$1', + }, + { + reg: /(e|i)lled$/i, + to: '$1ll', + }, + { + reg: /(.)(sh|ch)ed$/i, + to: '$1$2', + }, + { + reg: /(tl|gl)ed$/i, + to: '$1e', + }, + { + reg: /(um?pt?)ed$/i, + to: '$1', + }, + { + reg: /(ss)ed$/i, + to: '$1', + }, + { + reg: /pped$/i, + to: 'p', + }, + { + reg: /tted$/i, + to: 't', + }, + { + reg: /(..)gged$/i, + to: '$1g', + }, + { + reg: /(..)lked$/i, + to: '$1lk', + }, + { + reg: /([^aeiouy][aeiou])ked$/i, + to: '$1ke', + }, + { + reg: /(.[aeiou])led$/i, + to: '$1l', + }, + { + reg: /(..)(h|ion|n[dt]|ai.|[cs]t|pp|all|ss|tt|int|ail|ld|en|oo.|er|k|pp|w|ou.|rt|ght|rm)ed$/i, + to: '$1$2', + }, + { + reg: /(.ut)ed$/i, + to: '$1e', + }, + { + reg: /(.pt)ed$/i, + to: '$1', + }, + { + reg: /(us)ed$/i, + to: '$1e', + }, + { + reg: /(..[^aeiouy])ed$/i, + to: '$1e', + }, + { + reg: /(..)ied$/i, + to: '$1y', + }, + { + reg: /(.o)ed$/i, + to: '$1o', + }, + { + reg: /(..i)ed$/i, + to: '$1', + }, + { + reg: /(.a[^aeiou])ed$/i, + to: '$1', + }, + { + reg: /([rl])ew$/i, + to: '$1ow', + }, + { + reg: /([pl])t$/i, + to: '$1t', + }, + ], +} +module.exports = rules diff --git a/src/transforms/toInfinitive/index.js b/src/transforms/toInfinitive/index.js new file mode 100644 index 000000000..a9947c21c --- /dev/null +++ b/src/transforms/toInfinitive/index.js @@ -0,0 +1,51 @@ +const rules = require('./_transform') +const guess = require('./_guess') + +/** it helps to know what we're conjugating from */ +const guessTense = function(str) { + let three = str.substr(str.length - 3) + if (guess.hasOwnProperty(three) === true) { + return guess[three] + } + let two = str.substr(str.length - 2) + if (guess.hasOwnProperty(two) === true) { + return guess[two] + } + let one = str.substr(str.length - 1) + if (one === 's') { + return 'PresentTense' + } + return null +} + +const toInfinitive = function(str, world, tense) { + if (!str) { + return '' + } + //1. look at known irregulars + if (world.words.hasOwnProperty(str) === true) { + let irregs = world.irregulars.verbs + let keys = Object.keys(irregs) + for (let i = 0; i < keys.length; i++) { + let forms = Object.keys(irregs[keys[i]]) + for (let o = 0; o < forms.length; o++) { + if (str === irregs[keys[i]][forms[o]]) { + return keys[i] + } + } + } + } + + // give'r! + tense = tense || guessTense(str) + if (tense && rules[tense]) { + for (let i = 0; i < rules[tense].length; i++) { + const rule = rules[tense][i] + if (rule.reg.test(str) === true) { + return str.replace(rule.reg, rule.to) + } + } + } + return str +} +module.exports = toInfinitive diff --git a/src/transforms/toPlural/_rules.js b/src/transforms/toPlural/_rules.js new file mode 100644 index 000000000..6df27bd08 --- /dev/null +++ b/src/transforms/toPlural/_rules.js @@ -0,0 +1,42 @@ +/** patterns for turning 'bus' to 'buses'*/ +const suffixes = { + a: [[/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae'], [/([ti])a$/i, '$1a']], + + e: [ + [/(kn|l|w)ife$/i, '$1ives'], + [/(hive)$/i, '$1s'], + [/([m|l])ouse$/i, '$1ice'], + [/([m|l])ice$/i, '$1ice'], + ], + + f: [ + [/^(dwar|handkerchie|hoo|scar|whar)f$/i, '$1ves'], + [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)f$/i, '$1ves'], + ], + + i: [[/(octop|vir)i$/i, '$1i']], + + m: [[/([ti])um$/i, '$1a']], + + n: [[/^(oxen)$/i, '$1']], + + o: [[/(al|ad|at|er|et|ed|ad)o$/i, '$1oes']], + + s: [ + [/(ax|test)is$/i, '$1es'], + [/(alias|status)$/i, '$1es'], + [/sis$/i, 'ses'], + [/(bu)s$/i, '$1ses'], + [/(sis)$/i, 'ses'], + [/^(?!talis|.*hu)(.*)man$/i, '$1men'], + [/(octop|vir|radi|nucle|fung|cact|stimul)us$/i, '$1i'], + ], + + x: [[/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices'], [/^(ox)$/i, '$1en']], + + y: [[/([^aeiouy]|qu)y$/i, '$1ies']], + + z: [[/(quiz)$/i, '$1zes']], +} + +module.exports = suffixes diff --git a/src/transforms/toPlural/index.js b/src/transforms/toPlural/index.js new file mode 100644 index 000000000..b1f18d2b3 --- /dev/null +++ b/src/transforms/toPlural/index.js @@ -0,0 +1,40 @@ +const rules = require('./_rules') +const addE = /(x|ch|sh|s|z)$/ + +const trySuffix = function(str) { + let c = str[str.length - 1] + if (rules.hasOwnProperty(c) === true) { + for (let i = 0; i < rules[c].length; i += 1) { + let reg = rules[c][i][0] + if (reg.test(str) === true) { + return str.replace(reg, rules[c][i][1]) + } + } + } + return null +} + +/** Turn a singular noun into a plural + * assume the given string is singular + */ +const pluralize = function(str = '', world) { + let irregulars = world.irregulars.nouns + + // check irregulars list + if (irregulars.hasOwnProperty(str)) { + return irregulars[str] + } + + //we have some rules to try-out + let plural = trySuffix(str) + if (plural !== null) { + return plural + } + //like 'church' + if (addE.test(str)) { + return str + 'es' + } + // ¯\_(ツ)_/¯ + return str + 's' +} +module.exports = pluralize diff --git a/src/transforms/toSingular/_rules.js b/src/transforms/toSingular/_rules.js new file mode 100644 index 000000000..4f1fea485 --- /dev/null +++ b/src/transforms/toSingular/_rules.js @@ -0,0 +1,28 @@ +//patterns for turning 'dwarves' to 'dwarf' +module.exports = [ + [/([^v])ies$/i, '$1y'], + [/ises$/i, 'isis'], + [/(kn|[^o]l|w)ives$/i, '$1ife'], + [/^((?:ca|e|ha|(?:our|them|your)?se|she|wo)l|lea|loa|shea|thie)ves$/i, '$1f'], + [/^(dwar|handkerchie|hoo|scar|whar)ves$/i, '$1f'], + [/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a'], + [/(octop|vir|radi|nucle|fung|cact|stimul)(i)$/i, '$1us'], + [/(buffal|tomat|tornad)(oes)$/i, '$1o'], + // [/(analy|diagno|parenthe|progno|synop|the)ses$/i, '$1sis'], + [/(..[aeiou]s)es$/i, '$1'], + [/(vert|ind|cort)(ices)$/i, '$1ex'], + [/(matr|append)(ices)$/i, '$1ix'], + [/(x|ch|ss|sh|z|o)es$/i, '$1'], + [/men$/i, 'man'], + [/(n)ews$/i, '$1ews'], + [/([ti])a$/i, '$1um'], + [/([^aeiouy]|qu)ies$/i, '$1y'], + [/(s)eries$/i, '$1eries'], + [/(m)ovies$/i, '$1ovie'], + [/([m|l])ice$/i, '$1ouse'], + [/(cris|ax|test)es$/i, '$1is'], + [/(alias|status)es$/i, '$1'], + [/(ss)$/i, '$1'], + [/(ics)$/i, '$1'], + [/s$/i, ''], +] diff --git a/src/transforms/toSingular/index.js b/src/transforms/toSingular/index.js new file mode 100644 index 000000000..f56ec4692 --- /dev/null +++ b/src/transforms/toSingular/index.js @@ -0,0 +1,28 @@ +const rules = require('./_rules') + +const invertObj = function(obj) { + return Object.keys(obj).reduce((h, k) => { + h[obj[k]] = k + return h + }, {}) +} + +const toSingular = function(str, world) { + let irregulars = world.irregulars.nouns + let invert = invertObj(irregulars) + + // check irregulars list + if (invert.hasOwnProperty(str)) { + return invert[str] + } + + // go through our regexes + for (let i = 0; i < rules.length; i++) { + if (rules[i][0].test(str) === true) { + str = str.replace(rules[i][0], rules[i][1]) + return str + } + } + return str +} +module.exports = toSingular diff --git a/src/world/World.js b/src/world/World.js new file mode 100644 index 000000000..54fd762bd --- /dev/null +++ b/src/world/World.js @@ -0,0 +1,175 @@ +const lexData = require('./_data') +const defaultTags = require('./tags') +const unpack = require('efrt-unpack') +const addLex = require('./addWords') +const addIrregulars = require('./addIrregulars') +const inferTagSet = require('./tags/inference') + +let misc = require('./data/misc') + +//these let users change inflection / verb conjugation +const irregulars = { + nouns: require('./data/plurals'), + verbs: require('./data/conjugations'), +} + +//these behaviours are configurable & shared across some plugins +const transforms = { + conjugate: require('../transforms/conjugate'), + adjectives: require('../transforms/adjectives'), + toPlural: require('../transforms/toPlural'), + toSingular: require('../transforms/toSingular'), + toInfinitive: require('../transforms/toInfinitive'), +} + +let isVerbose = false + +/** all configurable linguistic data */ +class World { + constructor() { + // quiet these properties from a console.log + Object.defineProperty(this, 'words', { + enumerable: false, + value: misc, + writable: true, + }) + Object.defineProperty(this, 'hasCompound', { + enumerable: false, + value: {}, + writable: true, + }) + Object.defineProperty(this, 'irregulars', { + enumerable: false, + value: irregulars, + writable: true, + }) + Object.defineProperty(this, 'tags', { + enumerable: false, + value: Object.assign({}, defaultTags), + writable: true, + }) + Object.defineProperty(this, 'transforms', { + enumerable: false, + value: transforms, + writable: true, + }) + + Object.defineProperty(this, 'taggers', { + enumerable: false, + value: [], + writable: true, + }) + // add our compressed data to lexicon + this.unpackWords(lexData) + // add our irregulars to lexicon + this.addIrregulars() + + // cache our abbreviations for our sentence-parser + Object.defineProperty(this, 'cache', { + enumerable: false, + value: { + abbreviations: this.getByTag('Abbreviation'), + }, + }) + } + + /** more logs for debugging */ + verbose(bool) { + isVerbose = bool + return this + } + isVerbose() { + return isVerbose + } + + /** get all terms in our lexicon with this tag */ + getByTag(tag) { + let lex = this.words + let res = {} + let words = Object.keys(lex) + for (let i = 0; i < words.length; i++) { + if (typeof lex[words[i]] === 'string') { + if (lex[words[i]] === tag) { + res[words[i]] = true + } + } else if (lex[words[i]].some(t => t === tag)) { + res[words[i]] = true + } + } + return res + } + + /** augment our lingustic data with new data */ + unpackWords(lex) { + let tags = Object.keys(lex) + for (let i = 0; i < tags.length; i++) { + let words = Object.keys(unpack(lex[tags[i]])) + for (let w = 0; w < words.length; w++) { + addLex.addWord(words[w], tags[i], this.words) + // do some fancier stuff + addLex.addMore(words[w], tags[i], this) + } + } + } + /** put new words into our lexicon, properly */ + addWords(obj) { + let keys = Object.keys(obj) + for (let i = 0; i < keys.length; i++) { + let word = keys[i].toLowerCase() + addLex.addWord(word, obj[keys[i]], this.words) + // do some fancier stuff + addLex.addMore(word, obj[keys[i]], this) + } + } + + addIrregulars() { + addIrregulars(this) + return this + } + + /** extend the compromise tagset */ + addTags(tags) { + tags = Object.assign({}, tags) + this.tags = Object.assign(this.tags, tags) + // calculate graph implications for the new tags + this.tags = inferTagSet(this.tags) + return this + } + /** call methods after tagger runs */ + postProcess(fn) { + this.taggers.push(fn) + return this + } + + /** helper method for logging + debugging */ + stats() { + return { + words: Object.keys(this.words).length, + plurals: Object.keys(this.irregular.plurals).length, + conjugations: Object.keys(this.irregular.conjugations).length, + compounds: Object.keys(this.hasCompound).length, + postProcessors: this.taggers.length, + } + } +} + +// ¯\_(:/)_/¯ +const clone = function(obj) { + return JSON.parse(JSON.stringify(obj)) +} + +/** produce a deep-copy of all lingustic data */ +World.prototype.clone = function() { + let w2 = new World() + // these are simple to copy: + w2.words = Object.assign({}, this.words) + w2.hasCompound = Object.assign({}, this.hasCompound) + //these ones are nested: + w2.irregulars = clone(this.irregulars) + w2.tags = clone(this.tags) + // these are functions + w2.transforms = this.transforms + w2.taggers = this.taggers + return w2 +} +module.exports = World diff --git a/src/world/_data.js b/src/world/_data.js index 97e5698ff..96760b356 100644 --- a/src/world/_data.js +++ b/src/world/_data.js @@ -1 +1,51 @@ -module.exports=`{"words":"Comparative¦better|Superlative¦earlier|PresentTense¦sounds|Value¦a few|Noun¦autumn,daylight9eom,here,no doubt,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Copula¦a1is,w0;as,ere;m,re|Condition¦if,unless|PastTense¦be2came,d1had,mea0sa1taken,we0;nt;id;en,gan|Gerund¦accord0be0develop0go0result0stain0;ing|Negative¦n0;ever,o0;!n,t|QuestionWord¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s|Singular¦a06bZcUdQeOfLgKhGici0Ajel07kitty,lFmDnCoBp8question mark,r7s4t1us 0;dollVstW; rex,a1h0ic,ragedy,v show;ere,i07;l03x return;ky,t0uper bowl,yst06;ri04u0;dIff;alZi02oom;a1robl02u0;dCrpo8;rt,tE;cean,thers;othiXumbG;ayfTeeNo0;del,nopoS;iRunch;ead start,o0;lPme1u0;se;! run;adfMirlIlaci8od,rand slam,ulM;amiLly,olLr1un0;diN;iGosD;conomy,gg,ner3v0xampG;ent;eath,inn2o0ragonfG;cument6g0iFlFor;gy;er;an3eiliFhocol2i0ottage,redit card;ty,vil w0;ar;ate;ary;ankiAel7les9o2reakfast,u0;n0tterf6;ti8;dy,tt2y0;fri0;end;le;d1l0noma0;ly; homin2verti0;si0;ng;em|Infinitive¦0:6Y;1:7C;2:7A;3:79;4:5F;5:74;6:6D;7:6L;8:78;9:6W;A:73;B:76;C:6R;D:68;E:7D;F:60;a6Qb69c5Bd4Je43f3Qg3Jh3Ci2Zj2Xk2Tl2Km2Bn28o24p1Pques3Rr0Xs05tWuRvOwHyG;awn,ield;aJe24hist7iIoGre6H;nd0rG;k,ry;n,pe,sh,th0;lk,nHrGsh,tCve;n,raE;d0t;aHiGo8;ew,sA;l6Rry;nHpGr3se;gra4Wli49;dGi8lo65;erGo;go,mi5H;aNeMhKie,oJrHuGwi5;ne,rn;aGe0Ui60u5y;de,in,nsf0p,v5O;r37uC;ank,rG;eat2Vi2;nd,st;ke,lk,rg5Os8;a06c03eZhWi4Jkip,lVmUneTo56pQtJuGwitC;bmAck,ff0gge5ppHrGspe6;ge,pri1rou53vi2;ly,o3D;aLeKoJrHuG;dy,mb7;aDeGi2;ngth2Lss,tC;p,re;m,p;in,ke,r0Yy;iHlaFoil,rinG;g,k7;n,t;ak,e3E;aFe22i7o5B;am,e1Qip;aHiv0oG;ck,ut;re,ve;arCeIle6nHr2tG;!t7;d,se;k,m;aHo4rG;atCew;le,re;il,ve;a05eIisk,oHuG;b,in,le,n,sh;am,ll;a01cZdu9fYgXje6lUmTnt,pQquPsKtJvGwa5V;eGiew,o4U;al,l,rG;se,t;aDi4u42;eJi5oItG;!o4rG;i6uc20;l2rt;mb7nt,r2;e5i4;air,eHlGo40reseE;a9y;at;aDemb0i3Wo2;aHeGi2y;a1nt;te,x;a5Dr4A;act1Yer,le6u1;a12ei2k5PoGyc7;gni2Cnci7rd;ch,li2Bs5N;i1nG;ge,k;aTerSiRlPoNrIuG;b21ll,mp,rGsh,t;cha1s4Q;ai1eJiEoG;cHdu9greBhibAmi1te5vG;e,i2U;eBlaim;di6pa4ss,veE;iEp,rtr43sGur;e,t;a3RuG;g,n3;ck,le;fo32mAsi5;ck,iErt4Mss,u1y;bIccur,ff0pera8utweHverGwe;co47lap,ta3Qu1whelm;igh;ser2taD;eHotG;e,i9;ed,gle6;aLeKiIoHuG;ltip3Frd0;nit14ve;nGrr13;d,g7us;asu4lt,n0Qr3ssa3;intaDke d40na3rHtG;ch,t0;ch,k39ry;aMeLiIoGu1F;aGck,ok,ve;d,n;ft,ke,mAnHstGve;!en;e,k;a2Gc0Ht;b0Qck,uG;gh,nC;eIiHnoG;ck,w;ck,ll,ss;ep;am,oDuG;d3mp;gno4mQnGss3I;cOdica8flu0NhNsKtIvG;eGol2;nt,st;erGrodu9;a6fe4;i5tG;aGru6;ll;abAibA;lu1Fr1D;agi22pG;lemeEo20ro2;aKeIi4oHuG;nt,rry;ld fa5n03pe,st;aGlp;d,t;nd7ppGrm,te;en;aLet,loBoKrIuG;arGeBi14;ant39d;aGip,ow,umb7;b,sp;es,ve1I;in,th0ze;aQeaPiNlLoIracHuncG;ti3I;tu4;cus,lHrG;ce,eca5m,s30;d,l22;aFoG;at,od,w;gu4lGniFx;e,l;r,tu4;il,ll,vG;or;a13cho,dAle6mSnPstNvalua8xG;a0AcLerKi5pGte16;a15eHlaDoGreB;rt,se;ct,riG;en9;ci1t;el,han3;abGima8;liF;ab7couXdHfor9ga3han9j03riCsu4t0vG;isi2Vy;!u4;body,er3pG;hasiGow0;ze;a06eUiMoLrHuG;mp;aIeHiGop;ft;am,ss;g,in;!d3ubt;e,ff0p,re6sHvG;e,iXor9;aJcGli13miBpl18tinguiF;oGuB;uGv0;ra3;gr1YppG;ear,ro2;al,cNem,fLliv0ma0Cny,pKsHterG;mi0D;cribe,er2iHtrG;oy;gn,re;a08e07i6osA;eGi08y;at,ct;iIlHrG;ea1;a4i04;de;ma3n9re,te;a0Ae09h06i8l03oJrGut;aHeGoBuFy;a8dA;ck,ve;llYmSnHok,py,uGv0;gh,nt;cePdu6fMsKtIvG;eGin9;rt,y;aDin0XrG;a5ibu8ol;iGtitu8;d0st;iHoGroE;rm;gu4rm;rn;biKe,foJmaIpG;a4laD;re;nd;rt;ne;ap1e6;aHiGo1;ng,p;im,w;aHeG;at,ck,w;llen3n3r3se;a1nt0;ll,ncHrGt0u1;e,ry;el;aUeQloPoNrKuG;dgIlHrG;n,y;ly;et;aHuF;sh;ke;a5mb,o5rrGth0un9;ow;ck;ar,coSgDlHnefAtrG;ay;ie2ong;in;nGse;!g;band0Jc0Bd06ffo05gr04id,l01mu1nYppTrQsKttGvoid,waA;acIeHra6;ct;m0Fnd;h,k;k,sG;eIiHocia8uG;me;gn,st;mb7rt;le;chHgGri2;ue;!i2;eaJlIroG;aCve;ch;aud,y;l,r;noun9sw0tG;icipa8;ce;lHt0;er;e3ow;ee;rd;aRdIju5mAoR;it;st;!reB;ss;cJhie2knowled3tiva8;te;ge;ve;eIouEu1;se;nt;pt;on|Actor¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt|Honorific¦aObrigadiNcHdGexcellency,fiBking,liDmaAofficNp6queen,r3s0taoiseach,vice5;e0ultJ;c0rgeaC;ond liAretary;abbi,e0;ar0verend; adJ;astFr0;eside6i0ofessE;me ministEnce0;!ss;gistrate,r4yB;eld mar3rst l0;ady,i0;eutena0;nt;shA;oct5utchess;aptain,hance3o0;lonel,mmand4ngress0unci2;m0wom0;an;ll0;or;er;d0yatullah;mir0;al|SportsTeam¦0:1M;1:1T;2:1U;a1Rb1Dc0Zd0Qfc dallas,g0Nhouston 0Mindiana0Ljacksonville jagua0k0Il0Fm02newVoRpKqueens parkJrIsAt5utah jazz,vancouver whitecaps,w3yY;ashington 3est ham0Xh16;natio21redski1wizar12;ampa bay 6e5o3;ronto 3ttenham hotspur;blu1Hrapto0;nnessee tita1xasD;buccanee0ra1G;a7eattle 5heffield0Qporting kansas13t3;. louis 3oke12;c1Srams;mari02s3;eah1IounI;cramento Sn 3;antonio spu0diego 3francisco gi0Bjose earthquak2;char0EpaB;eal salt lake,o04; ran0C;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat2steele0;il3oenix su1;adelphia 3li2;eagl2philNunE;dr2;akland 4klahoma city thunder,r3;i10lando magic;athle0Trai3;de0; 3castle05;england 6orleans 5york 3;city fc,giUje0Lkn02me0Lred bul19y3;anke2;pelica1sain0J;patrio0Irevolut3;ion;aBe9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Rvi3;kings;imberwolv2wi1;re0Cuc0W;dolphi1heat,marli1;mphis grizz3ts;li2;nchester 5r3vN;i3li1;ne0;c00u0H;a4eicesterYos angeles 3;clippe0dodFlaA; galaxy,ke0;ansas city 3nH;chiefs,ro3;ya0M; pace0polis colX;astr0Edynamo,rockeWtexa1;i4olden state warrio0reen bay pac3;ke0;anT;.c.Aallas 7e3i0Cod5;nver 5troit 3;lio1pisto1ti3;ge0;bronc06nuggeO;cowboUmav3;er3;ic06; uX;arCelNh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki2;brow1cavalie0india1;benga03re3;ds;arlotte horCicago 3;b4cubs,fire,wh3;iteE;ea0ulY;di3olina panthe0;ff3naW; c3;ity;altimore ElAoston 7r3uffalo bilT;av2e5ooklyn 3;ne3;ts;we0;cel4red3; sox;tics;ackburn rove0u3;e ja3;ys;rs;ori3rave1;ol2;rizona Ast8tlanta 3;brav2falco1h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls|Uncountable¦0:1C;a1Hb1Bc12e0Wf0Qg0Mh0Gi0Dj0Cknowled1Gl07mYnXoWpRrOsCt8vi7w1;a5ea0Ai4o1;o2rld1;! seI;d,l;ldlife,ne;rmth,t0;neg0Xol08;e3hund0ime,oothpaste,r1una;affRou1;ble,sers,t;a,nnis;aAcene07e9h8il7now,o6p3te2u1;g0Rnshi0L;am,el;ace2e1;ciOed;!c12;ap,cc0ft0B;k,v0;eep,opp0O;riJ;d07fe0Wl1nd;m0Qt;ain,e1i0W;c1laxa0Csearch;ogni0Brea0B;a4e2hys0Elast9o1ress00;rk,w0;a1pp0trol;ce,nR;p0tiK;il,xygen;ews,oi0C;a7ea5i4o3u1;mps,s1;ic;nHo08;lk,st;sl1t;es;chine1il,themat00; learn02ry;aught0e3i2u1;ck,g07;ghtnZqu0CteratI;a1isH;th0;ewel7usti08;ce,mp1nformaOtself;ati1ortan06;en05;a4isto3o1;ck1mework,n1spitali01;ey;ry;ir,lib1ppi9;ut;o2r1um,ymnastJ;a7ound;l1ssip;d,f;i5lour,o2ruit,urnit1;ure;od,rgive1wl;ne1;ss;c6sh;conom9duca5lectriciMn3quip4th9very1;body,o1thB;ne;joy1tertain1;ment;tiC;a8elcius,h4iv3loth6o1urrency;al,ffee,ld w1nfusiAttA;ar;ics;aos,e1;e2w1;ing;se;ke,sh;a3eef,is2lood,read,utt0;er;on;g1ss;ga1;ge;c4dvi3irc2mnes1rt;ty;raft;ce;id|Unit¦0:17;a12b10c0Md0Le0Jf0Fg0Bh08in07joule0k01lZmOnNoMpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Lb,d0Rears old,o1;tt0F;att0b;able4b3e2on1sp;!ne0;a2r0B;!l,sp;spo03; ft,uare 1;c0Gd0Ff3i0Dkilo0Hm1ya0C;e0Kil1;e0li0F;eet0o0B;t,uart0;a3e2i1ou0Nt;c0Knt0;rcent,t00;!scals;hms,uVz;an0GewtR;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;²,³;e1g,z;ct1rtz0;aWogP;al2b,ig9ra1;in0m0;!l1;on0;a3emtOl1tG; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,l,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s|Pronoun¦'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s|Organization¦0:44;a39b2Qc2Ad22e1Yf1Ug1Mh1Hi1Ej1Ak18l14m0Tn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0You1w0Y;gov,tu2R;a3e1orld trade organizati3Z;lls fargo,st1;fie23inghou17;l1rner br3B;-m12gree30l street journ25m12;an halNeriz3Uisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Qps;es33i1;lev2Wted natio2T; mobi2Jaco bePd bMeAgi frida9h3im horto2Smz,o1witt2V;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen31daily ma2Vguess w2holli0rolling st1Ns1w2;mashing pumpki2Nuprem0;ho;ea1lack eyed pe3Dyrds;ch bo1tl0;ys;l2s1;co,la m13;efoni08us;a6e4ieme2Fnp,o2pice gir5ta1ubaru;rbucks,to2L;ny,undgard1;en;a2Px pisto1;ls;few24insbu25msu1W;.e.m.,adiohead,b6e3oyal 1yan2V;b1dutch she4;ank;/max,aders dige1Ed 1vl30;bu1c1Thot chili peppe2Ilobst27;ll;c,s;ant2Tizno2D;an5bs,e3fiz23hilip morrBi2r1;emier25octer & gamb1Qudenti14;nk floyd,zza hut;psi26tro1uge09;br2Ochina,n2O; 2ason1Wda2E;ld navy,pec,range juli2xf1;am;us;aAb9e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0L;l,s;c,stl3tflix,w1; 1sweek;kids on the block,york09;e,é;a,c;nd1Rs2t1;ional aca2Co,we0P;a,cYd0N;aAcdonald9e5i3lb,o1tv,yspace;b1Knsanto,ody blu0t1;ley crue,or0N;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt11z1V;'ore08a3e1g,ittle caesa1H;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1H;art;iffy lu0Jo3pmorgan1sa;! cha1;se;hnson & johns1Py d1O;bm,hop,n1tv;g,te1;l,rpol; & m,asbro,ewlett-packaSi3o1sbc,yundai;me dep1n1G;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Gu1;cci,ns n ros0;ldman sachs,o1;dye1g09;ar;axo smith kliYencore;electr0Gm1;oto0S;a3bi,da,edex,i1leetwood mac,oFrito-l08;at,nancial1restoU; tim0;cebook,nnie mae;b04sa,u3xxon1; m1m1;ob0E;!rosceptics;aiml08e5isney,o3u1;nkin donuts,po0Tran dur1;an;j,w j1;on0;a,f leppa2ll,peche mode,r spiegXstiny's chi1;ld;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra03;al;ca c5l4m1o08st03;ca2p1;aq;st;dplLgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Fy;dbury,pital o1rl's jr;ne;aFbc,eBf9l5mw,ni,o1p,rexiteeV;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roW;ckbuster video,omingda1;le; g1g1;oodriM;cht3e ge0n & jer2rkshire hathaw1;ay;ryG;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bWcRdidQerosmith,ig,lKmEnheuser-busDol,pple9r6s3t&t,v2y1;er;is,on;hland1sociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c|Demonym¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an|Region¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma|Possessive¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne|Currency¦$,aud,bRcPdKeurJfIgbp,hkd,inr,jpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotyRł;en,uanQ;af,of;h0t5;e0il5;k0q0;elL;iel,oubleKp,upeeK;e2ound st0;er0;lingH;n0soG;ceFn0;ies,y;e0i7;i,mpi6;n,r0wanzaByatB;!onaAw;ori7ranc9t;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s|Country¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an|City¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg|FemaleName¦0:G0;1:G4;2:FT;3:FF;4:FE;5:ER;6:FU;7:ET;8:GH;9:F1;A:GD;B:E7;C:EI;D:FQ;E:GA;F:FN;G:C8;aE4bD6cB9dAJe9Hf92g8Ih85i7Uj6Wk61l4Pm3An2Vo2Sp2Hqu2Fr1Ps0Rt05ursu7vVwPyMzH;aKeIoH;e,la,ra;lHna;da,ma;da,ra;as7GeIol1UvH;et5onBA;le0sen3;an9endBPhiB5iH;lJnH;if3BniHo0;e,f3A;a,helmi0lHma;a,ow;aNeKiH;cIviH;an9YenG4;kD1tor3;da,l8Wnus,rH;a,nHoniD4;a,iDE;leHnesEF;nDOrH;i1y;aTeQhOiNoKrHu7y4;acG6iHu0F;c3na,sH;h9Nta;nIrH;a,i;i9Kya;a5KffaCIna,s6;al3eHomasi0;a,l8Ho6Zres1;g7Vo6YrIssH;!a,ie;eCi,ri8;bOliNmLnJrIs6tHwa0;ia0um;a,yn;iHya;a,ka,s6;a4e4iHmCCra;!ka;a,t6;at6it6;a06carlet2Ze05hViTkye,oRtNuIyH;bFMlvi1;e,sIzH;an2Uet5ie,y;anHi8;!a,e,nH;aFe;aJeH;fHl3EphH;an2;cFBr73;f3nHphi1;d4ia,ja,ya;er4lv3mon1nHobh76;dy;aLeHirlBNo0y7;ba,e0i7lJrH;iHrBRyl;!d71;ia,lBX;ki4nJrIu0w0yH;la,na;i,leAon,ron;a,da,ia,nHon;a,on;l60re0;bNdMi9lLmJndIrHs6vannaF;aFi0;ra,y;aHi4;nt6ra;lBPome;e,ie;in1ri0;a03eYhWiUoIuH;by,thBM;bRcQlPnOsIwe0xH;an95ie,y;aIeHie,lE;ann8ll1marBHtB;!lHnn1;iHyn;e,nH;a,d7X;da,i,na;an9;hel55io;bin,erByn;a,cHkki,na,ta;helC2ki;ea,iannE0oH;da,n13;an0bJgi0i0nHta,y0;aHee;!e,ta;a,eH;cATkaF;chHe,i0mo0n5FquCGvDy0;aCFelHi9;!e,le;een2iH;a0nn;aNeMhKoJrH;iHudenAX;scil1Uyamva9;lly,rt3;ilome0oebe,ylH;is,lis;arl,ggy,nelope,r7t4;ige,m0Fn4Po7rvaBDtIulH;a,et5in1;ricHsy,tA9;a,e,ia;ctav3deIf86lHph86;a,ga,iv3;l3t5;aReQiKoHy7;eIrH;aFeDma;ll1mi;aLcJkHla,na,s6ta;iHki;!ta;hoB4k8ColH;a,eBJ;!mh;l7Una,risC;dJi5PnIo23taH;li1s6;cy,et5;eAiCQ;a01ckenz2eViLoIrignayani,uriBIyrH;a,na,tAV;i4ll9ZnH;a,iH;ca,ka,qB7;a,chPkaOlKmi,nJrHtzi;aHiam;!n9;a,dy,erva,h,n2;a,dJi9LlH;iHy;cent,e;red;!e7;ae7el3I;ag4LgLi,lIrH;edi62isCyl;an2iHliC;nHsAP;a,da;!an,han;b09c9Gd07e,g05i04l02n00rLtKuIv6TxGyHz2;a,bell,ra;de,rH;a,eD;h77il9t2;a,cTgPiKjor2l6Jn2s6tJyH;!aHbe5RjaAlou;m,n9V;a,ha,i0;!aJbAOeIja,lEna,sHt54;!a,ol,sa;!l07;!h,m,nH;!a,e,n1;arJeIie,oHr3Lueri5;!t;!ry;et3JiB;elHi62y;a,l1;dHon,ue7;akranBy;iHlo97;a,ka,n9;a,re,s2;daHg2;!l2Y;alEd2elHge,isBJon0;eiAin1yn;el,le;a0Je09iXoRuLyH;d3la,nH;!a,dIe9VnHsAT;!a,e9U;a,sAR;aB4cKelJiClIna,pHz;e,iB;a,u;a,la;iHy;a2Ce,l27n9;is,l1IrItt2uH;el7is1;aJeIi8na,rH;aGi8;lei,n1tB;!in1;aRbQd3lMnJsIv3zH;!a,be4Let5z2;a,et5;a,dH;a,sHy;ay,ey,i,y;a,iaJlH;iHy;a8Je;!n4G;b7Verty;!n5T;aOda,e0iMla,nLoJslAUtHx2;iHt2;c3t3;la,nHra;a,ie,o4;a,or1;a,gh,laH;!ni;!h,nH;a,d4e,n4O;cOdon7Ui7kes6na,rNtLurJvIxHy7;mi;ern1in3;a,eHie,yn;l,n;as6is6oH;nya,ya;a,isC;ey,ie,y;a01eWhadija,iOoNrJyH;lHra;a,ee,ie;isHy5D;!tH;a,en,iHy;!e,n48;ri,urtn9C;aNerMl9BmJrHzzy;a,stH;en,in;!berlH;eHi,y;e,y;a,stD;!na,ra;el6QiKlJnIrH;a,i,ri;d4na;ey,i,l9Ss2y;ra,s6;c8Yi5YlPma7nyakumari,rNss5MtKviByH;!e,lH;a,eH;e,i7A;a5FeIhHi3PlEri0y;arGerGie,leDr9Hy;!lyn75;a,en,iHl4Vyn;!ma,n31sC;ei74i,l2;a05eWilUoNuH;anLdKliHstG;aIeHsC;!nAt0W;!n8Z;e,i2Ry;a,iB;!anMcelEd5Wel73han6JlKni,sIva0yH;a,ce;eHie;fi0lEphG;eHie;en,n1;!a,e,n36;!i10lH;!i0Z;anMle0nJrIsH;i5Rsi5R;i,ri;!a,el6Rif1RnH;a,et5iHy;!e,f1P;a,e74iInH;a,e73iH;e,n1;cMd1mi,nIqueliAsmin2Uvie4yAzH;min8;a8eIiH;ce,e,n1s;!lHsCt06;e,le;inIk2lEquelH;in1yn;da,ta;da,lQmOnNo0rMsIvaH;!na;aIiHob6W;do4;!belHdo4;!a,e,l2G;en1i0ma;a,di4es,gr5T;el9ogH;en1;a,eAia0o0se;aNeKilIoHyacin1N;ll2rten1H;a5HdHla5H;a,egard;ath0XiIlHnrietBrmiAst0X;en25ga;di;il78lLnKrHtt2yl78z6G;iHmo4Hri4I;etH;!te;aFnaF;ey,l2;aZeUiPlNold13rJwH;enHyne19;!dolE;acIetHisel9;a,chD;e,ieH;!la;adys,enHor3yn1Z;a,da,na;aKgi,lIna,ov74selH;a,e,le;da,liH;an;!n0;mZnJorgIrH;aldGi,m2Utru76;et5i5W;a,eHna;s1Ovieve;briel3Hil,le,rnet,yle;aSePio0loNrH;anIe9iH;da,e9;!cH;esIiHoi0H;n1s3X;!ca;!rH;a,en45;lIrnH;!an9;ec3ic3;rItiHy8;ma;ah,rah;d0GileDkBl01mVn4DrSsNtMuLvH;aJelIiH;e,ta;in0Byn;!ngelG;geni1la,ni3T;h55ta;meral9peranKtH;eIhHrel7;er;l2Rr;za;iHma,nestGyn;cHka,n;a,ka;eKilJmH;aHie,y;!liA;ee,i1y;lHrald;da,y;aUeSiNlMma,no4oKsJvH;a,iH;na,ra;a,ie;iHuiH;se;a,en,ie,y;a0c3da,nKsHzaI;aHe;!beH;th;!a,or;anor,nH;!a;in1na;en,iHna,wi0;e,th;aXeLiKoHul2W;lor54miniq41n32rHtt2;a,eDis,la,othHthy;ea,y;an0AnaFonAx2;anQbPde,eOiMja,lJmetr3nHsir4X;a,iH;ce,se;a,iIla,orHphiA;es,is;a,l5M;dHrdH;re;!d4Pna;!b2EoraFra;a,d4nH;!a,e;hl3i0mNnLphn1rIvi1YyH;le,na;a,by,cIia,lH;a,en1;ey,ie;a,et5iH;!ca,el1Cka;arHia;is;a0Se0Oh06i04lWoKrIynH;di,th3;istHy06;al,i0;lQnNrIurH;tn1F;aKdJiHnJriA;!nH;a,e,n1;el3;!l1T;n2sH;tanHuelo;ce,za;eHleD;en,t5;aJeoIotH;il4D;!pat4;ir8rJudH;et5iH;a,ne;a,e,iH;ce,sY;a4er4ndH;i,y;aQeNloe,rH;isIyH;stal;sy,tH;aIen,iHy;!an1e,n1;!l;lseIrH;!i8yl;a,y;nMrH;isKlImH;aiA;a,eHot5;n1t5;!sa;d4el1RtH;al,el1Q;cIlH;es5i3H;el3ilH;e,ia,y;iZlYmilXndWrOsMtHy7;aKeJhHri0;erGleDrEy;in1;ri0;li0ri0;a2IsH;a2Hie;a,iNlLmeJolIrH;ie,ol;!e,in1yn;lHn;!a,la;a,eHie,y;ne,y;na,sC;a0Ei0E;a,e,l1;isBl2;tlH;in,yn;arb0DeZianYlWoUrH;andSeQiJoIyH;an0nn;nwEok8;an2PdgLg0KtH;n29tH;!aInH;ey,i,y;ny;etH;!t8;an0e,nH;da,na;i8y;bbi8nH;iBn2;ancHossom,ythe;a,he;ca;aScky,lin9niBrOssNtJulaFvH;!erlH;ey,y;hIsy,tH;e,i11y8;!anH;ie,y;!ie;nHt6yl;adIiH;ce;et5iA;!triH;ce,z;a4ie,ra;aliy2Bb26d1Ng1Ji1Bl0Um0Pn03rYsPthe0uLvJyH;anHes6;a,na;a,eHr27;ry;drJgusIrH;el3o4;ti0;a,ey,i,y;hItrH;id;aLlHt1Q;eIi8yH;!n;e,iHy;gh;!nH;ti;iJleIpiB;ta;en,n1t5;an1AelH;le;aZdXeVgRiPja,nItoHya;inet5n3;!aKeIiHmJ;e,ka;!mHt5;ar2;!belIliCmU;sa;!le;ka,sHta;a,sa;elHie;a,iH;a,ca,n1qH;ue;!t5;te;je7rea;la;!bImHstas3;ar3;el;aJberIel3iHy;e,na;!ly;l3n9;da;aUba,eOiLlJma,ta,yH;a,c3sH;a,on,sa;iHys0K;e,s0J;a,cIna,sHza;a,ha,on,sa;e,ia;c3is6jaJna,ssaJxH;aHia;!nd4;nd4;ra;ia;i0nIyH;ah,na;a,is,naF;c6da,leDmMnslLsH;haFlH;inHyX;g,n;!h;ey;ee;en;at6g2nH;es;ie;ha;aWdiTelMrH;eJiH;anMenH;a,e,ne;an0;na;aLeKiIyH;nn;a,n1;a,e;!ne;!iH;de;e,lEsH;on;yn;!lH;iAyn;ne;agaKbIiH;!gaJ;ey,i8y;!e;il;ah|Place¦aMbKcIdHeFfEgBhAi9jfk,kul,l7m5new eng4ord,p2s1the 0upJyyz;bronx,hamptons;fo,oho,under2yd;acifMek,h0;l,x;land;a0co,idDuc;libu,nhattK;a0gw,hr;s,x;ax,cn,ndianGst;arlem,kg,nd;ay village,re0;at 0enwich;britain,lak2;co,ra;urope,verglad0;es;en,fw,own1xb;dg,gk,hina0lt;town;cn,e0kk,rooklyn;l air,verly hills;frica,m5ntar1r1sia,tl0;!ant1;ct0;ic0; oce0;an;ericas,s|Person¦a01bZcTdQeOfMgJhHinez,jFkEleDmAnettPo9p7r4s3t2uncle,v0womL;a0irgin maH;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussaQcarlett johanssRistZlobodan milosevic,omeone,tepGuC;ay romano,eese witherspoQo1ush limbau0;gh;d stewart,naldinho,sario;a0ipV;lmUris hiltM;prah winfrOra;an,essiaen,itt romnNo0ubarek;m0thR;!my;bron james,e;anye west,iefer sutherland,obe bryaN;aime,effersFk rowli0;ng;alle ber0ulk hog3;ry;astBentlem1irl,rand0uy;fa2mo2;an;a0ella;thF;ff0meril lagasse,zekiel;ie;a0enzel washingt4ick wolf,ude;d0lt3nte;!dy;ar2lint1ous0ruz;in;on;dinal wols1son0;! palm5;ey;arack obama,oy,ro0;!ck,th2;dolf hitl1shton kutch1u0;nt;er|WeekDay¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s|Date¦autumn,daylight9eom,one d8s5t2w0yesterd8;eek0int5;d6end;mr1o0;d4morrow;!w;ome 1tandard3umm0;er;d0point;ay; time|Time¦a6breakfast 5dinner5e3lunch5m2n0oclock,some5to7;i7o0;on,w;id4or1;od,ve0;ning;time;fternoon,go,ll day,t 0;ni0;ght|Holiday¦0:1Q;1:1P;a1Fb1Bc12d0Ye0Of0Kg0Hh0Di09june07kwanzaa,l04m00nYoVpRrPsFt9v6w4xm03y2;om 2ule;hasho16kippur;hit2int0Xomens equalit8; 0Ss0T;alentines3e2ictor1E;r1Bteran1;! 0;-0ax 0h6isha bav,rinityMu2; b3rke2;y 0;ish2she2;vat;a0Xe prophets birth0;a6eptember14h4imchat tor0Ut 3u2;kk4mmer T;a8p7s6valentines day ;avu2mini atzeret;ot;int 2mhain;a4p3s2valentine1;tephen1;atrick1;ndrew1;amadan,ememberanc0Yos2;a park1h hashana;a3entecost,reside0Zur2;im,ple heart 0;lm2ssovE; s04;rthodox 2stara;christma1easter2goOhoJn0C;! m07;ational 2ew years09;freedom 0nurse1;a2emorial 0lHoOuharram;bMr2undy thurs0;ch0Hdi gr2tin luther k0B;as;a2itRughnassadh;bour 0g baom2ilat al-qadr;er; 2teenth;soliU;d aJmbolc,n2sra and miraj;augurGd2;ependen2igenous people1;c0Bt1;a3o2;ly satur0;lloween,nukkUrvey mil2;k 0;o3r2;ito de dolores,oundhoW;odW;a4east of 2;our lady of guadalupe,the immaculate concepti2;on;ther1;aster8id 3lectYmancip2piphany;atX;al-3u2;l-f3;ad3f2;itr;ha;! 2;m8s2;un0;ay of the dead,ecemb3i2;a de muertos,eciseis de septiembre,wali;er sol2;stice;anad8h4inco de mayo,o3yber m2;on0;lumbu1mmonwealth 0rpus christi;anuk4inese n3ristmas2;! N;ew year;ah;a 0ian tha2;nksgiving;astillCeltaine,lack4ox2;in2;g 0; fri0;dvent,ll 9pril fools,rmistic8s6u2;stral4tum2;nal2; equinox;ia 0;cens2h wednes0sumption of mary;ion 0;e 0;hallows 6s2;ai2oul1t1;nt1;s 0;day;eve|Month¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il|Duration¦centur4d2hour3m0seconds,week3year3;i0onth2;llisecond1nute1;ay0ecade0;!s;ies,y|FirstName¦aEblair,cCdevBj8k6lashawn,m3nelly,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0;ls7nyatta,rry;am0ess1;ie,m0;ie;an,on;as0heyenne;ey,sidy;lexis,ndra,ubr0;ey|LastName¦0:35;1:3A;2:3C;3:2Z;4:2F;a3Bb31c2Od2Ee2Bf25g1Zh1Oi1Jj1Dk16l0Ym0Mn0Io0Fp04rXsLtGvEwBxAy7zh5;a5ou,u;ng,o;a5eun2Uoshi1Jun;ma5ng;da,guc1Zmo27sh21zaQ;iao,u;a6eb0il5o3right,u;li3Bs1;gn0lk0ng,tanabe;a5ivaldi;ssilj37zqu2;a8h7i2Go6r5sui,urn0;an,ynisI;lst0Orr1Uth;at1Uomps1;kah0Unaka,ylor;aDchCeBhimizu,iAmi9o8t6u5zabo;ar2lliv2AzuD;a5ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n6sa5to;ki;ch2dKtos,z;amAeag1Zi8o6u5;bio,iz,sC;b5dri1MgHj0Sme24osevelt,sZux;erts,ins1;c5ve0E;ci,hards1;ir2os;aDe9h7ic5ow20;as5hl0;so;a5illips;m,n1T;ders20et7r6t5;e0Nr4;ez,ry;ers;h21rk0t5vl4;el,te0J;baAg0Alivei00r5;t5w1O;ega,iz;a5eils1guy1Rix1owak,ym1E;gy,ka5var1K;ji5muV;ma;aDeBiAo7u5;ll0n5rr0Bssolini,ñ5;oz;lina,oJr5zart;al0Me5r0U;au,no;hhail4ll0;rci0s5y0;si;eVmmad4r5tsu07;in5tin2;!o;aBe7i5op2uo;!n5u;coln,dholm;fe6n0Qr5w0J;oy;bv5v5;re;mmy,rs14u;aAennedy,imu9le0Lo7u6wo5;k,n;mar,znets4;bay5vacs;asY;ra;hn,rl8to,ur,zl4;a9en8ha3imen2o5u3;h5nYu3;an5ns1;ss1;ki0Es0S;cks1nsse0D;glesi8ke7noue,shik6to,vano5;u,v;awa;da;as;aBe8it7o6u5;!a3b0ghNynh;a3ffmann,rvat;chcock,l0;mingw6nde5rM;rs1;ay;ns0ErrPs6y5;asCes;an4hi5;moI;a8il,o7r6u5;o,tierr2;ayli3ub0;m2nzal2;nd5o,rcia;hi;er9is8lor7o6uj5;ita;st0urni0;es;ch0;nand2;d6insteGsposi5vaK;to;is1wards;aBeAi8omin7u5;bo5rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw6vi5;es,s;in;aEhAlark9o5;hKl5op0rbyn,x;em6li5;ns;an;!e;an7e6iu,o5ristensFu3we;i,ng,u3w,y;!n,on5u3;!g;mpb6rt0st5;ro;ell;aAe7ha3lanco,oyko,r5yrne;ooks,yant;ng;ck6ethov5nnett;en;er,ham;ch,h7iley,rn5;es,i0;er;k,ng;dCl8nd5;ers5r9;en,on,s1;on;eks6iy7var2;ez;ej5;ev;ams|MaleName¦0:CE;1:BK;2:C2;3:BS;4:B4;5:BZ;6:AT;7:9V;8:BC;9:AW;A:AO;B:8W;aB5bA9c98d88e7Hf6Zg6Hh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt07u06v01wOxavi3yHzC;aCor0;cCh8Jne;hDkC;!a5Z;ar51e5Y;ass2i,oDuC;sEu25;nFsEusC;oCsD;uf;ef;at0g;aKeIiDoCyaAQ;lfgang,odrow;lCn1O;bEey,frBJlC;aA6iC;am,e,s;e8Aur;i,nde7sC;!l6t1;de,lDrr5yC;l1ne;lCt3;a94y;aFern1iC;cDha0nceCrg9Cva0;!nt;ente,t5B;lentin49n8Zughn;lyss4Msm0;aTeOhLiJoFrDyC;!l3ro8s1;av9ReCist0oy,um0;nt9Jv55y;bEd7YmCny;!as,mCoharu;aAYie,y;iBy;mCt9;!my,othy;adDeoCia7EomB;!do7O;!de9;dFrC;en8JrC;an8IeCy;ll,n8H;!dy;dgh,ic9Unn3req,ts46;aScotQeOhKiIoGpenc3tCur1Pylve8Jzym1;anEeCua7D;f0phAGvCwa7C;e59ie;!islaw,l6;lom1nA4uC;leyma8ta;dClBm1;!n6;aEeC;lCrm0;d1t1;h6Une,qu0Vun,wn,y8;aCbasti0k1Yl42rg41th,ymo9J;m9n;!tC;!ie,y;lDmCnti22q4Kul;!mAu4;ik,vato6X;aXeThe94iPoGuDyC;an,ou;b6NdDf9pe6SssC;!elAK;ol2Vy;an,bJcIdHel,geGh0landA4mFnEry,sDyC;!ce;coe,s;!a96nA;an,eo;l3Kr;e4Sg3n6oA5ri6A;co,ky;bAe9V;cCl6;ar5Qc5PhDkCo;!ey,ie,y;a87ie;gDid,ub5x,yCza;ansh,nT;g8XiC;na8Ts;ch60fa4lEmDndCpha4sh6Wul,ymo72;alA0ol2Cy;i9Jon;f,ph;ent2inC;cy,t1;aGeEhilDier64ol,reC;st1;!ip,lip;d9Crcy,tC;ar,e2W;b3Udra6Ht46ul;ctav2Wliv3m97rGsDtCum8Vw5;is,to;aDc8TvC;al54;ma;i,l4BvK;athKeIiEoC;aCel,l0ma0r2Y;h,m;cDg4i3KkC;h6Wola;holBkColB;!olB;al,d,il,ls1vC;il52;anCy;!a4i4;aXeUiLoGuDyC;l22r1;hamDr61staC;fa,p4I;ed,mG;dibo,e,hamEis1YntDsCussa;es,he;e,y;ad,ed,mC;ad,ed;cHgu4kFlEnDtchC;!e7;a7Aik;o04t1;e,olC;aj;ah,hCk6;a4eC;al,l;hDlv2rC;le,ri7v2;di,met;ck,hOlMmPnu4rIs1tEuricDxC;!imilian87we7;e,io;eo,hDiBtC;!eo,hew,ia;eCis;us,w;cEio,k81lDqu6Isha7tCv2;i2Jy;in,on;!el,oLus;achCcolm,ik;ai,y;amCdi,moud;adC;ou;aSeOiNlo2ToJuDyC;le,nd1;cFiEkCth3;aCe;!s;gi,s;as,iaC;no;g0nn6SrenEuCwe7;!iC;e,s;!zo;am,on4;a7Cevi,la4UnEoCst3vi;!nC;!a62el;!ny;mDnCr16ur4Vwr4V;ce,d1;ar,o4P;aJeEhaled,iCrist4Xu4Ay3D;er0p,rC;by,k,ollos;en0iFnCrmit,v2;!dDnCt5E;e10y;a7ri4P;r,th;na69rCthem;im,l;aZeRiPoEuC;an,liCst2;an,o,us;aqu2eKhnJnHrFsC;eDhCi7Due;!ua;!ph;dCge;an,i,on;!aCny;h,s,th4Z;!ath4Yie,nA;!l,sCy;ph;an,e,mC;!mA;d,ffHrEsC;sCus;!e;a5KemDmai8oCry;me,ni0Q;i6Wy;!e07rC;ey,y;cId5kHmGrEsDvi3yC;!d5s1;on,p3;ed,od,rCv4O;e51od;al,es,is1;e,ob,ub;k,ob,quC;es;aObrahNchika,gLkeKlija,nuJrHsEtCv0;ai,sC;uki;aCha0i6Hma4sac;ac,iaC;h,s;a,vinCw2;!g;k,nngu53;!r;nacCor;io;im;in,n;aLeGina4WoEuCyd57;be27gCmber4EsE;h,o;m3ra35sCwa3Z;se2;aFctEitEnDrC;be22m0;ry;or;th;bLlKmza,nJo,rEsDyC;a44d5;an,s0;lFo4FrEuCv6;hi41ki,tC;a,o;is1y;an,ey;k,s;!im;ib;aReNiMlenLoJrFuC;illerDsC;!tavo;mo;aEegCov3;!g,orC;io,y;dy,h58nt;nzaCrd1;lo;!n;lbe4Qno,ovan4S;ne,oErC;aCry;ld,rd4O;ffr6rge;bri4l5rCv2;la20r3Fth,y;aSeOiMlKorr0JrC;anEedCitz;!dAeCri25;ri24;cEkC;!ie,lC;in,yn;esKisC;!co,zek;etch3oC;yd;d4lConn;ip;deriEliDng,rnC;an02;pe,x;co;bi0di;ar00dVfrUit0lOmHnGo2rDsteb0th0uge8vCym5zra;an,ere2W;gi,iDnCrol,v2w2;est3Zie;c08k;och,rique,zo;aHerGiDmC;aGe2Q;lDrC;!h0;!io;s1y;nu4;be0Ad1iFliEmDt1viCwood;n,s;er,o;ot1Us;!as,j44sC;ha;a2en;!dAg32mFuDwC;a26in;arC;do;o0Tu0T;l,nC;est;aZePiMoFrEuDwCyl0;ay8ight;a8dl6nc0st2;ag0ew;minGnEri0ugDyC;le;!lB;!a29nCov0;e7ie,y;go,icC;!k;armuDeCll1on,rk;go;id;anJj0lbeImetri9nGon,rFsEvDwCxt3;ay8ey;en,in;hawn,mo09;ek,ri0G;is,nCv3;is,y;rt;!dC;re;lLmJnIrEvC;e,iC;!d;en,iEne7rCyl;eCin,yl;l2Wn;n,o,us;!e,i4ny;iCon;an,en,on;e,lB;as;a07e05hXiar0lMoHrFuDyrC;il,us;rtC;!is;aCistobal;ig;dy,lFnDrC;ey,neli9y;or,rC;ad;by,e,in,l2t1;aHeEiCyJ;fCnt;fo0Dt1;meDt9velaC;nd;nt;rEuDyC;!t1;de;enC;ce;aGeFrisDuC;ck;!tC;i0oph3;st3;d,rlCs;eCie;s,y;cCdric,s11;il;lFmer1rC;ey,lDro7y;ll;!os,t1;eb,v2;ar03eVilUlaToQrDuCyr1;ddy,rtJ;aKeFiEuDyC;an,ce,on;ce,no;an,ce;nDtC;!t;dDtC;!on;an,on;dDndC;en,on;!foCl6y;rd;bDrCyd;is;!by;i8ke;al,lA;nGrCshoi;at,nDtC;!r11;aCie;rd0M;!edict,iDjam2nA;ie,y;to;n6rCt;eCy;tt;ey;ar0Yb0Od0Kgust2hm0Hid5ja0FlZmXnPputsiOrFsaEuCya0ziz;gust9st2;us;hi;aJchIi4jun,maGnEon,tCy0;hCu07;ur;av,oC;ld;an,nd05;el;ie;ta;aq;dHgel00tC;hoFoC;i8nC;!iXy;ne;ny;reCy;!as,s,w;ir,mCos;ar;an,bePd5eJfGi,lFonEphonIt1vC;aNin;on;so,zo;an,en;onDrC;edK;so;c,jaFksandEssaFxC;!and3;er;ar,er;ndC;ro;rtC;!o;ni;en;ad,eC;d,t;in;aDoCri0vik;lfo;mCn;!a;dGeFraDuC;!bakr,lfazl;hCm;am;!l;allFel,oulaye,ulC;!lDrahm0;an;ah,o;ah;av,on|Verb¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en|PhrasalVerb¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut|Modal¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld|Adjective¦0:73;1:7I;2:7O;3:7H;4:7A;5:5A;6:47;7:48;8:4Q;9:5Z;A:7F;B:6X;C:5V;D:6Y;E:71;a6Hb63c5Pd55e4Rf48g40h3Pi34j32k31l2Qm2Fn26o1Qp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6A;d6Czy;despr73s5E;!sa7;eGlFste25;co1Hl o4J;!k5;aGiFola4A;b7Rce versa,ol53;ca2gabo61nilla;ltWnJpGrb58su4tterF;!moB; f33b1NpGsFti1G;ca7et,ide dMtairs;er,i3M;aPbeco6Pconvin26deMeLfair,ivers4knKprecedYrIsGwF;iel1Zritt5X;i1UuF;pervis0specti3;eFu5;cognLgul6Fl6F;own;ndi3v5Rxpect0;cid0rF;!grou5MsF;iz0tood;b7ppeaLssu6EuthorF;iz0;i23ra;aJeHhough4NoGrF;i1oubl0;geth8p,rpD;en5OlFm4Yrr2Tst0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3DoPpOqueami3DtJuFymb62;bHi gener53pFrprisi3;erFre0K;! dup8b,i28;du0seq4S;anda6SeIi0OrFy37;aightFip0; fFfF;or59;adfaBreotyp0;aCec2Fir1IlendDot on; call0le,mb8phist1WrFu0Wvi40;dDry;gnifica2nF;ceCg7;am2Oe8ocki3ut;cFda1em5lfi2Xni1Vpa67re6;o1Fr3U;at56ient27reec56;cr0me,ns serif;aMeIiGoF;buBtt4SuSy4;ghtFv4;!-28f9;ar,bel,condi1du61fres50lHpublic3UsFtard0;is46oF;lu1na2;e1Duc44;bDciF;al,st;aPeNicayu6lacDopuliBrGuF;bl58mp0;eJiGoF;!b09fuEmi30p8;mGor,sFva1;ti6;a4Ue;ciEmF;a0Hi5I;ac20rFti1;feAma2Tplexi3v33;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Lsi45;en,posi1; boa5Fg2Jli6;!ay; gua5DbFli6;eat;eHsF;cFer0Hole1;e6uC;d2Sse;ak0eMiLoFua4O;nJrGtF;ab7;thF;!eF;rn;chala2descri4Zstop;ght5;arby,cessa3Wighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuC;di4EnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abCho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3C;!-0C;nguDst,tt8;ap1Sind5no0A;agg0uF;niOstifi0veni7;de4gno4Blleg4mSnHpso 1VrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenEoxF;ic36;a6i2R;a1er,oce2;iGoF;or;reA;deq3Jppr2Y;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0Q;d2QnE;aKelJiHoFumdr3B;neBok0rrFs07ur5;if2S;ghfalut1OspF;an2Q;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Jiga22lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Dob4;aUeOinNlMoHrF;a1TeFoz1K;e2Dq12tf9;oHrF; keeps,eFm8tuna1;g04ign;liF;sh;ag2Zue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lEr Fux,vori1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiC;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erE;creHeas0gruntl0honeBordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarClJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraDg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainBgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerE;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt|Comparable¦0:41;1:4I;2:45;3:4B;4:2Y;5:3X;a4Ob44c3Od3De35f2Rg2Fh24i1Vj1Uk1Rl1Im1Cn16o14p0Tqu0Rr0IsRtKuIvFw7y6za12;ell27ou3;aBe9hi1Yi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Mt;k,ry;n1Tr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Mse5;like0ti1;aAen9hi8i7ough,r6;anqu2Qen1ue;dy,g3Ume0ny,r09;ck,n,rs2R;d42se;ll,me,rt,s6wd47;te5;aVcarUeThRiQkin0GlMmKoHpGqua1HtAu7w6;eet,ift;b7dd15per0Hr6;e,re2J;sta2Ht4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Hn0W;a1ep,rn;le,rk;e24i3Hright0;ci2Aft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g37m6;!y;ek,nd3F;ck,l0mp4;a6iUort,rill,y;dy,ll0Zrp;cu0Tve0Txy;ce,ed,y;d,fe,int0l1Xv16;aBe9i8o6ude;mantic,o1Ksy,u6;gh,nd;ch,pe,tzy;a6d,mo0J;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aFhoEi1SlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fou00ud;ey,k0;li06or,te1D;a6easa2;in,nt;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd|Adverb¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori|Expression¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la|Preposition¦'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut|Conjunction¦aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh|Determiner¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er","conjugations":"t:ake,ook,,,aken|:can,could,can,_|free:_,,,ing|puk:e,,,ing|ar:ise,ose,,,isen|babys:it,at|:be,was,is,am,been|:is,was,is,being|beat:_,,,ing,en|beg:in,an,,inning,un|ban:_,ned,,ning|bet:_,,,,_|bit:e,_,,ing,ten|ble:ed,d,,,d|bre:ed,d|br:ing,ought,,,ought|broadcast:_,_|buil:d,t,,,t|b:uy,ought,,,ought|cho:ose,se,,osing,sen|cost:_,_|deal:_,t,,,t|d:ie,ied,,ying|d:ig,ug,,igging,ug|dr:aw,ew,,,awn|dr:ink,ank,,,unk|dr:ive,ove,,iving,iven|:eat,ate,,eating,eaten|f:all,ell,,,allen|fe:ed,d,,,d|fe:el,lt|f:ight,ought,,,ought|f:ind,ound|fl:y,ew,,,own|bl:ow,ew,,,own|forb:id,ade|edit:_,,,ing|forg:et,ot,,eting,otten|forg:ive,ave,,iving,iven|fr:eeze,oze,,eezing,ozen|g:et,ot|g:ive,ave,,iving,iven|:go,went,goes,,gone|h:ang,ung,,,ung|ha:ve,d,s,ving,d|hear:_,d,,,d|hid:e,_,,,den|h:old,eld,,,eld|hurt:_,_,,,_|la:y,id,,,id|le:ad,d,,,d|le:ave,ft,,,ft|l:ie,ay,,ying|li:ght,t,,,t|los:e,t,,ing|ma:ke,de,,,de|mean:_,t,,,t|me:et,t,,eting,t|pa:y,id,,,id|read:_,_,,,_|r:ing,ang,,,ung|r:ise,ose,,ising,isen|r:un,an,,unning,un|sa:y,id,ys,,id|s:ee,aw,,eeing,een|s:ell,old,,,old|sh:ine,one,,,one|sho:ot,t,,,t|show:_,ed|s:ing,ang,,,ung|s:ink,ank|s:it,at|slid:e,_,,,_|sp:eak,oke,,,oken|sp:in,un,,inning,un|st:and,ood|st:eal,ole|st:ick,uck|st:ing,ung|:stream,,,,|str:ike,uck,,iking|sw:ear,ore|sw:im,am,,imming|sw:ing,ung|t:each,aught,eaches|t:ear,ore|t:ell,old|th:ink,ought|underst:and,ood|w:ake,oke|w:ear,ore|w:in,on,,inning|withdr:aw,ew|wr:ite,ote,,iting,itten|t:ie,ied,,ying|ski:_,ied|:boil,,,,|miss:_,,_|:act,,,,|compet:e,ed,,ing|:being,were,are,are|impl:y,ied,ies|ic:e,ed,,ing|develop:_,ed,,ing|wait:_,ed,,ing|aim:_,ed,,ing|spil:l,t,,,led|drop:_,ped,,ping|log:_,ged,,ging|rub:_,bed,,bing|smash:_,,es|egg:_,ed|suit:_,ed,,ing|age:_,d,s,ing|shed:_,_,s,ding|br:eak,oke|ca:tch,ught|d:o,id,oes|b:ind,ound|spread:_,_|become:_,,,,_|ben:d,,,,t|br:ake,,,,oken|burn:_,,,,ed|burst:_,,,,_|cl:ing,,,,ung|c:ome,ame,,,ome|cre:ep,,,,pt|cut:_,,,,_|dive:_,,,,d|dream:_,,,,t|fle:e,,,eing,d|fl:ing,,,,ung|got:_,,,,ten|grow:_,,,,n|hit:_,,,,_|ke:ep,,,,pt|kne:el,,,,lt|know:_,,,,n|leap:_,,,,t|len:d,,,,t|lo:ose,,,,st|prove:_,,,,n|put:_,,,,_|quit:_,,,,_|rid:e,,,,den|s:eek,,,,ought|sen:d,,,,t|set:_,,,,_|sew:_,,,,n|shake:_,,,,n|shave:_,,,,d|shut:_,,,,_|s:eat,,,,at|sla:y,,,,in|sle:ep,,,,pt|sn:eak,,,,uck|spe:ed,,,,d|spen:d,,,,t|sp:it,,,,at|split:_,,,,_|spr:ing,,,,ung|st:ink,unk,,,unk|strew:_,,,,n|sw:are,,,,orn|swe:ep,,,,pt|thrive:_,,,,d|undergo:_,,,,ne|upset:_,,,,_|w:eave,,,,oven|we:ep,,,,pt|w:ind,,,,ound|wr:ing,,,,ung","plurals":"addend|um|a,alga|e,alumna|e,alumn|us|i,appendi|x|ces,avocado|s,bacill|us|i,barracks|,beau|x,bus|es,cact|us|i,chateau|x,analys|is|es,diagnos|is|es,parenthes|is|es,prognos|is|es,synops|is|es,thes|is|es,child|ren,circus|es,clothes|,corp|us|ora,criteri|on|a,curricul|um|a,database|s,deer|,echo|es,embargo|es,epoch|s,f|oot|eet,gen|us|era,g|oose|eese,halo|s,hippopotam|us|i,ind|ex|ices,larva|e,lea|f|ves,librett|o|i,loa|f|ves,m|an|en,matri|x|ces,memorand|um|a,modul|us|i,mosquito|es,move|s,op|us|era,ov|um|a,ox|en,pe|rson|ople,phenomen|on|a,quiz|zes,radi|us|i,referend|um|a,rodeo|s,sex|es,shoe|s,sombrero|s,stomach|s,syllab|us|i,tableau|x,thie|f|ves,t|ooth|eeth,tornado|s,tuxedo|s,zero|s","patterns":{"Person":["master of #Noun","captain of the #Noun"]},"regex":{"HashTag":["^#[a-z]+"],"Gerund":["^[a-z]+n['’]$"],"PhoneNumber":["^[0-9]{3}-[0-9]{4}$","^[0-9]{3}[ -]?[0-9]{3}-[0-9]{4}$"],"Time":["^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])$","^[012]?[0-9](:[0-5][0-9])?(:[0-5][0-9])? ?(am|pm)$","^[012]?[0-9](:[0-5][0-9])(:[0-5][0-9])? ?(am|pm)?$","^[PMCE]ST$","^utc ?[+-]?[0-9]+?$","^[a-z0-9]*? o'?clock$"],"Date":["^[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,4}$","^[0-9]{1,4}/[0-9]{1,2}/[0-9]{1,4}$"],"Money":["^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?$","^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$"],"Value":["^[-+]?[$€¥£][0-9]+(.[0-9]{1,2})?$","^[-+]?[$€¥£][0-9]{1,3}(,[0-9]{3})+(.[0-9]{1,2})?$","^[0-9.]{1,2}[-–][0-9]{1,2}$"],"NumberRange":["^[0-9.]{1,4}(st|nd|rd|th)?[-–][0-9.]{1,4}(st|nd|rd|th)?$","^[0-9.]{1,2}[-–][0-9]{1,2}$"],"NiceNumber":["^[-+]?[0-9.,]{1,3}(,[0-9.,]{3})+(.[0-9]+)?$"],"NumericValue":["^[-+]?[0-9]+(.[0-9]+)?$","^.?[0-9]+([0-9,.]+)?%$"],"Percent":["^.?[0-9]+([0-9,.]+)?%$"],"Cardinal":["^.?[0-9]+([0-9,.]+)?%$"],"Fraction":["^[0-9]{1,4}/[0-9]{1,4}$"],"LastName":["^ma?c'.*","^o'[drlkn].*"]}}` \ No newline at end of file +module.exports={ + "Comparative": "true¦better", + "Superlative": "true¦earlier", + "PresentTense": "true¦is,sounds", + "Value": "true¦a few", + "Noun": "true¦a8b7c5e3f2here,ie,lit,m1no doubt,p0tce,vs;d,l;a,d;t,y;g,sp,tc,x0;!p;a,ca,o0;l,rp;a,c,l;d,l,rc", + "Copula": "true¦a1is,w0;as,ere;m,re", + "PastTense": "true¦be3came,d2had,meant,sa2taken,w0;as,e0;nt,re;id;en,gan", + "Condition": "true¦if,unless", + "Gerund": "true¦accord0be0develop0go0result0stain0;ing", + "Negative": "true¦n0;ever,o0;!n,t", + "QuestionWord": "true¦how3wh0;at,e1ich,o0y;!m,se;n,re; come,'s", + "Plural": "true¦records", + "Conjunction": "true¦&,aEbAcuz,how8in caDno7o6p4supposing,t1vers5wh0yet;eth8ile;h0o;eref9o0;!uC;l0rovided that;us;r,therwi6; matt1r;!ev0;er;e0ut;cau1f0;ore;se;lthou1nd,s 0;far as,if;gh", + "Pronoun": "true¦'em,elle,h4i3me,ourselves,she5th1us,we,you0;!rself;e0ou;m,y;!l,t;e0im;!'s", + "Singular": "true¦0:0X;1:10;a0Wb0Kc0Bd04e02fXgShOici1jel0kitty,lNmJnIoHpDquestion mark,rBs7t4u2womW;nc0Rs 2;doll0Dst0F; rex,a3h2ic,ragedy,v show;ere,i1;l0x return;ist0Pky,omeone,t2uper bowl,yst0W;ep3ri1u2;de0Pff;faMmoM;al0i1o2;om,se;a4i0Jr3u2;dLrpoD;erogaVobl0O;rt,te0I;bjSceGthers;othi1umb0E;a4ee04o2;del,m2nopo0th0C;!my;n,yf0;i0unch;ead start,o2;l0me3u2;se;! run;adf0entlem5irlZlaci04od,rand3u2;l0y; slam,fa2mo2;th01;an;a5ella,ly,ol0r3un2;di1;iTo2;ntiWsN;mi0thV;conomy,gg,ner5veWx2;ampQecu7;ad7e4innSo2ragonf0ude;cumentFg2i0l0or;gy;ath,t2;ec2;tive;!dy;a8eili1h6i4o2redit card;ttage,u2;riJsin;ty,vil w2;ar;andeliGocol2;ate;n2rD;ary;aAel0lesHo6r4u2;n2tterf0;ti1;eakfast,o2;!th8;dy,tt4y2;!fri2;end;le;nki1r2;ri2;er;d4l0noma0u2;nt;ly; homin4verti2;si1;ng;em", + "Actor": "true¦aJbGcFdCengineIfAgardenIh9instructPjournalLlawyIm8nurse,opeOp5r3s1t0;echnCherapK;ailNcientJoldiGu0;pervKrgeon;e0oofE;ceptionGsearC;hotographClumbColi1r0sychologF;actitionBogrammB;cem6t5;echanic,inist9us4;airdress8ousekeep8;arm7ire0;fight6m2;eputy,iet0;ici0;an;arpent2lerk;ricklay1ut0;ch0;er;ccoun6d2ge7r0ssis6ttenda7;chitect,t0;ist;minist1v0;is1;rat0;or;ta0;nt", + "Honorific": "true¦a03b00cSdReQfiLgKhon,jr,king,lJmEoDp8queen,r4s0taoiseach,vice7;e1fc,gt,ir,r,u0;ltTpt,rg;c0nDrgeaL;ond liJretary;abbi,e0;ar1pAs,v0;!erend; admirY;astPhd,r0vt;esideEi1of0;!essN;me mini5nce0;!ss;fficOp,rd;a3essrs,i2lle,me,r1s0;!tr;!s;stK;gistrate,j,r6yF;i3lb,t;en,ov;eld mar3rst l0;ady,i0;eutena0;nt;shG;sq,xcellency;et,oct6r,utchess;apt6hance4mdr,o0pl;lonel,m2ngress0unci3;m0wom0;an;dr,mand5;ll0;or;!ain;ldg,rig0;!adi0;er;d0sst,tty,yatullah;j,m0v;!ir0;al", + "SportsTeam": "true¦0:1A;1:1H;2:1G;a1Eb16c0Td0Kfc dallas,g0Ihouston 0Hindiana0Gjacksonville jagua0k0El0Bm01newToQpJqueens parkIreal salt lake,sAt5utah jazz,vancouver whitecaps,w3yW;ashington 3est ham0Rh10;natio1Oredski2wizar0W;ampa bay 6e5o3;ronto 3ttenham hotspur;blue ja0Mrapto0;nnessee tita2xasC;buccanee0ra0K;a7eattle 5heffield0Kporting kansas0Wt3;. louis 3oke0V;c1Frams;marine0s3;eah15ounG;cramento Rn 3;antonio spu0diego 3francisco gJjose earthquak1;char08paA; ran07;a8h5ittsburgh 4ortland t3;imbe0rail blaze0;pirat1steele0;il3oenix su2;adelphia 3li1;eagl1philNunE;dr1;akland 3klahoma city thunder,rlando magic;athle0Mrai3;de0; 3castle01;england 7orleans 6york 3;city fc,g4je0FknXme0Fred bul0Yy3;anke1;ian0D;pelica2sain0C;patrio0Brevolut3;ion;anchester Be9i3ontreal impact;ami 7lwaukee b6nnesota 3;t4u0Fvi3;kings;imberwolv1wi2;rewe0uc0K;dolphi2heat,marli2;mphis grizz3ts;li1;cXu08;a4eicesterVos angeles 3;clippe0dodDla9; galaxy,ke0;ansas city 3nE;chiefs,roya0E; pace0polis colU;astr06dynamo,rockeTtexa2;olden state warrio0reen bay pac3;ke0;.c.Aallas 7e3i05od5;nver 5troit 3;lio2pisto2ti3;ge0;broncZnuggeM;cowbo4maver3;ic00;ys; uQ;arCelKh8incinnati 6leveland 5ol3;orado r3umbus crew sc;api5ocki1;brow2cavalie0india2;bengaWre3;ds;arlotte horAicago 3;b4cubs,fire,wh3;iteB;ea0ulR;diff3olina panthe0; c3;ity;altimore 9lackburn rove0oston 5rooklyn 3uffalo bilN;ne3;ts;cel4red3; sox;tics;rs;oriol1rave2;rizona Ast8tlanta 3;brav1falco2h4u3;nited;aw9;ns;es;on villa,r3;os;c5di3;amondbac3;ks;ardi3;na3;ls", + "Uncountable": "true¦a1Ib1Ac11d0Ye0Rf0Lg0Hh0Ci08j07knowled1Hl02mUnews,oTpQrLsAt5vi4w0;a2ea05i1oo0;d,l;ldlife,ne;rmth,t17;neg0Yol06tae;e3h2oothpaste,r0una;affPou0;ble,sers,t;ermod1Eund12;a,nnis;a8cene04eri0Oh7il6kittl0Onow,o5p3t1u0;g0Rnshi0H;ati1De0;am,el;ace16e0;ci0Jed;ap,cc0U;k,v0T;eep,ingl0G;d04fe10l0nd;m0St;a3e1ic0;e,ke0D;c0laxa09search;ogni08rea08;bi09in;aJe1hys10last5o0ressV;lit0Zrk,w0J;a0Vtrol;bstetr0Xil,xygen;a5e3ilk,o2u0;mps,s0;ic;nGo0A;a0chan0S;slZt;chine0il,themat0Q; learn05ry;aught08e2i1ogi0Nu0;ck,g0C;ce,ghtn02ngui0LteratH;a0isG;th04;ewel7usti0G;ce,mp0nformaOtself;a0ortan0E;ti0;en0C;a3isto2o0;ck0mework,n0spitali06;ey;ry;ir,libut,ppi7;en01o1r0um,ymna08;a6ound;l0ssip;d,f;i4lour,o1urnit0;ure;od,rgive0uriNwl;ne0;ss;c6sh;conomZduca5lectr4n2quip3thZvery0;body,o0thE;ne;joy0tertain0;ment;iciNonU;tiF;ar1iabet0raugh1;es;ts;a7elcius,h3ivPl2o0urrency;al,ld w0nfusiAttA;ar;assMoth2;aos,e0;e1w0;ing;se;r4sh;a4eef,i1lood,owls,read,utt0;er;lliar1s0;on;ds;g0ss;ga0;ge;c6dvi5ero3ir2mnes1rt,thl0;et7;ty;craft;b4d0naut4;ynam3;ce;id,ou0;st0;ics", + "Infinitive": "true¦0:6H;1:6V;2:55;3:6S;4:6T;5:5W;6:64;7:6R;8:6N;9:6F;A:6P;B:6M;C:6A;D:6W;a67b5Wc4Yd46e3Qf3Dg37h30i2Nj2Lk2Jl2Am20n1Xo1Tp1Eques3Er0Ms01tTuPvMwFyE;awn,ield;aHe1Thist6iGoEre60;nd0rE;k,ry;pe,sh,th0;lk,nFrEsh,tCve;n,raD;d0t;aFiEo7;ew,sB;l68ry;nFpEr3se;gra4Jli3W;dEi7lo5O;er47o;aKeJhIoHrFuEwi8;ne,rn;aEe0Ki5Ku8y;de,in,nsf0p,v5C;r2VuC;ank,reat2L;nd,st;lk,rg1Ms7;aXcUeThRi48kip,lQmPnee3Ho4WpOtHuEwitC;bmBck,ff0gge8ppFrEspe5;ge,pri1rou4Tvi4;ly,o32;aJeIoHrFuE;dy,mb6;a4NeEi4;ngth2Bss,tC;p,re;m,p;in,ke,r0Oy;la50oil,rink6;e1Vi6o3F;am,ip;a2iv0oE;ck,ut;arCem,le5n1r4tt6;aFo2rE;atCew;le,re;il,ve;a03eGisk,oFuE;in,le,sh;am,ll;aZcXdu9fWgVje5lSmRnt,pOquNsItHvEwa5L;eEiew,o32;al,l,rE;se,t;a41i2u3Y;eHi8oGtE;!o2rE;i5uc1W;l4rt;mb6nt,r4;e8i2;air,eFlEo3XreseD;a9y;at;a3Remb0i3To4;aFeEi4y;a1nt;te,x;a53r0F;act1Uer,le5u1;a0Zei4k5FoEyc6;gni28nci6rd;ch,li27s5D;i1nE;ge,k;aRerQiPlMoKrGuE;b1Xll,mp,rEsh;cha1s4G;ai1eGiDoE;cEdu9greAhibBmi1te8vi2R;eAlaim;di5pa2ss,veD;iDp,rtr3WsEur;e,t;aFuE;g,n3;n,y;ck,le;fo2YmBsi8;ck,iDrt4Css,u1;bGccur,ff0pera7utweFverEwe;co3Xlap,ta1Yu1whelm;igh;ser4ta2Y;eFotE;e,i9;ed,gle5;aJeIiGoFuE;ltip3Ard0;nit10ve;nErr0Z;d,g6us;asu2lt,n0Mr3ssa3;inta2Ona3rFtE;ch,t0;ch,kEry;et;aKeJiGoEu1A;aEck,ok,ve;d,n;ft,ke,mBnFstEve;!en;e,k;a2Bc0Ct;b0Lck,uE;gh,nC;iEno2W;ck,ll,ss;am,o29uE;d3mp;gno2mOnEss39;cMdica7flu0KhLsItGvE;eEol4;nt,st;erErodu9;a5fe2;i8tE;aEru5;ll;abBibB;lu1Cr1A;agi20pE;lemeDo1Yro4;aIeGi2oFuE;nt,rry;n00pe,st;aElp;d,t;nd6ppErm,te;en;aIloAove1KrGuE;arEeAi11;ant30d;aEip,umb6;b,sp;in,th0ze;aOeaNiLlJoGracFuncE;ti3A;tu2;cus,lFrE;ce,eca8m,s2S;d,l1W;a1ToE;at,od,w;gu2lEni1Rx;e,l;r,tu2;il,vE;or;a11cho,le5mQnNstLvalua7xE;a08cJerIi8pEte15;a14eFla12oEreA;rt,se;ct,riE;en9;ci1t;el,han3;abEima7;li1D;ab6couVdFfor9ga3han9j01riCsu2t0vE;isi2Ny;!u2;body,er3pE;hasiEow0;ze;a04eSiJoIrFuE;mp;aFeAiE;ft;g,in;d3ubt;ff0p,re5sFvE;iWor9;aIcFliEmiApl13tingui0Y;ke;oEuA;uEv0;ra3;gr1QppE;ear,ro4;cLem,fJliv0ma0Bny,pIsFterE;mi0C;cribe,er4iFtrE;oy;gn,re;a07e06i5osB;eEi07y;at,ct;iGlFrE;ea1;a2i03;de;ma3n9re,te;a08e07h04i7l02oHrE;aFeEoAu0Dy;a7dB;ck,ve;llXmQnFok,py,uEv0;gh,nt;ceNdu5fKsItGvE;eEin9;rt,y;aNin0PrE;a8ibu7ol;iEtitu7;d0st;iFoEroD;rm;gu2rm;rn;biJfoImaHpE;a2laE;in;re;nd;rt;ne;ap1e5;aEip,o1;im,w;aFeE;at,ck,w;llen3n3r3se;a1nt0;ll,ncFrEt0u1;e,ry;el;aNeKloJoHruGuE;lEry;ly;sh;a8mb,o8rrEth0un9;ow;ck;ar,lFnefBtrE;ay;ie4ong;ng,se;band0Hc09d04ffo03gr02id,lZmu1nWppRrOsIttEvoid,waB;acGeFra5;ct;m0Dnd;h,k;k,sE;eGiFocia7uE;me;gn,st;mb6rt;le;chFgEri4;ue;!i4;eaHlGroE;aCve;ch;aud,y;l,r;noun9sw0tE;icipa7;ce;lFt0;er;e3ow;ee;rd;aPdGju8mBoP;it;st;!reA;ss;cHhie4knowled3tiva7;te;ge;ve;eGouDu1;se;nt;pt;on", + "Unit": "true¦0:16;a11b0Zc0Ld0Ke0If0Dg09h06in0Ejoule0k00lYmNnMoLpIqHsqCt7volts,w6y4z3°2µ1;g,s;c,f,n;b,e2;a0Kb,d0Qears old,o1;tt0E;att0b;able4b3e2on1sp;!ne0;a2r0A;!l,sp;spo01; ft,uare 1;c0Fd0Ef3i0Ckilo0Gm1ya0B;e0Jil1;e0li0E;eet0o0A;t,uart0;ascals,e2i1ou0Mt;c0Jnt0;rcent,tZ;hms,uVz;an0GewtQ;/s,b,e7g,i3l,m2p1²,³;h,s;!²;!/h,cro3l1;e1li05;! DsC²;g05s0A;gPter1;! 2s1;! 1;per second;b,iZm,u1x;men0x0;b,elvin0g,ilo2m1nQ;!/h,ph,²;byYgWmeter1;! 2s1;! 1;per hour;e1g,z;ct1rtz0;aXogQ;al2b,igAra1;in0m0;!l1;on0;a4emtPl2t1;²,³; oz,uid ou1;nce0;hrenheit0rad0;b,x1;abyH;eciCg,l,mA;arat0eAg,m9oulomb0u1;bic 1p0;c5d4fo3i2meAya1;rd0;nch0;ot0;eci2;enti1;me4;!²,³;lsius0nti1;g2li1me1;ter0;ram0;bl,y1;te0;c4tt1;os1;eco1;nd0;re0;!s", + "Organization": "true¦0:46;a3Ab2Qc2Ad21e1Xf1Tg1Lh1Gi1Dj19k17l13m0Sn0Go0Dp07qu06rZsStFuBv8w3y1;amaha,m0Xou1w0X;gov,tu2S;a3e1orld trade organizati41;lls fargo,st1;fie22inghou16;l1rner br3D;-m11gree31l street journ25m11;an halNeriz3Wisa,o1;dafo2Gl1;kswagLvo;bs,kip,n2ps,s1;a tod2Rps;es35i1;lev2Xted natio2Uv; mobi2Kaco bePd bMeAgi frida9h3im horto2Tmz,o1witt2W;shiba,y1;ota,s r Y;e 1in lizzy;b3carpen33daily ma2Xguess w2holli0rolling st1Ms1w2;mashing pumpki2Ouprem0;ho;ea1lack eyed pe3Fyrds;ch bo1tl0;ys;l2s1;co,la m12;efoni07us;a6e4ieme2Gnp,o2pice gir5ta1ubaru;rbucks,to2N;ny,undgard1;en;a2Rx pisto1;ls;few25insbu26msu1X;.e.m.,adiohead,b6e3oyal 1yan2X;b1dutch she4;ank;/max,aders dige1Ed 1vl32;bu1c1Uhot chili peppe2Klobst28;ll;c,s;ant2Vizno2F;an5bs,e3fiz24hilip morrBi2r1;emier27octer & gamb1Rudenti14;nk floyd,zza hut;psi28tro1uge08;br2Qchina,n2Q; 2ason1Xda2G;ld navy,pec,range juli2xf1;am;us;a9b8e5fl,h4i3o1sa,wa;kia,tre dame,vart1;is;ke,ntendo,ss0K;l,s;c,st1Etflix,w1; 1sweek;kids on the block,york08;a,c;nd1Us2t1;ional aca2Fo,we0Q;a,cYd0O;aAcdonald9e5i3lb,o1tv,yspace;b1Nnsanto,ody blu0t1;ley crue,or0O;crosoft,t1;as,subisO;dica3rcedes2talli1;ca;!-benz;id,re;'s,s;c's milk,tt13z1Y;'ore09a3e1g,ittle caesa1Ktd;novo,x1;is,mark; pres5-z-boy,bour party;atv,fc,kk,m1od1K;art;iffy lu0Lo3pmorgan1sa;! cha1;se;hnson & johns1Sy d1R;bm,hop,n1tv;c,g,te1;l,rpol; & m,asbro,ewlett-packaTi3o1sbc,yundai;me dep1n1J;ot;tac1zbollah;hi;eneral 6hq,l5mb,o2reen d0Iu1;cci,ns n ros0;ldman sachs,o1;dye1g0B;ar;axo smith kliZencore;electr0Im1;oto0V;a3bi,da,edex,i1leetwood mac,oGrito-l0A;at,nancial1restoV; tim0;cebook,nnie mae;b06sa,u3xxon1; m1m1;ob0H;!rosceptics;aiml0Ae5isney,o3u1;nkin donuts,po0Wran dur1;an;j,w j1;on0;a,f leppa3ll,p2r spiegZstiny's chi1;ld;eche mode,t;rd;aEbc,hBi9nn,o3r1;aigsli5eedence clearwater reviv1ossra05;al;!ca c5l4m1o0Ast05;ca2p1;aq;st;dplMgate;ola;a,sco1tigroup;! systems;ev2i1;ck fil-a,na daily;r0Hy;dbury,pital o1rl's jr;ne;aGbc,eCfAl6mw,ni,o2p,r1;exiteeWos;ei3mbardiJston 1;glo1pizza;be;ng;ack & deckFo2ue c1;roX;ckbuster video,omingda1;le; g1g1;oodriN;cht3e ge0n & jer2rkshire hathaw1;ay;ryH;el;nana republ3s1xt5y5;f,kin robbi1;ns;ic;bXcSdidRerosmith,ig,lLmFnheuser-busEol,ppleAr7s3t&t,v2y1;er;is,on;hland2s1;n,ociated F; o1;il;by4g2m1;co;os; compu2bee1;'s;te1;rs;ch;c,d,erican3t1;!r1;ak; ex1;pre1;ss; 4catel2t1;air;!-luce1;nt;jazeera,qae1;da;as;/dc,a3er,t1;ivisi1;on;demy of scienc0;es;ba,c", + "Demonym": "true¦0:16;1:13;a0Wb0Nc0Cd0Ae09f07g04h02iYjVkTlPmLnIomHpDqatari,rBs7t5u4v3wel0Rz2;am0Fimbabwe0;enezuel0ietnam0H;g9krai1;aiwThai,rinida0Iu2;ni0Qrkmen;a4cot0Ke3ingapoOlovak,oma0Tpa05udRw2y0X;edi0Kiss;negal0Br08;mo0uU;o6us0Lw2;and0;a3eru0Hhilipp0Po2;li0Ertugu06;kist3lesti1na2raguay0;ma1;ani;amiZi2orweP;caragu0geri2;an,en;a3ex0Mo2;ngo0Erocc0;cedo1la2;gasy,y08;a4eb9i2;b2thua1;e0Dy0;o,t02;azakh,eny0o2uwaiti;re0;a2orda1;ma0Bp2;anN;celandic,nd4r2sraeli,ta02vo06;a2iT;ni0qi;i0oneV;aiDin2ondur0unN;di;amDe2hanai0reek,uatemal0;or2rm0;gi0;i2ren7;lipino,n4;cuadoVgyp6ngliJsto1thiopi0urope0;a2ominXut4;niH;a9h6o4roa3ub0ze2;ch;ti0;lom2ngol5;bi0;a6i2;le0n2;ese;lifor1m2na3;bo2eroo1;di0;angladeshi,el8o6r3ul2;gaG;aziBi2;ti2;sh;li2s1;vi0;aru2gi0;si0;fAl7merBngol0r5si0us2;sie,tr2;a2i0;li0;gent2me1;ine;ba1ge2;ri0;ni0;gh0r2;ic0;an", + "Possessive": "true¦anyAh5its,m3noCo1sometBthe0yo1;ir1mselves;ur0;!s;i8y0;!se4;er1i0;mse2s;!s0;!e0;lf;o1t0;hing;ne", + "Currency": "true¦$,aud,bScQdLeurKfJgbp,hkd,iIjpy,kGlEp8r7s3usd,x2y1z0¢,£,¥,ден,лв,руб,฿,₡,₨,€,₭,﷼;lotySł;en,uanR;af,of;h0t5;e0il5;k0q0;elM;iel,oubleLp,upeeL;e2ound st0;er0;lingI;n0soH;ceGn0;ies,y;e0i8;i,mpi7;n,r0wanzaCyatC;!onaBw;ls,nr;ori7ranc9;!o8;en3i2kk,o0;b0ll2;ra5;me4n0rham4;ar3;ad,e0ny;nt1;aht,itcoin0;!s", + "City": "true¦a2Wb26c1Wd1Re1Qf1Og1Ih1Ai18jakar2Hk0Zl0Tm0Gn0Co0ApZquiYrVsLtCuBv8w3y1z0;agreb,uri1Z;ang1Te0okohama;katerin1Hrev34;ars3e2i0rocl3;ckl0Vn0;nipeg,terth0W;llingt1Oxford;aw;a1i0;en2Hlni2Z;lenc2Uncouv0Gr2G;lan bat0Dtrecht;a6bilisi,e5he4i3o2rondheim,u0;nVr0;in,ku;kyo,ronIulouC;anj23l13miso2Jra2A; haJssaloni0X;gucigalpa,hr2Ol av0L;i0llinn,mpe2Bngi07rtu;chu22n2MpT;a3e2h1kopje,t0ydney;ockholm,uttga12;angh1Fenzh1X;o0KvZ;int peters0Ul3n0ppo1F; 0ti1B;jo0salv2;se;v0z0Q;adU;eykjavik,i1o0;me,sario,t25;ga,o de janei17;to;a8e6h5i4o2r0ueb1Qyongya1N;a0etor24;gue;rt0zn24; elizabe3o;ls1Grae24;iladelph1Znom pe07oenix;r0tah tik19;th;lerJr0tr10;is;dessa,s0ttawa;a1Hlo;a2ew 0is;delTtaip0york;ei;goya,nt0Upl0Uv1R;a5e4i3o1u0;mb0Lni0I;nt0scH;evideo,real;l1Mn01skolc;dellín,lbour0S;drid,l5n3r0;ib1se0;ille;or;chest0dalWi0Z;er;mo;a4i1o0vAy01;nd00s angel0F;ege,ma0nz,sbZverpo1;!ss0;ol; pla0Iusan0F;a5hark4i3laipeda,o1rak0uala lump2;ow;be,pavog0sice;ur;ev,ng8;iv;b3mpa0Kndy,ohsiu0Hra0un03;c0j;hi;ncheMstanb0̇zmir;ul;a5e3o0; chi mi1ms,u0;stI;nh;lsin0rakliG;ki;ifa,m0noi,va0A;bu0SiltD;alw4dan3en2hent,iza,othen1raz,ua0;dalaj0Gngzhou;bu0P;eUoa;sk;ay;es,rankfu0;rt;dmont4indhovU;a1ha01oha,u0;blRrb0Eshanbe;e0kar,masc0FugavpiJ;gu,je0;on;a7ebu,h2o0raioJuriti01;lo0nstanJpenhagNrk;gFmbo;enn3i1ristchur0;ch;ang m1c0ttagoL;ago;ai;i0lgary,pe town,rac4;ro;aHeBirminghWogoAr5u0;char3dap3enos air2r0sZ;g0sa;as;es;est;a2isba1usse0;ls;ne;silPtisla0;va;ta;i3lgrade,r0;g1l0n;in;en;ji0rut;ng;ku,n3r0sel;celo1ranquil0;la;na;g1ja lu0;ka;alo0kok;re;aBb9hmedabad,l7m4n2qa1sh0thens,uckland;dod,gabat;ba;k0twerp;ara;m5s0;terd0;am;exandr0maty;ia;idj0u dhabi;an;lbo1rh0;us;rg", + "Abbreviation": "true¦a08b05cZdXeUfSgRhQiPjNkanMlKmGnEoDpCque,rAs6t4u3v2w0;is0y00;!c;a,s,t;niv,safa,t;ce,e0;nn,x;ask,e1fc,gt,ir,r,t,u0;pt,rg;nDp0;!t;d,e0;pAs,v;a,d,ennGhd,l,rof,vt;ct,kla,nt,p,rd;eb0ov;!r;a2d,essrs,i1lle,me,r5s0t;!tr;nn,ster;!j,r;it,lb,t0;!d;!s;an,r,u0;l,n;a,da,e,nc;on,wy;a,en,ov;eb,l0t,y;!a;g,s1tc,x0;!p;p,q;ak,e0ist,r;c,pt,t;a3ca,l,m2o0pl,res,t;!l0m1nn,rp;!o;dr;!l0pt;!if;a,c,l1r0;ig,os;!dg,vd;d3l2pr,r1ss0tty,ug,ve;n,t;c,iz;!ta;!j,m,v", + "Place": "true¦a07b05cZdYeXfVgRhQiOjfk,kMlKmHneEoDp9que,rd,s8t5u4v3w0yyz;is1y0;!o;!c;a,t;pYsafa,t;e1he 0;bronx,hamptons;nn,x;ask,fo,oho,t,under6yd;a2e1h0;l,x;k,nnK;!cifX;kla,nt;b1w eng0;land;!r;a1co,i0t,uc;dKnn;libu,nhattS;a0gw,hr;s,x;an0ul;!s;a0cn,da,ndianMst;!x;arlem,kg,nd,wy;a2re0;at 0enwich;britain,lak6;!y village;co,l0ra;!a;urope,verglad2;ak,en,fw,ist,own4xb;al4dg,gk,hina3l2o1r0t;es;lo,nn;!t;town;!if;cn,e0kk,lvd,rooklyn;l air,verly hills;frica,lta,m5ntarct2r1sia,tl0ve;!ant1;ct0iz;ic0; oce0;an;ericas,s", + "Country": "true¦0:38;1:2L;a2Wb2Dc21d1Xe1Rf1Lg1Bh19i13j11k0Zl0Um0Gn05om3CpZqat1JrXsKtCu6v4wal3yemTz2;a24imbabwe;es,lis and futu2X;a2enezue31ietnam;nuatu,tican city;.5gTkraiZnited 3ruXs2zbeE;a,sr;arab emirat0Kkingdom,states2;! of am2X;k.,s.2; 27a.;a7haBimor-les0Bo6rinidad4u2;nis0rk2valu;ey,me2Xs and caic1T; and 2-2;toba1J;go,kel0Ynga;iw2Vji2nz2R;ki2T;aCcotl1eBi8lov7o5pa2Bri lanka,u4w2yr0;az2ed9itzerl1;il1;d2Qriname;lomon1Vmal0uth 2;afr2IkLsud2O;ak0en0;erra leoEn2;gapo1Wt maart2;en;negKrb0ychellY;int 2moa,n marino,udi arab0;hele24luc0mart1Z;epublic of ir0Com2Cuss0w2;an25;a3eHhilippinTitcairn1Ko2uerto riM;l1rtugE;ki2Bl3nama,pua new0Tra2;gu6;au,esti2;ne;aAe8i6or2;folk1Gth3w2;ay; k2ern mariana1B;or0M;caragua,ger2ue;!ia;p2ther18w zeal1;al;mib0u2;ru;a6exi5icro09o2yanm04;ldova,n2roc4zamb9;a3gol0t2;enegro,serrat;co;c9dagascZl6r4urit3yot2;te;an0i14;shall0Vtin2;ique;a3div2i,ta;es;wi,ys0;ao,ed00;a5e4i2uxembourg;b2echtenste10thu1E;er0ya;ban0Gsotho;os,tv0;azakh1De2iriba02osovo,uwait,yrgyz1D;eling0Jnya;a2erF;ma15p1B;c6nd5r3s2taly,vory coast;le of m19rael;a2el1;n,q;ia,oI;el1;aiSon2ungary;dur0Mg kong;aAermany,ha0Pibralt9re7u2;a5ern4inea2ya0O;!-biss2;au;sey;deloupe,m,tema0P;e2na0M;ce,nl1;ar;bTmb0;a6i5r2;ance,ench 2;guia0Dpoly2;nes0;ji,nl1;lklandTroeT;ast tim6cu5gypt,l salv5ngl1quatorial3ritr4st2thiop0;on0; guin2;ea;ad2;or;enmark,jibou4ominica3r con2;go;!n B;ti;aAentral african 9h7o4roat0u3yprQzech2; 8ia;ba,racao;c3lo2morPngo-brazzaville,okFsta r03te d'ivoiK;mb0;osD;i2ristmasF;le,na;republic;m2naTpe verde,yman9;bod0ero2;on;aFeChut00o8r4u2;lgar0r2;kina faso,ma,undi;azil,itish 2unei;virgin2; is2;lands;liv0nai4snia and herzegoviGtswaGuvet2; isl1;and;re;l2n7rmuF;ar2gium,ize;us;h3ngladesh,rbad2;os;am3ra2;in;as;fghaFlCmAn5r3ustr2zerbaijH;al0ia;genti2men0uba;na;dorra,g4t2;arct6igua and barbu2;da;o2uil2;la;er2;ica;b2ger0;an0;ia;ni2;st2;an", + "Region": "true¦0:1U;a20b1Sc1Id1Des1Cf19g13h10i0Xj0Vk0Tl0Qm0FnZoXpSqPrMsDtAut9v6w3y1zacatec22;o05u1;cat18kZ;a1est vi4isconsin,yomi14;rwick0shington1;! dc;er2i1;rgin1S;acruz,mont;ah,tar pradesh;a2e1laxca1DuscaA;nnessee,x1R;bas0Kmaulip1QsmJ;a6i4o2taf0Ou1ylh13;ffVrr00s0Y;me10no1Auth 1;cSdR;ber1Ic1naloa;hu0Sily;n2skatchew0Rxo1;ny; luis potosi,ta catari1I;a1hode7;j1ngp02;asth0Mshahi;inghai,u1;e1intana roo;bec,ensWreta0E;ara4e2rince edward1; isU;i,nnsylv1rnambu02;an14;!na;axa0Ndisha,h1klaho1Bntar1reg4x04;io;ayarit,eBo3u1;evo le1nav0L;on;r1tt0Rva scot0X;f6mandy,th1; 1ampton0;c3d2yo1;rk0;ako0Y;aroli0V;olk;bras0Xva01w1; 2foundland1;! and labrador;brunswick,hamp0jers1mexiJyork state;ey;a6i2o1;nta0Nrelos;ch3dlanBn2ss1;issippi,ouri;as geraGneso0M;igQoacQ;dhya,harasht04ine,ni3r1ssachusetts;anhao,y1;land;p1toba;ur;anca0e1incoln0ouis8;e1iH;ds;a1entucky,hul0A;ns08rnata0Dshmir;alis1iangxi;co;daho,llino2nd1owa;ia05;is;a2ert1idalEunA;ford0;mp0waii;ansu,eorgWlou5u1;an2erre1izhou,jarat;ro;ajuato,gdo1;ng;cester0;lori2uji1;an;da;sex;e4o2uran1;go;rs1;et;lawaErby0;a8ea7hi6o1umbrH;ahui4l3nnectic2rsi1ventry;ca;ut;iMorado;la;apEhuahua;ra;l8m1;bridge0peche;a5r4uck1;ingham0;shi1;re;emen,itish columb3;h2ja cal1sque,var2;iforn1;ia;guascalientes,l4r1;izo2kans1;as;na;a2ber1;ta;ba2s1;ka;ma", + "FemaleName": "true¦0:FY;1:G2;2:FR;3:FD;4:FC;5:EP;6:ER;7:FS;8:GF;9:EZ;A:GB;B:E5;C:FO;D:FL;E:G8;F:EG;aE2bD4cB8dAIe9Gf91g8Hh83i7Sj6Uk60l4Om38n2To2Qp2Fqu2Er1Os0Qt04ursu6vUwOyLzG;aJeHoG;e,la,ra;lGna;da,ma;da,ra;as7EeHol1TvG;et5onB9;le0sen3;an9endBNhiB4iG;lInG;if3AniGo0;e,f39;a,helmi0lGma;a,ow;aMeJiG;cHviG;an9XenG1;kCZtor3;da,l8Vnus,rG;a,nGoniD2;a,iDC;leGnesEC;nDLrG;i1y;aSePhNiMoJrGu6y4;acG3iGu0E;c3na,sG;h9Mta;nHrG;a,i;i9Jya;a5IffaCGna,s7;al3eGomasi0;a,l8Go6Xres1;g7Uo6WrHssG;!a,ie;eFi,ri8;bNliMmKnIrHs7tGwa0;ia0um;a,yn;iGya;a,ka,s7;a4e4iGmCAra;!ka;a,t7;at7it7;a05carlet2Ye04hUiSkye,oQtMuHyG;bFJlvi1;e,sHzG;an2Tet5ie,y;anGi8;!a,e,nG;aDe;aIeG;fGl3DphG;an2;cF8r6;f3nGphi1;d4ia,ja,ya;er4lv3mon1nGobh75;dy;aKeGirlBLo0y6;ba,e0i6lIrG;iGrBPyl;!d70;ia,lBV;ki4nIrHu0w0yG;la,na;i,leAon,ron;a,da,ia,nGon;a,on;l5Yre0;bMdLi9lKmIndHrGs7vannaD;aDi0;ra,y;aGi4;nt7ra;lBNome;e,ie;in1ri0;a02eXhViToHuG;by,thBK;bQcPlOnNsHwe0xG;an94ie,y;aHeGie,lE;ann8ll1marBFtB;!lGnn1;iGyn;e,nG;a,d7W;da,i,na;an9;hel53io;bin,erByn;a,cGkki,na,ta;helBZki;ea,iannDXoG;da,n12;an0bIgi0i0nGta,y0;aGee;!e,ta;a,eG;cARkaD;chGe,i0mo0n5EquCDvCy0;aCCelGi9;!e,le;een2ia0;aMeLhJoIrG;iGudenAW;scil1Uyamva9;lly,rt3;ilome0oebe,ylG;is,lis;arl,ggy,nelope,r6t4;ige,m0Fn4Oo6rvaBBtHulG;a,et5in1;ricGsy,tA8;a,e,ia;ctav3deHfAWlGphAW;a,ga,iv3;l3t5;aQePiJoGy6;eHrG;aDeCma;ll1mi;aKcIkGla,na,s7ta;iGki;!ta;hoB2k8BolG;a,eBH;!mh;l7Tna,risF;dIi5PnHo23taG;li1s7;cy,et5;eAiCO;a01ckenz2eViLoIrignayani,uriBGyG;a,rG;a,na,tAS;i4ll9XnG;a,iG;ca,ka,qB4;a,chOkaNlJmi,nIrGtzi;aGiam;!n9;a,dy,erva,h,n2;a,dIi9JlG;iGy;cent,e;red;!e6;ae6el3G;ag4KgKi,lHrG;edi61isFyl;an2iGliF;nGsAM;a,da;!an,han;b08c9Ed06e,g04i03l01nZrKtJuHv6Sx87yGz2;a,bell,ra;de,rG;a,eC;h75il9t2;a,cSgOiJjor2l6In2s7tIyG;!aGbe5QjaAlou;m,n9S;a,ha,i0;!aIbALeHja,lEna,sGt53;!a,ol,sa;!l06;!h,m,nG;!a,e,n1;arIeHie,oGr3Kueri5;!t;!ry;et3IiB;elGi61y;a,l1;dGon,ue6;akranBy;iGlo36;a,ka,n9;a,re,s2;daGg2;!l2W;alEd2elGge,isBGon0;eiAin1yn;el,le;a0Ie08iWoQuKyG;d3la,nG;!a,dHe9SnGsAQ;!a,e9R;a,sAO;aB1cJelIiFlHna,pGz;e,iB;a,u;a,la;iGy;a2Ae,l25n9;is,l1GrHtt2uG;el6is1;aIeHi8na,rG;a6Zi8;lei,n1tB;!in1;aQbPd3lLnIsHv3zG;!a,be4Ket5z2;a,et5;a,dG;a,sGy;ay,ey,i,y;a,iaIlG;iGy;a8Ge;!n4F;b7Terty;!n5R;aNda,e0iLla,nKoIslARtGx2;iGt2;c3t3;la,nGra;a,ie,o4;a,or1;a,gh,laG;!ni;!h,nG;a,d4e,n4N;cNdon7Si6kes7na,rMtKurIvHxGy6;mi;ern1in3;a,eGie,yn;l,n;as7is7oG;nya,ya;a,isF;ey,ie,y;aZeUhadija,iMoLrIyG;lGra;a,ee,ie;istGy5B;a,en,iGy;!e,n48;ri,urtn9A;aMerLl99mIrGzzy;a,stG;en,in;!berlG;eGi,y;e,y;a,stC;!na,ra;el6PiJlInHrG;a,i,ri;d4na;ey,i,l9Qs2y;ra,s7;c8Wi5XlOma6nyakumari,rMss5LtJviByG;!e,lG;a,eG;e,i78;a5EeHhGi3PlEri0y;ar5Cer5Cie,leCr9Fy;!lyn73;a,en,iGl4Uyn;!ma,n31sF;ei72i,l2;a04eVilToMuG;anKdJliGst56;aHeGsF;!nAt0W;!n8X;i2Ry;a,iB;!anLcelEd5Vel71han6IlJni,sHva0yG;a,ce;eGie;fi0lEph4X;eGie;en,n1;!a,e,n36;!i10lG;!i0Z;anLle0nIrHsG;i5Qsi5Q;i,ri;!a,el6Pif1RnG;a,et5iGy;!e,f1P;a,e72iHnG;a,e71iG;e,n1;cLd1mi,nHqueliAsmin2Uvie4yAzG;min8;a8eHiG;ce,e,n1s;!lGsFt06;e,le;inHk2lEquelG;in1yn;da,ta;lPmNnMo0rLsHvaG;!na;aHiGob6U;do4;!belGdo4;!a,e,l2G;en1i0ma;a,di4es,gr5R;el9ogG;en1;a,eAia0o0se;aNeKilHoGyacin1N;ll2rten1H;aHdGlaH;a,egard;ry;ath0WiHlGnrietBrmiAst0W;en24ga;di;il75lKnJrGtt2yl75z6D;iGmo4Fri4G;etG;!te;aDnaD;ey,l2;aYeTiOlMold12rIwG;enGyne18;!dolE;acHetGisel9;a,chC;e,ieG;!la;adys,enGor3yn1Y;a,da,na;aJgi,lHna,ov71selG;a,e,le;da,liG;an;!n0;mYnIorgHrG;ald35i,m2Stru73;et5i5T;a,eGna;s1Nvieve;briel3Fil,le,rnet,yle;aReOio0loMrG;anHe9iG;da,e9;!cG;esHiGoi0G;n1s3V;!ca;!rG;a,en43;lHrnG;!an9;ec3ic3;rHtiGy8;ma;ah,rah;d0FileCkBl00mUn4ArRsMtLuKvG;aIelHiG;e,ta;in0Ayn;!ngel2H;geni1la,ni3R;h52ta;meral9peranJtG;eHhGrel6;er;l2Pr;za;iGma,nest29yn;cGka,n;a,ka;eJilImG;aGie,y;!liA;ee,i1y;lGrald;da,y;aTeRiMlLma,no4oJsIvG;a,iG;na,ra;a,ie;iGuiG;se;a,en,ie,y;a0c3da,nJsGzaH;aGe;!beG;th;!a,or;anor,nG;!a;in1na;en,iGna,wi0;e,th;aWeKiJoGul2U;lor51miniq3Yn30rGtt2;a,eCis,la,othGthy;ea,y;an09naDonAx2;anPbOde,eNiLja,lImetr3nGsir4U;a,iG;ce,se;a,iHla,orGphiA;es,is;a,l5J;dGrdG;re;!d4Mna;!b2CoraDra;a,d4nG;!a,e;hl3i0mMnKphn1rHvi1WyG;le,na;a,by,cHia,lG;a,en1;ey,ie;a,et5iG;!ca,el1Aka;arGia;is;a0Qe0Mh04i02lUoJrHynG;di,th3;istGy04;al,i0;lOnLrHurG;tn1D;aId28iGn28riA;!nG;a,e,n1;!l1S;n2sG;tanGuelo;ce,za;eGleC;en,t5;aIeoHotG;il4B;!pat4;ir8rIudG;et5iG;a,ne;a,e,iG;ce,sX;a4er4ndG;i,y;aPeMloe,rG;isHyG;stal;sy,tG;aHen,iGy;!an1e,n1;!l;lseHrG;!i8yl;a,y;nLrG;isJlHmG;aiA;a,eGot5;n1t5;!sa;d4el1PtG;al,el1O;cHlG;es5i3F;el3ilG;e,ia,y;iYlXmilWndVrNsLtGy6;aJeIhGri0;erGleCrEy;in1;ri0;li0ri0;a2GsG;a2Fie;a,iMlKmeIolHrG;ie,ol;!e,in1yn;lGn;!a,la;a,eGie,y;ne,y;na,sF;a0Di0D;a,e,l1;isBl2;tlG;in,yn;arb0CeYianXlVoTrG;andRePiIoHyG;an0nn;nwEok8;an2NdgKg0ItG;n27tG;!aHnG;ey,i,y;ny;etG;!t8;an0e,nG;da,na;i8y;bbi8nG;iBn2;ancGossom,ythe;a,he;ca;aRcky,lin9niBrNssMtIulaDvG;!erlG;ey,y;hHsy,tG;e,i0Zy8;!anG;ie,y;!ie;nGt7yl;adHiG;ce;et5iA;!triG;ce,z;a4ie,ra;aliy29b24d1Lg1Hi19l0Sm0Nn01rWsNthe0uJvIyG;anGes7;a,na;a,r25;drIgusHrG;el3;ti0;a,ey,i,y;hHtrG;id;aKlGt1P;eHi8yG;!n;e,iGy;gh;!nG;ti;iIleHpiB;ta;en,n1t5;an19elG;le;aYdWeUgQiOja,nHtoGya;inet5n3;!aJeHiGmI;e,ka;!mGt5;ar2;!belHliFmT;sa;!le;ka,sGta;a,sa;elGie;a,iG;a,ca,n1qG;ue;!t5;te;je6rea;la;!bHmGstas3;ar3;el;aIberHel3iGy;e,na;!ly;l3n9;da;aTba,eNiKlIma,yG;a,c3sG;a,on,sa;iGys0J;e,s0I;a,cHna,sGza;a,ha,on,sa;e,ia;c3is7jaIna,ssaIxG;aGia;!nd4;nd4;ra;ia;i0nHyG;ah,na;a,is,naD;c7da,leCmLnslKsG;haDlG;inGyW;g,n;!h;ey;ee;en;at7g2nG;es;ie;ha;aVdiSelLrG;eIiG;anLenG;a,e,ne;an0;na;aKeJiHyG;nn;a,n1;a,e;!ne;!iG;de;e,lEsG;on;yn;!lG;iAyn;ne;agaJbHiG;!gaI;ey,i8y;!e;il;ah", + "WeekDay": "true¦fri4mon4s2t1wed0;!nesd4;hurs2ues2;at0un1;!urd1;!d0;ay0;!s", + "Month": "true¦aBdec9feb7j2mar,nov9oct1sep0;!t8;!o8;an3u0;l1n0;!e;!y;!u1;!ru0;ary;!em0;ber;pr1ug0;!ust;!il", + "FirstName": "true¦aEblair,cCdevBj8k6lashawn,m3nelly,quinn,re2sh0;ay,e0iloh;a,lby;g1ne;ar1el,org0;an;ion,lo;as8e0r9;ls7nyatta,rry;am0ess1ude;ie,m0;ie;an,on;as0heyenne;ey,sidy;lex1ndra,ubr0;ey;is", + "LastName": "true¦0:34;1:39;2:3B;3:2Y;4:2E;5:30;a3Bb31c2Od2Ee2Bf25g1Zh1Pi1Kj1Ek17l0Zm0Nn0Jo0Gp05rYsMtHvFwCxBy8zh6;a6ou,u;ng,o;a6eun2Uoshi1Kun;ma6ng;da,guc1Zmo27sh21zaR;iao,u;a7eb0il6o3right,u;li3Bs1;gn0lk0ng,tanabe;a6ivaldi;ssilj37zqu2;a9h8i2Go7r6sui,urn0;an,ynisJ;lst0Prr1Uth;at1Uomps1;kah0Vnaka,ylor;aEchDeChimizu,iBmiAo9t7u6zabo;ar2lliv2AzuE;a6ein0;l23rm0;sa,u3;rn4th;lva,mmo24ngh;mjon4rrano;midt,neid0ulz;ito,n7sa6to;ki;ch2dLtos,z;amBeag1Zi9o7u6;bio,iz,sD;b6dri1MgIj0Tme24osevelt,ssi,ux;erts,ins1;c6ve0F;ci,hards1;ir2os;aEeAh8ic6ow20;as6hl0;so;a6illips;m,n1T;ders5et8r7t6;e0Nr4;ez,ry;ers;h21rk0t6vl4;el,te0J;baBg0Blivei01r6;t6w1O;ega,iz;a6eils1guy5ix1owak,ym1E;gy,ka6var1K;ji6muW;ma;aEeCiBo8u6;ll0n6rr0Bssolini,ñ6;oz;lina,oKr6zart;al0Me6r0U;au,no;hhail4ll0;rci0ssi6y0;!er;eWmmad4r6tsu07;in6tin2;!o;aCe8i6op2uo;!n6u;coln,dholm;fe7n0Qr6w0J;oy;bv6v6;re;mmy,rs5u;aBennedy,imuAle0Lo8u7wo6;k,n;mar,znets4;bay6vacs;asY;ra;hn,rl9to,ur,zl4;aAen9ha3imen2o6u3;h6nYu3;an6ns1;ss1;ki0Es5;cks1nsse0D;glesi9ke8noue,shik7to,vano6;u,v;awa;da;as;aBe8itchcock,o7u6;!a3b0ghNynh;a3ffmann,rvat;mingw7nde6rN;rs1;ay;ns5rrQs7y6;asDes;an4hi6;moJ;a9il,o8r7u6;o,tierr2;ayli3ub0;m2nzal2;nd6o,rcia;hi;erAis9lor8o7uj6;ita;st0urni0;es;ch0;nand2;d7insteHsposi6vaL;to;is1wards;aCeBi9omin8u6;bo6rand;is;gu2;az,mitr4;ov;lgado,vi;nkula,rw7vi6;es,s;in;aFhBlarkAo6;h5l6op0rbyn,x;em7li6;ns;an;!e;an8e7iu,o6ristens5u3we;i,ng,u3w,y;!n,on6u3;!g;mpb7rt0st6;ro;ell;aBe8ha3lanco,oyko,r6yrne;ooks,yant;ng;ck7ethov5nnett;en;er,ham;ch,h8iley,rn6;es,i0;er;k,ng;dDl9nd6;ers6rA;en,on,s1;on;eks7iy8var2;ez;ej6;ev;ams", + "MaleName": "true¦0:CE;1:BL;2:C2;3:BT;4:B5;5:9V;6:BZ;7:AT;8:BD;9:AX;A:AO;aB4bA8c97d87e7Gf6Yg6Gh5Wi5Ij4Lk4Bl3Rm2Pn2Eo28p22qu20r1As0Qt06u05v00wNxavi3yGzB;aBor0;cBh8Ine;hCkB;!aB1;ar51eB0;ass2i,oCuB;sDu25;nEsDusB;oBsC;uf;ef;at0g;aJeHiCoByaAP;lfgang,odrow;lBn1O;bDey,frBJlB;aA5iB;am,e,s;e89ur;i,nde5sB;!l7t1;de,lCrr6yB;l1ne;lBt3;a93y;aEern1iB;cCha0nceBrg9Bva0;!nt;ente,t5A;lentin49n8Yughn;lyss4Msm0;aTeOhKiIoErCyB;!l3ro8s1;av9QeBist0oy,um0;nt9Iv54y;bDd7XmBny;!as,mBoharu;aAYie,y;i83y;mBt9;!my,othy;adDeoCia7DomB;!as;!do7M;!de9;dErB;en8HrB;an8GeBy;ll,n8F;!dy;dgh,ic9Tnn3req,ts45;aRcotPeNhJiHoFpenc3tBur1Oylve8Hzym1;anDeBua7B;f0phAFvBwa7A;e57ie;!islaw,l7;lom1nA3uB;leyma8ta;dBl7Jm1;!n7;aDeB;lBrm0;d1t1;h6Sne,qu0Uun,wn,y8;aBbasti0k1Xl41rg40th,ymo9I;m9n;!tB;!ie,y;lCmBnti21q4Iul;!mAu4;ik,vato6V;aWeShe92iOoFuCyB;an,ou;b6LdCf9pe6QssB;!elAI;ol2Uy;an,bIcHdGel,geFh0landA9mEnDry,sCyB;!ce;coe,s;!a95nA;an,eo;l3Jr;e4Qg3n7olfo,ri68;co,ky;bAe9U;cBl7;ar5Oc5NhCkBo;!ey,ie,y;a85ie;gCid,ub6x,yBza;ansh,nS;g8WiB;na8Ss;ch5Yfa4lDmCndBpha4sh6Uul,ymo70;al9Yol2By;i9Ion;f,ph;ent2inB;cy,t1;aFeDhilCier62ol,reB;st1;!ip,lip;d9Brcy,tB;ar,e2V;b3Sdra6Ft44ul;ctav2Vliv3m96rFsCtBum8Uw6;is,to;aCc8SvB;al52;ma;i,l49vJ;athJeHiDoB;aBel,l0ma0r2X;h,m;cCg4i3IkB;h6Uola;hol5XkBol5X;!ol5W;al,d,il,ls1vB;il50;anBy;!a4i4;aWeTiKoFuCyB;l21r1;hamCr5ZstaB;fa,p4G;ed,mF;dibo,e,hamDis1XntCsBussa;es,he;e,y;ad,ed,mB;ad,ed;cGgu4kElDnCtchB;!e5;a78ik;house,o03t1;e,olB;aj;ah,hBk7;a4eB;al,l;hClv2rB;le,ri5v2;di,met;ck,hNlLmOnu4rHs1tDuricCxB;!imilian8Cwe5;e,io;eo,hCi52tB;!eo,hew,ia;eBis;us,w;cDio,k86lCqu6Gsha5tBv2;i2Hy;in,on;!el,oKus;achBcolm,ik;ai,y;amBdi,moud;adB;ou;aReNiMlo2RoIuCyB;le,nd1;cEiDkBth3;aBe;!s;gi,s;as,iaB;no;g0nn6RrenDuBwe5;!iB;e,s;!zo;am,on4;a7Bevi,la4SnDoBst3vi;!nB;!a60el;!ny;mCnBr67ur4Twr4T;ce,d1;ar,o4N;aIeDhaled,iBrist4Vu48y3B;er0p,rB;by,k,ollos;en0iEnBrmit,v2;!dCnBt5C;e0Yy;a5ri4N;r,th;na68rBthem;im,l;aYeQiOoDuB;an,liBst2;an,o,us;aqu2eJhnInGrEsB;eChBi7Bue;!ua;!ph;dBge;an,i,on;!aBny;h,s,th4X;!ath4Wie,nA;!l,sBy;ph;an,e,mB;!mA;d,ffGrDsB;sBus;!e;a5JemCmai8oBry;me,ni0O;i6Uy;!e58rB;ey,y;cHd6kGmFrDsCvi3yB;!d6s1;on,p3;ed,od,rBv4M;e4Zod;al,es,is1;e,ob,ub;k,ob,quB;es;aNbrahMchika,gKkeJlija,nuIrGsDtBv0;ai,sB;uki;aBha0i6Fma4sac;ac,iaB;h,s;a,vinBw2;!g;k,nngu52;!r;nacBor;io;im;in,n;aJeFina4VoDuByd56;be25gBmber4CsD;h,o;m3ra33sBwa3X;se2;aDctCitCn4ErB;be20m0;or;th;bKlJmza,nIo,rDsCyB;a43d6;an,s0;lEo4FrDuBv7;hi40ki,tB;a,o;is1y;an,ey;k,s;!im;ib;aQeMiLlenKoIrEuB;illerCsB;!tavo;mo;aDegBov3;!g,orB;io,y;dy,h57nt;nzaBrd1;lo;!n;lbe4Qno,ovan4R;ne,oDrB;aBry;ld,rd4U;ffr7rge;bri4l6rBv2;la1Zr3Eth,y;aReNiLlJorr0IrB;anDedBitz;!dAeBri24;ri23;cDkB;!ie,lB;in,yn;esJisB;!co,zek;etch3oB;yd;d4lBonn;ip;deriDliCng,rnB;an01;pe,x;co;bi0di;arZdUfrTit0lNmGnFo2rCsteb0th0uge8vBym6zra;an,ere2V;gi,iCnBrol,v2w2;est45ie;c07k;och,rique,zo;aGerFiCmB;aFe2P;lCrB;!h0;!io;s1y;nu4;be09d1iEliDmCt1viBwood;n,s;er,o;ot1Ts;!as,j43sB;ha;a2en;!dAg32mEuCwB;a25in;arB;do;o0Su0S;l,nB;est;aYeOiLoErDuCwByl0;ay8ight;a8dl7nc0st2;ag0ew;minFnDri0ugCyB;le;!l03;!a29nBov0;e5ie,y;go,icB;!k;armuCeBll1on,rk;go;id;anIj0lbeHmetri9nFon,rEsDvCwBxt3;ay8ey;en,in;hawn,mo08;ek,ri0F;is,nBv3;is,y;rt;!dB;re;lKmInHrDvB;e,iB;!d;en,iDne5rByl;eBin,yl;l2Vn;n,o,us;!e,i4ny;iBon;an,en,on;e,lB;as;a06e04hWiar0lLoGrEuCyrB;il,us;rtB;!is;aBistobal;ig;dy,lEnCrB;ey,neli9y;or,rB;ad;by,e,in,l2t1;aGeDiByI;fBnt;fo0Ct1;meCt9velaB;nd;nt;rDuCyB;!t1;de;enB;ce;aFeErisCuB;ck;!tB;i0oph3;st3;d,rlBs;eBie;s,y;cBdric,s11;il;lEmer1rB;ey,lCro5y;ll;!os,t1;eb,v2;ar02eUilTlaSoPrCuByr1;ddy,rtI;aJeEiDuCyB;an,ce,on;ce,no;an,ce;nCtB;!t;dCtB;!on;an,on;dCndB;en,on;!foBl7y;rd;bCrByd;is;!by;i8ke;al,lA;nFrBshoi;at,nCtB;!r10;aBie;rd0S;!edict,iCjam2nA;ie,y;to;n7rBt;eBy;tt;ey;ar0Xb0Nd0Jgust2hm0Gid6ja0ElZmXnPputsiOrFsaEuCveBya0ziz;ry;gust9st2;us;hi;aIchHi4jun,maFnDon,tBy0;hBu06;ur;av,oB;ld;an,nd0A;el;ie;ta;aq;dGgel05tB;hoEoB;i8nB;!i02y;ne;ny;reBy;!as,s,w;ir,mBos;ar;an,beOd6eIfFi,lEonDphonHt1vB;aMin;on;so,zo;an,en;onCrB;edP;so;c,jaEksandDssaExB;!and3;er;ar,er;ndB;ro;rtH;ni;en;ad,eB;d,t;in;aColfBri0vik;!o;mBn;!a;dFeEraCuB;!bakr,lfazl;hBm;am;!l;allEel,oulaye,ulB;!lCrahm0;an;ah,o;ah;av,on", + "Person": "true¦ashton kutchSbRcMdKeIgastNhGinez,jEkDleCmBnettJoAp8r4s3t2v0;a0irgin maG;lentino rossi,n go3;heresa may,iger woods,yra banks;addam hussain,carlett johanssJlobodan milosevic,uB;ay romano,eese witherspoIo1ush limbau0;gh;d stewart,nald0;inho,o;a0ipJ;lmIris hiltD;prah winfrFra;essiaen,itt romnEubarek;bron james,e;anye west,iefer sutherland,obe bryant;aime,effers8k rowli0;ng;alle ber0itlBulk hogan;ry;ff0meril lagasse,zekiel;ie;a0enzel washingt2ick wolf;lt1nte;ar1lint0ruz;on;dinal wols1son0;! palm2;ey;arack obama,rock;er", + "Verb": "true¦awak9born,cannot,fr8g7h5k3le2m1s0wors9;e8h3;ake sure,sg;ngth6ss6;eep tabs,n0;own;as0e2;!t2;iv1onna;ight0;en", + "PhrasalVerb": "true¦0:71;1:6P;2:7D;3:73;4:6I;5:7G;6:75;7:6O;8:6B;9:6C;A:5H;B:70;C:6Z;a7Gb62c5Cd59e57f45g3Nh37iron0j33k2Yl2Km2Bn29o27p1Pr1Es09tQuOvacuum 1wGyammerCzD;eroAip EonD;e0k0;by,up;aJeGhFiEorDrit52;d 1k2Q;mp0n49pe0r8s8;eel Bip 7K;aEiD;gh 06rd0;n Br 3C;it 5Jk8lk6rm 0Qsh 73t66v4O;rgeCsD;e 9herA;aRePhNiJoHrFuDype 0N;ckArn D;d2in,o3Fup;ade YiDot0y 32;ckle67p 79;ne66p Ds4C;d2o6Kup;ck FdEe Dgh5Sme0p o0Dre0;aw3ba4d2in,up;e5Jy 1;by,o6U;ink Drow 5U;ba4ov7up;aDe 4Hll4N;m 1r W;ckCke Elk D;ov7u4N;aDba4d2in,o30up;ba4ft7p4Sw3;a0Gc0Fe09h05i02lYmXnWoVpSquare RtJuHwD;earFiD;ngEtch D;aw3ba4o6O; by;ck Dit 1m 1ss0;in,up;aIe0RiHoFrD;aigh1LiD;ke 5Xn2X;p Drm1O;by,in,o6A;n2Yr 1tc3H;c2Xmp0nd Dr6Gve6y 1;ba4d2up;d2o66up;ar2Uell0ill4TlErDurC;ingCuc8;a32it 3T;be4Brt0;ap 4Dow B;ash 4Yoke0;eep EiDow 9;c3Mp 1;in,oD;ff,v7;gn Eng2Yt Dz8;d2o5up;in,o5up;aFoDu4E;ot Dut0w 5W;aw3ba4f36o5Q;c2EdeAk4Rve6;e Hll0nd GtD; Dtl42;d2in,o5upD;!on;aw3ba4d2in,o1Xup;o5to;al4Kout0rap4K;il6v8;at0eKiJoGuD;b 4Dle0n Dstl8;aDba4d2in52o3Ft2Zu3D;c1Ww3;ot EuD;g2Jnd6;a1Wf2Qo5;ng 4Np6;aDel6inAnt0;c4Xd D;o2Su0C;aQePiOlMoKrHsyc29uD;ll Ft D;aDba4d2in,o1Gt33up;p38w3;ap37d2in,o5t31up;attleCess EiGoD;p 1;ah1Gon;iDp 52re3Lur44wer 52;nt0;ay3YuD;gAmp 9;ck 52g0leCn 9p3V;el 46ncilA;c3Oir 2Hn0ss FtEy D;ba4o4Q; d2c1X;aw3ba4o11;pDw3J;e3It B;arrow3Serd0oD;d6te3R;aJeHiGoEuD;ddl8ll36;c16p 1uth6ve D;al3Ad2in,o5up;ss0x 1;asur8lt 9ss D;a19up;ke Dn 9r2Zs1Kx0;do,o3Xup;aOeMiHoDuck0;a16c36g 0AoDse0;k Dse34;aft7ba4d2forw2Ain3Vov7uD;nd7p;e GghtFnEsDv1T;ten 4D;e 1k 1; 1e2Y;ar43d2;av1Ht 2YvelD; o3L;p 1sh DtchCugh6y1U;in3Lo5;eEick6nock D;d2o3H;eDyA;l2Hp D;aw3ba4d2fSin,o05to,up;aFoEuD;ic8mpA;ke2St2W;c31zz 1;aPeKiHoEuD;nker2Ts0U;lDneArse2O;d De 1;ba4d2fast,oZup;de Et D;ba4on,up;aw3o5;aDlp0;d Fr Dt 1;fDof;rom;in,oO;cZm 1nDve it;d Dg 27kerF;d2in,o5;aReLive Jloss1VoFrEunD; f0M;in39ow 23; Dof 0U;aEb17it,oDr35t0Ou12;ff,n,v7;bo5ft7hJw3;aw3ba4d2in,oDup,w3;ff,n,ut;a17ek0t D;aEb11d2oDr2Zup;ff,n,ut,v7;cEhDl1Pr2Xt,w3;ead;ross;d aEnD;g 1;bo5;a08e01iRlNoJrFuD;cDel 1;k 1;eEighten DownCy 1;aw3o2L;eDshe1G; 1z8;lFol D;aDwi19;bo5r2I;d 9;aEeDip0;sh0;g 9ke0mDrD;e 2K;gLlJnHrFsEzzD;le0;h 2H;e Dm 1;aw3ba4up;d0isD;h 1;e Dl 11;aw3fI;ht ba4ure0;eInEsD;s 1;cFd D;fDo1X;or;e B;dQl 1;cHll Drm0t0O;apYbFd2in,oEtD;hrough;ff,ut,v7;a4ehi1S;e E;at0dge0nd Dy8;o1Mup;o09rD;ess 9op D;aw3bNin,o15;aShPlean 9oDross But 0T;me FoEuntD; o1M;k 1l6;aJbIforGin,oFtEuD;nd7;ogeth7;ut,v7;th,wD;ard;a4y;pDr19w3;art;eDipA;ck BeD;r 1;lJncel0rGsFtch EveA; in;o16up;h Bt6;ry EvD;e V;aw3o12;l Dm02;aDba4d2o10up;r0Vw3;a0He08l01oSrHuD;bbleFcklTilZlEndlTrn 05tDy 10zz6;t B;k 9; ov7;anMeaKiDush6;ghHng D;aEba4d2forDin,o5up;th;bo5lDr0Lw3;ong;teD;n 1;k D;d2in,o5up;ch0;arKgJil 9n8oGssFttlEunce Dx B;aw3ba4;e 9; ar0B;k Bt 1;e 1;d2up; d2;d 1;aIeed0oDurt0;cFw D;aw3ba4d2o5up;ck;k D;in,oK;ck0nk0st6; oJaGef 1nd D;d2ov7up;er;up;r0t D;d2in,oDup;ff,ut;ff,nD;to;ck Jil0nFrgEsD;h B;ainCe B;g BkC; on;in,o5; o5;aw3d2o5up;ay;cMdIsk Fuction6; oD;ff;arDo5;ouD;nd;d D;d2oDup;ff,n;own;t D;o5up;ut", + "Modal": "true¦c5lets,m4ought3sh1w0;ill,o5;a0o4;ll,nt;! to;ay,ight,ust;an,o0;uld", + "Adjective": "true¦0:75;1:7K;2:7Q;3:7J;4:7C;5:5C;6:48;7:49;8:4S;9:61;A:7H;B:70;C:6Z;D:73;E:5X;a6Jb65c5Rd57e4Tf49g41h3Qi35j33k32l2Rm2Gn27o1Rp1Aquack,r10s0Gt09uQvNwFyear5;arp0eJholeIiHoF;man5oFu6C;d6Ezy;despr75s5G;!sa7;eGlFste26;co1Il o4L;!k5;aGiFola4B;b7Tce versa,ol55;ca2gabo63nilla;ltWnJpGrb5Asu4tterF;!moC; f34b1OpGsFti1H;ca7et,ide dMtairs;er,i3N;aPbeco6Rconvin27deMeLfair,ivers4knKprecedYrIsGwF;iel20ritt5Z;i1VuF;pervis0specti3;eFu5;cognLgul6Hl6H;own;ndi3v5Txpect0;cid0rF;!grou5OsF;iz0tood;b7ppeaLssu6GuthorF;iz0;i24ra;aJeHhough4PoGrF;i1oubl0;geth8p,rpB;en5QlFm50rr2Ust0;li3;boo,lFn;ent0;aXcWeUhTiRmug,nobbi3EoPpOqueami3EtJuFymb64;bHi gener55pFrprisi3;erFre0L;! dup8b,i29;du0seq4U;anda6UeIi0PrFy38;aightFip0; fFfF;or5B;adfaCreotyp0;aEec2Gir1JlendBot on; call0le,mb8phist1XrFu0Xvi42;dBry;gnifica2nF;ceEg7;am2Pe8ocki3ut;cFda1em5lfi2Yni1Wpa69re6;o1Gr3W;at58ient28reec58;cr0me,ns serif;aMeIiGoF;buCtt4UuSy4;ghtFv4;!-29f9;ar,bel,condi1du63fres52lHpublic3WsFtard0;is48oF;lu1na2;e1Euc46;bBciF;al,st;aQeOicayu6lacBopuliCrGuF;bl5Amp0;eJiGoF;!b0AfuDmi32p8;mGor,sFva1;ti6;a4We;ciDmF;a0IiF;er,um;ac20rFti1;feAma2Uplexi3v34;rFst;allelHtF;-tiFi4;me;!ed;bQffOkNld fashion0nMpLrg1Hth8utKvF;al,erF;!aHniGt,wF;eiFrouF;ght;ll;do0Ver,g2Msi46;en,posi1; boa5Gg2Kli6;!ay; gua5EbFli6;eat;eHsF;cFer0Hole1;e6uE;d2Tse;ak0eMiLoFua4P;nJrGtF;ab7;thF;!eF;rn;chala2descri50stop;ght5;arby,cessa3Xighbor5xt;aNeLiIoFultip7;bi7derGlFnth5ot,st;dy;a1n;nFx0;iaFor;tuE;di4FnaFre;ci3;cFgenta,in,j03keshift,le,mmoth,ny,sculi6;abEho;aOeJiGoFu13;uti12vi3;mGteraF;l,te;it0;ftIgFth4;al,eGitiF;ma1;nda3D;!-0C;nguBst,tt8;ap1Tind5no0A;agg0uF;niOstifi0veni7;de4gno4Clleg4mSnHpso 1WrF;a1releF;va2; NaMbr0corLdJfluenTiTnIsHtF;aAenDoxF;ic37;a6i2S;a1er,oce2;iGoF;or;reA;deq3Kppr2Z;fFsitu,vitro;ro2;mJpF;arHerfeAoFrop8;li1rtF;a2ed;ti4;eFi0R;d2RnD;aKelJiHoFumdr3C;neCok0rrFs07ur5;if2T;ghfalut1PspF;an2R;liZpf9;lInHrF;d05roF;wi3;dy,gi3;f,low0;ainf9ener2Kiga23lLoKraHuF;ilFng ho;ty;cGtF;ef9is;ef9;ne,od;ea2Eob4;aUeOinNlMoHrF;a1UeFoz1L;e2Eq13tf9;oHrF; keeps,eFm8tuna1;g05ign;liF;sh;ag30ue2;al,i1;dJmGrF;ti7;a7ini6;ne;le; up;bl0i2lDr Gux,voF;ri1uri1;oFreac1F;ff;aOfficie2lNmiMnKreAthere4veJxF;aAcess,peHtraGuF;be2Ml0I;!va1E;ct0rt;n,ryday; Fcouragi3tiE;rou1sui1;ne2;abo23dQe18i1;g8sF;t,ygF;oi3;er;aVeNiHoFrea15ue;mina2ne,ubF;le,tf9;dact1Bfficu1OsGvF;erD;creHeas0gruntl0honeCordGtF;a2ress0;er5;et; LadpKfJgene1PliHrang0spe1PtGvoF;ut;ail0ermin0;be1Mca1ghF;tf9;ia2;an;facto;i5magFngeroZs0I;ed,i3;ly;ertaRhief,ivil,oHrF;aFowd0u0H;mp0v02z0;loNmLnGoi3rrFve0P;eAu1I;cre1grIsHtF;emFra0F;po0D;ta2;ue2;mer08pleF;te,x;ni4ss4;in;aPeLizarElJoGrF;and new,isk,okP;gGna fiWttom,urgeoF;is;us;ank,iI;re;autif9hiGlov0nFst,yoG;eVt;nd;ul;ckGnkru0XrrF;en;!wards; priori,b0Nc0Kd0AfraBg05h04lZma06ntiquYpUrOsMttracti07utheLvIwF;aGkF;wa0U;ke,re;ant garGerF;age;de;ntV;leep,tonisF;hi3;ab,bitIroHtiF;fiF;ci4;ga2;raF;ry;pFt;are2etiPrF;oprF;ia1;at0;arIcohGeFiMl,oof;rt;olF;ic;mi3;ead;ainCgressiGoniF;zi3;ve;st;id; MeKuJvF;aGerD;se;nc0;ed;lt;pt,qF;ua1;hoc,infinitF;um;cuGtu4u1;al;ra1;erPlOoMruLsGuF;nda2;e2oGtraA;ct;lu1rbi3;ng;te;pt;aFve;rd;aze,e;ra2;nt", + "Comparable": "true¦0:40;1:4H;2:44;3:4A;4:2X;5:3W;a4Nb43c3Nd3Ce34f2Qg2Eh23i1Uj1Tk1Ql1Hm1Bn15o13p0Tqu0Rr0IsRtKuIvFw7y6za11;ell26ou3;aBe9hi1Xi7r6;o3y;ck0Mde,l6n1ry,se;d,y;a6i4Lt;k,ry;n1Sr6sI;m,y;a7e6ulgar;nge5rda2xi3;gue,in,st;g0n6pco3Lse5;like0ti1;aAen9hi8i7ough,r6;anqu2Pen1ue;dy,g3Tme0ny,r09;ck,n,rs2Q;d41se;ll,me,rt,s6wd46;te5;aVcarUeThRiQkin0FlMmKoHpGqua1GtAu7w6;eet,ift;b7dd14per0Gr6;e,re2I;sta2Gt4;aAe9iff,r7u6;pXr1;a6ict,o3;ig3Gn0V;a1ep,rn;le,rk;e23i3Gright0;ci29ft,l7o6re,ur;n,thi3;emn,id;a6el0ooth;ll,rt;e8i6ow,y;ck,g36m6;!y;ek,nd3E;ck,l0mp4;a6iTort,rill,y;dy,ll0Yrp;cu0Sve0Sxy;ce,ed,y;d,fe,int0l1Wv15;aBe9i8o6ude;mantic,o1Jsy,u6;gh,nd;ch,pe,tzy;a6d,mo0I;dy,l;gg7ndom,p6re,w;id;ed;ai2i6;ck,et;aEhoDi1RlCoBr8u6;ny,r6;e,p4;egna2ic7o6;fouZud;ey,k0;li05or,te1C;ain,easa2;ny;in5le;dd,f6i0ld,ranR;fi11;aAe8i7o6;b4isy,rm16sy;ce,mb4;a6w;r,t;ive,rr02;aAe8ild,o7u6;nda1Ate;ist,o1;a6ek,llY;n,s0ty;d,tuR;aCeBi9o6ucky;f0Vn7o1Eu6ve0w18y0U;d,sy;e0g;g1Uke0tt4v6;e0i3;an,wd;me,r6te;ge;e7i6;nd;en;ol0ui1P;cy,ll,n6;sBt6;e6ima8;llege2r6;es7media6;te;ti3;ecu6ta2;re;aEeBiAo8u6;ge,m6ng1R;b4id;ll6me0t;ow;gh,l0;a6f04sita2;dy,v6;en0y;nd1Hppy,r6te5;d,sh;aGenFhDiClBoofy,r6;a9e8is0o6ue1E;o6ss;vy;at,en,y;nd,y;ad,ib,ooI;a2d1;a6o6;st0;t4uiY;u1y;aIeeb4iDlat,oAr8u6;ll,n6r14;!ny;aHe6iend0;e,sh;a7r6ul;get5mG;my;erce8n6rm,t;an6e;ciC;! ;le;ir,ke,n0Fr,st,t,ulA;aAerie,mp9sse7v6xtre0Q;il;nti6;al;ty;r7s6;tern,y;ly,th0;aFeCi9r7u6;ll,mb;u6y;nk;r7vi6;ne;e,ty;a6ep,nD;d6f,r;!ly;mp,pp03rk;aHhDlAo8r7u6;dd0r0te;isp,uel;ar6ld,mmon,ol,st0ward0zy;se;e6ou1;a6vW;n,r;ar8e6il0;ap,e6;sy;mi3;gey,lm8r6;e5i3;ful;!i3;aNiLlIoEr8u6;r0sy;ly;aAi7o6;ad,wn;ef,g7llia2;nt;ht;sh,ve;ld,r7un6;cy;ed,i3;ng;a7o6ue;nd,o1;ck,nd;g,tt6;er;d,ld,w1;dy;bsu9ng8we6;so6;me;ry;rd", + "TextValue": "true¦bMeIfChundredNmMnin9one,qu8s6t0zeroN;enMh3rLw0;e0o;l0ntC;fGve;ir0ousandIree;d,t5;e0ix7;cond,ptEven6xtE;adrDintD;e0th;!t0;e9ie8y;i3o0;rt1ur0;!t2;ie4y;ft0rst,ve;e3h,ie2y;ight0lev2;!e1h,ie0y;th;en1;illion0;!th", + "Ordinal": "true¦bGeDf9hundredHmGnin7qu6s4t0zeroH;enGh1rFwe0;lfFn9;ir0ousandE;d,t4;e0ixt9;cond,ptAvent8xtA;adr9int9;et0th;e6ie8;i2o0;r0urt3;tie5;ft1rst;ight0lev1;e0h,ie2;en1;illion0;th", + "Cardinal": "true¦bGeDf7hundred,mGnine9one,qu6s4t0zero;en,h2rFw0;e0o;lve,n7;irt8ousand,ree;e0ix4;ptAven3xtA;adr9int9;i3o0;r1ur0;!t2;ty;ft0ve;e2y;ight0lev1;!e0y;en;illion", + "Expression": "true¦a02b01dXeVfuck,gShLlImHnGoDpBshAu7voi04w3y0;a1eLu0;ck,p;!a,hoo,y;h1ow,t0;af,f;e0oa;e,w;gh,h0;! 0h,m;huh,oh;eesh,hh,it;ff,hew,l0sst;ease,z;h1o0w,y;h,o,ps;!h;ah,ope;eh,mm;m1ol0;!s;ao,fao;a4e2i,mm,oly1urr0;ah;! mo6;e,ll0y;!o;ha0i;!ha;ah,ee,o0rr;l0odbye;ly;e0h,t cetera,ww;k,p;'oh,a0uh;m0ng;mit,n0;!it;ah,oo,ye; 1h0rgh;!em;la", + "Adverb": "true¦a07by 05d01eYfShQinPjustOkinda,mMnJoEpCquite,r9s5t2up1very,w0Bye0;p,s; to,wards5;h1o0wiO;o,t6ward;en,us;everal,o0uch;!me1rt0; of;hXtimes,w07;a1e0;alS;ndomRthN;ar excellDer0oint blank; Mhaps;f3n0;ce0ly;! 0;ag00moU; courHten;ewJo0; longEt 0;onHwithstanding;aybe,eanwhiAore0;!ovB;! aboS;deed,steT;en0;ce;or2u0;l9rther0;!moH; 0ev3;examp0good,suF;le;n mas1v0;er;se;e0irect1; 1finite0;ly;ju7trop;far,n0;ow; CbroBd nauseam,gAl5ny2part,side,t 0w3;be5l0mo5wor5;arge,ea4;mo1w0;ay;re;l 1mo0one,ready,so,ways;st;b1t0;hat;ut;ain;ad;lot,posteriori", + "Preposition": "true¦'o,-,aKbHcGdFexcept,fEinDmidPnotwithstandiQoBpRqua,sAt6u3vi2w0;/o,hereMith0;!in,oQ;a,s-a-vis;n1p0;!on;like,til;h0ill,owards;an,r0;ough0u;!oI;ans,ince,o that;',f0n1ut;!f;!to;or,rom;espite,own,u3;hez,irca;ar1e0oAy;low,sides,tween;ri6;',bo7cross,ft6lo5m3propos,round,s1t0;!op;! long 0;as;id0ong0;!st;ng;er;ut", + "Determiner": "true¦aAboth,d8e5few,l3mu7neiCown,plenty,some,th2various,wh0;at0ich0;evB;at,e3is,ose;a,e0;!ast,s;a1i6l0nough,very;!se;ch;e0u;!s;!n0;!o0y;th0;er" +} \ No newline at end of file diff --git a/src/world/addConjugations.js b/src/world/addConjugations.js deleted file mode 100644 index de5f14a00..000000000 --- a/src/world/addConjugations.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; -const conjugate = require('../subset/verbs/methods/conjugate/faster.js'); - -//extend our current irregular conjugations, overwrite if exists -//also, map the irregulars for easy infinitive lookup - {bought: 'buy'} -const addConjugations = function(obj) { - - Object.keys(obj).forEach((inf) => { - this.conjugations[inf] = this.conjugations[inf] || {}; - //add it to the lexicon - this.words[inf] = this.words[inf] || 'Infinitive'; - Object.keys(obj[inf]).forEach((tag) => { - let word = obj[inf][tag]; - //add this to our conjugations - this.conjugations[inf][tag] = word; - //add it to the lexicon, too - this.words[word] = this.words[word] || tag; - //also denormalize to cache.toInfinitive - this.cache.toInfinitive[obj[inf][tag]] = inf; - }); - //guess the other conjugations - let forms = conjugate(inf, this); - Object.keys(forms).forEach((k) => { - let word = forms[k]; - if (this.words.hasOwnProperty(word) === false) { - this.words[word] = k; - } - }); - }); - return obj; -}; -module.exports = addConjugations; diff --git a/src/world/addIrregulars.js b/src/world/addIrregulars.js new file mode 100644 index 000000000..3a0d7f4da --- /dev/null +++ b/src/world/addIrregulars.js @@ -0,0 +1,27 @@ +// add words from plurals and conjugations data +const addIrregulars = function(world) { + //add irregular plural nouns + let nouns = world.irregulars.nouns + let words = Object.keys(nouns) + for (let i = 0; i < words.length; i++) { + const w = words[i] + world.words[w] = 'Singular' + world.words[nouns[w]] = 'Plural' + } + + // add irregular verb conjugations + let verbs = world.irregulars.verbs + let keys = Object.keys(verbs) + for (let i = 0; i < keys.length; i++) { + const inf = keys[i] + //add only if it it's safe... + world.words[inf] = world.words[inf] || 'Infinitive' + let forms = world.transforms.conjugate(inf, world) + forms = Object.assign(forms, verbs[inf]) + //add the others + Object.keys(forms).forEach(tag => { + world.words[forms[tag]] = world.words[forms[tag]] || tag + }) + } +} +module.exports = addIrregulars diff --git a/src/world/addPatterns.js b/src/world/addPatterns.js deleted file mode 100644 index 214ba0cf6..000000000 --- a/src/world/addPatterns.js +++ /dev/null @@ -1,9 +0,0 @@ - -// -const addPatterns = function(obj) { - Object.keys(obj).forEach((k) => { - this.patterns[k] = obj[k]; - }); - return obj; -}; -module.exports = addPatterns; diff --git a/src/world/addPlurals.js b/src/world/addPlurals.js deleted file mode 100644 index faa2a59b4..000000000 --- a/src/world/addPlurals.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -//put singular->plurals in world, the reverse in cache, -//and both forms in the lexicon -const addPlurals = function(obj) { - Object.keys(obj).forEach((sing) => { - let plur = obj[sing]; - this.plurals[sing] = plur; - //add them both to the lexicon - this.words[plur] = this.words[plur] || 'Plural'; - this.words[sing] = this.words[sing] || 'Singular'; - //denormalize them in cache.toPlural - this.cache.toSingular[plur] = sing; - }); - return obj; -}; -module.exports = addPlurals; diff --git a/src/world/addRegex.js b/src/world/addRegex.js deleted file mode 100644 index 0b426fd8c..000000000 --- a/src/world/addRegex.js +++ /dev/null @@ -1,11 +0,0 @@ - -// -const addRegex = function(obj) { - Object.keys(obj).forEach((k) => { - this.regex.push({ - reg: new RegExp(k, 'i'), - tag: obj[k] - }); - }); -}; -module.exports = addRegex; diff --git a/src/world/addTags.js b/src/world/addTags.js deleted file mode 100644 index 6ae99f3de..000000000 --- a/src/world/addTags.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -//add 'downward' tags (that immediately depend on this one) -const addDownword = require('../tags/addDownward'); - -//extend our known tagset with these new ones -const addTags = function(tags) { - Object.keys(tags).forEach((tag) => { - let obj = tags[tag]; - obj.notA = obj.notA || []; - obj.downward = obj.downward || []; - this.tags[tag] = obj; - }); - addDownword(this.tags); - return tags; -}; -module.exports = addTags; diff --git a/src/world/addWords.js b/src/world/addWords.js index 8982c28bb..76f783516 100644 --- a/src/world/addWords.js +++ b/src/world/addWords.js @@ -1,74 +1,83 @@ -'use strict'; -const normalize = require('../term/methods/normalize/normalize').normalize; -const inflect = require('../subset/nouns/methods/pluralize'); -const conjugate = require('../subset/verbs/methods/conjugate/faster.js'); -const adjFns = require('../subset/adjectives/methods'); -const wordReg = / /; - - -const cleanUp = function(str) { - str = normalize(str); - //extra whitespace - str = str.replace(/\s+/, ' '); - //remove sentence-punctuaion too - str = str.replace(/[.\?,;\!]/g, ''); - return str; -}; - -// -const addWords = function(words) { - //go through each word - Object.keys(words).forEach((word) => { - let tag = words[word]; - word = cleanUp(word); - this.words[word] = tag; - //add it to multi-word cache, - if (wordReg.test(word) === true) { - let arr = word.split(wordReg); - this.cache.firstWords[arr[0]] = true; +//safely add it to the lexicon +const addWord = function(word, tag, lex) { + if (lex[word] !== undefined) { + if (typeof lex[word] === 'string') { + lex[word] = [lex[word]] } + lex[word].push(tag) + } else { + lex[word] = tag + } +} - //turn singulars into plurals - if (tag === 'Singular') { - let plural = inflect(word, {}); - if (plural && plural !== word) { - this.words[plural] = 'Plural'; - } - return; - } - //turn infinitives into all conjugations - if (tag === 'Infinitive') { - let conj = conjugate(word, this); - Object.keys(conj).forEach((k) => { - this.words[conj[k]] = k; - }); - return; +// blast-out more forms for some given words +const addMore = function(word, tag, world) { + let lexicon = world.words + let transform = world.transforms + + // cache multi-words + let words = word.split(' ') + if (words.length > 1) { + //cache the beginning word + world.hasCompound[words[0]] = true + } + // inflect our nouns + if (tag === 'Singular') { + let plural = transform.toPlural(word, world) + lexicon[plural] = lexicon[plural] || 'Plural' // only if it's safe + } + //conjugate our verbs + if (tag === 'Infinitive') { + let conj = transform.conjugate(word, world) + let tags = Object.keys(conj) + for (let i = 0; i < tags.length; i++) { + let w = conj[tags[i]] + lexicon[w] = lexicon[w] || tags[i] // only if it's safe } - //phrasals like 'pull out' get conjugated too - if (tag === 'PhrasalVerb') { - let arr = word.split(/ /); - let conj = conjugate(arr[0], this); - Object.keys(conj).forEach((k) => { - let form = conj[k] + ' ' + arr[1]; - this.words[form] = 'PhrasalVerb'; - //add it to cache, too - this.cache.firstWords[conj[k]] = true; - }); - return; + } + //derive more adjective forms + if (tag === 'Comparable') { + let conj = transform.adjectives(word) + let tags = Object.keys(conj) + for (let i = 0; i < tags.length; i++) { + let w = conj[tags[i]] + lexicon[w] = lexicon[w] || tags[i] // only if it's safe } - //turn some adjectives into superlatives - if (tag === 'Comparable') { - let comp = adjFns.toComparative(word); - if (comp && word !== comp) { - this.words[comp] = 'Comparative'; - } - let supr = adjFns.toSuperlative(word); - if (supr && word !== supr) { - this.words[supr] = 'Superlative'; - } + } + //conjugate phrasal-verbs + if (tag === 'PhrasalVerb') { + //add original form + addWord(word, 'Infinitive', lexicon) + //conjugate first word + let conj = transform.conjugate(words[0], world) + let tags = Object.keys(conj) + for (let i = 0; i < tags.length; i++) { + //add it to our cache + world.hasCompound[conj[tags[i]]] = true + //first + last words + let w = conj[tags[i]] + ' ' + words[1] + + addWord(w, tags[i], lexicon) + addWord(w, 'PhrasalVerb', lexicon) } - }); + } + // inflect our demonyms - 'germans' + if (tag === 'Demonym') { + let plural = transform.toPlural(word, world) + lexicon[plural] = lexicon[plural] || ['Demonym', 'Plural'] // only if it's safe + } +} - return words; -}; -module.exports = addWords; +// throw a bunch of words in our lexicon +// const doWord = function(words, tag, world) { +// let lexicon = world.words +// for (let i = 0; i < words.length; i++) { +// addWord(words[i], tag, lexicon) +// // do some fancier stuff +// addMore(words[i], tag, world) +// } +// } +module.exports = { + addWord: addWord, + addMore: addMore, +} diff --git a/src/world/data/conjugations.js b/src/world/data/conjugations.js new file mode 100644 index 000000000..b3d23a34a --- /dev/null +++ b/src/world/data/conjugations.js @@ -0,0 +1,697 @@ +// a list of irregular verb conjugations +// used in verbs().conjugate() +// but also added to our lexicon + +//use shorter key-names +const mapping = { + g: 'Gerund', + prt: 'Participle', + perf: 'PerfectTense', + pst: 'PastTense', + fut: 'FuturePerfect', + pres: 'PresentTense', + pluperf: 'Pluperfect', + a: 'Actor', +} + +// '_' in conjugations is the infinitive form +let conjugations = { + act: { + a: '_or', + }, + age: { + g: 'ageing', + pst: 'aged', + pres: 'ages', + }, + aim: { + a: '_er', + g: '_ing', + pst: '_ed', + }, + arise: { + prt: '_n', + pst: 'arose', + }, + babysit: { + a: '_ter', + pst: 'babysat', + }, + ban: { + a: '', + g: '_ning', + pst: '_ned', + }, + be: { + a: '', + g: 'am', + prt: 'been', + pst: 'was', + pres: 'is', + }, + beat: { + a: '_er', + g: '_ing', + prt: '_en', + }, + become: { + prt: '_', + }, + begin: { + g: '_ning', + prt: 'begun', + pst: 'began', + }, + being: { + g: 'are', + pst: 'were', + pres: 'are', + }, + bend: { + prt: 'bent', + }, + bet: { + a: '_ter', + prt: '_', + }, + bind: { + pst: 'bound', + }, + bite: { + g: 'biting', + prt: 'bitten', + pst: 'bit', + }, + bleed: { + prt: 'bled', + pst: 'bled', + }, + blow: { + prt: '_n', + pst: 'blew', + }, + boil: { + a: '_er', + }, + brake: { + prt: 'broken', + }, + break: { + pst: 'broke', + }, + breed: { + pst: 'bred', + }, + bring: { + prt: 'brought', + pst: 'brought', + }, + broadcast: { + pst: '_', + }, + budget: { + pst: '_ed', + }, + build: { + prt: 'built', + pst: 'built', + }, + burn: { + prt: '_ed', + }, + burst: { + prt: '_', + }, + buy: { + prt: 'bought', + pst: 'bought', + }, + can: { + a: '', + fut: '_', + g: '', + pst: 'could', + perf: 'could', + pluperf: 'could', + pres: '_', + }, + catch: { + pst: 'caught', + }, + choose: { + g: 'choosing', + prt: 'chosen', + pst: 'chose', + }, + cling: { + prt: 'clung', + }, + come: { + prt: '_', + pst: 'came', + }, + compete: { + a: 'competitor', + g: 'competing', + pst: '_d', + }, + cost: { + pst: '_', + }, + creep: { + prt: 'crept', + }, + cut: { + prt: '_', + }, + deal: { + prt: '_t', + pst: '_t', + }, + develop: { + a: '_er', + g: '_ing', + pst: '_ed', + }, + die: { + g: 'dying', + pst: '_d', + }, + dig: { + g: '_ging', + prt: 'dug', + pst: 'dug', + }, + dive: { + prt: '_d', + }, + do: { + pst: 'did', + pres: '_es', + }, + draw: { + prt: '_n', + pst: 'drew', + }, + dream: { + prt: '_t', + }, + drink: { + prt: 'drunk', + pst: 'drank', + }, + drive: { + g: 'driving', + prt: '_n', + pst: 'drove', + }, + drop: { + g: '_ping', + pst: '_ped', + }, + eat: { + a: '_er', + g: '_ing', + prt: '_en', + pst: 'ate', + }, + edit: { + g: '_ing', + }, + egg: { + pst: '_ed', + }, + fall: { + prt: '_en', + pst: 'fell', + }, + feed: { + prt: 'fed', + pst: 'fed', + }, + feel: { + a: '_er', + pst: 'felt', + }, + fight: { + prt: 'fought', + pst: 'fought', + }, + find: { + pst: 'found', + }, + flee: { + g: '_ing', + prt: 'fled', + }, + fling: { + prt: 'flung', + }, + fly: { + prt: 'flown', + pst: 'flew', + }, + forbid: { + pst: 'forbade', + }, + forget: { + g: '_ing', + prt: 'forgotten', + pst: 'forgot', + }, + forgive: { + g: 'forgiving', + prt: '_n', + pst: 'forgave', + }, + free: { + a: '', + g: '_ing', + }, + freeze: { + g: 'freezing', + prt: 'frozen', + pst: 'froze', + }, + get: { + pst: 'got', + prt: 'gotten', + }, + give: { + g: 'giving', + prt: '_n', + pst: 'gave', + }, + go: { + prt: '_ne', + pst: 'went', + pres: 'goes', + }, + grow: { + prt: '_n', + }, + hang: { + prt: 'hung', + pst: 'hung', + }, + have: { + g: 'having', + prt: 'had', + pst: 'had', + pres: 'has', + }, + hear: { + prt: '_d', + pst: '_d', + }, + hide: { + prt: 'hidden', + pst: 'hid', + }, + hit: { + prt: '_', + }, + hold: { + prt: 'held', + pst: 'held', + }, + hurt: { + prt: '_', + pst: '_', + }, + ice: { + g: 'icing', + pst: '_d', + }, + imply: { + pst: 'implied', + pres: 'implies', + }, + is: { + a: '', + g: 'being', + pst: 'was', + pres: '_', + }, + keep: { + prt: 'kept', + }, + kneel: { + prt: 'knelt', + }, + know: { + prt: '_n', + }, + lay: { + prt: 'laid', + pst: 'laid', + }, + lead: { + prt: 'led', + pst: 'led', + }, + leap: { + prt: '_t', + }, + leave: { + prt: 'left', + pst: 'left', + }, + lend: { + prt: 'lent', + }, + lie: { + g: 'lying', + pst: 'lay', + }, + light: { + prt: 'lit', + pst: 'lit', + }, + log: { + g: '_ging', + pst: '_ged', + }, + loose: { + prt: 'lost', + }, + lose: { + g: 'losing', + pst: 'lost', + }, + make: { + prt: 'made', + pst: 'made', + }, + mean: { + prt: '_t', + pst: '_t', + }, + meet: { + a: '_er', + g: '_ing', + prt: 'met', + pst: 'met', + }, + miss: { + pres: '_', + }, + pay: { + prt: 'paid', + pst: 'paid', + }, + prove: { + prt: '_n', + }, + puke: { + g: 'puking', + }, + put: { + prt: '_', + }, + quit: { + prt: '_', + }, + read: { + prt: '_', + pst: '_', + }, + ride: { + prt: 'ridden', + }, + ring: { + prt: 'rung', + pst: 'rang', + }, + rise: { + fut: 'will have _n', + g: 'rising', + prt: '_n', + pst: 'rose', + pluperf: 'had _n', + }, + rub: { + g: '_bing', + pst: '_bed', + }, + run: { + g: '_ning', + prt: '_', + pst: 'ran', + }, + say: { + prt: 'said', + pst: 'said', + pres: '_s', + }, + seat: { + prt: 'sat', + }, + see: { + g: '_ing', + prt: '_n', + pst: 'saw', + }, + seek: { + prt: 'sought', + }, + sell: { + prt: 'sold', + pst: 'sold', + }, + send: { + prt: 'sent', + }, + set: { + prt: '_', + }, + sew: { + prt: '_n', + }, + shake: { + prt: '_n', + }, + shave: { + prt: '_d', + }, + shed: { + g: '_ding', + pst: '_', + pres: '_s', + }, + shine: { + prt: 'shone', + pst: 'shone', + }, + shoot: { + prt: 'shot', + pst: 'shot', + }, + show: { + pst: '_ed', + }, + shut: { + prt: '_', + }, + sing: { + prt: 'sung', + pst: 'sang', + }, + sink: { + pst: 'sank', + pluperf: 'had sunk', + }, + sit: { + pst: 'sat', + }, + ski: { + pst: '_ied', + }, + slay: { + prt: 'slain', + }, + sleep: { + prt: 'slept', + }, + slide: { + prt: 'slid', + pst: 'slid', + }, + smash: { + pres: '_es', + }, + sneak: { + prt: 'snuck', + }, + speak: { + fut: 'will have spoken', + prt: 'spoken', + pst: 'spoke', + perf: 'have spoken', + pluperf: 'had spoken', + }, + speed: { + prt: 'sped', + }, + spend: { + prt: 'spent', + }, + spill: { + prt: '_ed', + pst: 'spilt', + }, + spin: { + g: '_ning', + prt: 'spun', + pst: 'spun', + }, + spit: { + prt: 'spat', + }, + split: { + prt: '_', + }, + spread: { + pst: '_', + }, + spring: { + prt: 'sprung', + }, + stand: { + pst: 'stood', + }, + steal: { + a: '_er', + pst: 'stole', + }, + stick: { + pst: 'stuck', + }, + sting: { + pst: 'stung', + }, + stink: { + prt: 'stunk', + pst: 'stunk', + }, + stream: { + a: '_er', + }, + strew: { + prt: '_n', + }, + strike: { + g: 'striking', + pst: 'struck', + }, + suit: { + a: '_er', + g: '_ing', + pst: '_ed', + }, + sware: { + prt: 'sworn', + }, + swear: { + pst: 'swore', + }, + sweep: { + prt: 'swept', + }, + swim: { + g: '_ming', + pst: 'swam', + }, + swing: { + pst: 'swung', + }, + take: { + fut: 'will have _n', + pst: 'took', + perf: 'have _n', + pluperf: 'had _n', + }, + teach: { + pst: 'taught', + pres: '_es', + }, + tear: { + pst: 'tore', + }, + tell: { + pst: 'told', + }, + think: { + pst: 'thought', + }, + thrive: { + prt: '_d', + }, + tie: { + g: 'tying', + pst: '_d', + }, + undergo: { + prt: '_ne', + }, + understand: { + pst: 'understood', + }, + upset: { + prt: '_', + }, + wait: { + a: '_er', + g: '_ing', + pst: '_ed', + }, + wake: { + pst: 'woke', + }, + wear: { + pst: 'wore', + }, + weave: { + prt: 'woven', + }, + weep: { + prt: 'wept', + }, + win: { + g: '_ning', + pst: 'won', + }, + wind: { + prt: 'wound', + }, + withdraw: { + pst: 'withdrew', + }, + wring: { + prt: 'wrung', + }, + write: { + g: 'writing', + prt: 'written', + pst: 'wrote', + }, +} + +//uncompress our ad-hoc compression scheme +let keys = Object.keys(conjugations) +for (let i = 0; i < keys.length; i++) { + const inf = keys[i] + let final = {} + Object.keys(conjugations[inf]).forEach(key => { + let str = conjugations[inf][key] + //swap-in infinitives for '_' + str = str.replace('_', inf) + + let full = mapping[key] + final[full] = str + }) + //over-write original + conjugations[inf] = final +} + +module.exports = conjugations diff --git a/src/world/data/misc.js b/src/world/data/misc.js new file mode 100644 index 000000000..112168de3 --- /dev/null +++ b/src/world/data/misc.js @@ -0,0 +1,15 @@ +//words that can't be compressed, for whatever reason +module.exports = { + // numbers + '20th century fox': 'Organization', + // '3m': 'Organization', + '7 eleven': 'Organization', + '7-eleven': 'Organization', + g8: 'Organization', + 'motel 6': 'Organization', + vh1: 'Organization', + q1: 'Date', + q2: 'Date', + q3: 'Date', + q4: 'Date', +} diff --git a/src/world/data/plurals.js b/src/world/data/plurals.js new file mode 100644 index 000000000..4424bbb5d --- /dev/null +++ b/src/world/data/plurals.js @@ -0,0 +1,81 @@ +//nouns with irregular plural/singular forms +//used in noun.inflect, and also in the lexicon. + +module.exports = { + addendum: 'addenda', + alga: 'algae', + alumna: 'alumnae', + alumnus: 'alumni', + analysis: 'analyses', + antenna: 'antennae', + appendix: 'appendices', + avocado: 'avocados', + axis: 'axes', + bacillus: 'bacilli', + barracks: 'barracks', + beau: 'beaux', + bus: 'buses', + cactus: 'cacti', + chateau: 'chateaux', + child: 'children', + circus: 'circuses', + clothes: 'clothes', + corpus: 'corpora', + criterion: 'criteria', + curriculum: 'curricula', + database: 'databases', + deer: 'deer', + diagnosis: 'diagnoses', + echo: 'echoes', + embargo: 'embargoes', + epoch: 'epochs', + foot: 'feet', + formula: 'formulae', + fungus: 'fungi', + genus: 'genera', + goose: 'geese', + halo: 'halos', + hippopotamus: 'hippopotami', + index: 'indices', + larva: 'larvae', + leaf: 'leaves', + libretto: 'libretti', + loaf: 'loaves', + man: 'men', + matrix: 'matrices', + memorandum: 'memoranda', + modulus: 'moduli', + mosquito: 'mosquitoes', + mouse: 'mice', + move: 'moves', + nebula: 'nebulae', + nucleus: 'nuclei', + octopus: 'octopi', + opus: 'opera', + ovum: 'ova', + ox: 'oxen', + parenthesis: 'parentheses', + person: 'people', + phenomenon: 'phenomena', + prognosis: 'prognoses', + quiz: 'quizzes', + radius: 'radii', + referendum: 'referenda', + rodeo: 'rodeos', + sex: 'sexes', + shoe: 'shoes', + sombrero: 'sombreros', + stimulus: 'stimuli', + stomach: 'stomachs', + syllabus: 'syllabi', + synopsis: 'synopses', + tableau: 'tableaux', + thesis: 'theses', + thief: 'thieves', + tooth: 'teeth', + tornado: 'tornados', + tuxedo: 'tuxedos', + vertebra: 'vertebrae', + // virus: 'viri', + // zero: 'zeros', +} diff --git a/src/world/index.js b/src/world/index.js deleted file mode 100644 index b90d4cc4f..000000000 --- a/src/world/index.js +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; -// const addWords = require('./addWords'); -const fns = require('../fns'); -let data = require('./_data'); -let moreData = require('./more-data'); -let tags = require('../tags'); -let unpack = require('./unpack'); -let addTags = require('./addTags'); -let addWords = require('./addWords'); -let addRegex = require('./addRegex'); -let addConjugations = require('./addConjugations'); -let addPatterns = require('./addPatterns'); -let addPlurals = require('./addPlurals'); -let misc = require('./more-data/misc'); - -//lazier/faster object-merge -const extend = (main, obj) => { - let keys = Object.keys(obj); - for (let i = 0; i < keys.length; i++) { - main[keys[i]] = obj[keys[i]]; - } - return main; -}; - -//class World -let World = function() { - this.words = {}; - this.tags = tags; - this.regex = []; - this.patterns = {}; - this.conjugations = {}; - this.plurals = {}; - //denormalized data for faster-lookups - this.cache = { - firstWords: {}, - toInfinitive: {}, - toSingular: {} - }; -}; - -World.prototype.addTags = addTags; -World.prototype.addWords = addWords; -World.prototype.addRegex = addRegex; -World.prototype.addConjugations = addConjugations; -World.prototype.addPlurals = addPlurals; -World.prototype.addPatterns = addPatterns; - -//make a no-reference copy of all the data -World.prototype.clone = function() { - let w2 = new World(); - ['words', 'firstWords', 'tagset', 'regex', 'patterns', 'conjugations', 'plurals'].forEach((k) => { - if (this[k]) { - w2[k] = fns.copy(this[k]); - } - }); - return w2; -}; - -//add all the things, in all the places -World.prototype.plugin = function(obj) { - //untangle compromise-plugin - obj = unpack(obj); - //add all-the-things to this world object - //(order may matter) - if (obj.tags) { - this.addTags(obj.tags); - } - if (obj.regex) { - this.addRegex(obj.regex); - } - if (obj.patterns) { - this.addPatterns(obj.patterns); - } - if (obj.conjugations) { - this.addConjugations(obj.conjugations); - } - if (obj.plurals) { - this.addPlurals(obj.plurals); - } - if (obj.words) { - this.addWords(obj.words); - } -}; - -//export a default world -let w = new World(); -w.plugin(data); -w.addWords(misc); -moreData.forEach((obj) => { - extend(w.words, obj); -}); - -module.exports = { - w: w, - reBuild: function() { - //export a default world - let w2 = new World(); - w2.plugin(data); - w2.addWords(misc); - moreData.forEach((obj) => { - extend(w2.words, obj); - }); - return w2; - } -}; diff --git a/src/world/more-data/abbreviations.js b/src/world/more-data/abbreviations.js deleted file mode 100644 index bf880a99a..000000000 --- a/src/world/more-data/abbreviations.js +++ /dev/null @@ -1,178 +0,0 @@ -//these are common word shortenings used in the lexicon and sentence segmentation methods -//there are all nouns,or at the least, belong beside one. -"use strict"; - -//common abbreviations -let compact = { - Noun: [ - "arc", - "al", - "exp", - "fy", - "pd", - "pl", - "plz", - "tce", - "bl", - "ma", - "ba", - "lit", - "ex", - "eg", - "ie", - "ca", - "cca", - "vs", - "etc", - "esp", - "ft", - //these are too ambiguous - "bc", - "ad", - "md", - "corp", - "col" - ], - Organization: [ - "dept", - "univ", - "assn", - "bros", - "inc", - "ltd", - "co", - //proper nouns with exclamation marks - "yahoo", - "joomla", - "jeopardy" - ], - - Place: [ - "rd", - "st", - "dist", - "mt", - "ave", - "blvd", - "cl", - "ct", - "cres", - "hwy", - //states - "ariz", - "cal", - "calif", - "colo", - "conn", - "fla", - "fl", - "ga", - "ida", - "ia", - "kan", - "kans", - - "minn", - "neb", - "nebr", - "okla", - "penna", - "penn", - "pa", - "dak", - "tenn", - "tex", - "ut", - "vt", - "va", - "wis", - "wisc", - "wy", - "wyo", - "usafa", - "alta", - "ont", - "que", - "sask" - ], - - Month: [ - "jan", - "feb", - "mar", - "apr", - "jun", - "jul", - "aug", - "sep", - "sept", - "oct", - "nov", - "dec" - ], - Date: ["circa"], - - //Honorifics - Honorific: [ - "adj", - "adm", - "adv", - "asst", - "atty", - "bldg", - "brig", - "capt", - "cmdr", - "comdr", - "cpl", - "det", - "dr", - "esq", - "gen", - "gov", - "hon", - "jr", - "llb", - "lt", - "maj", - "messrs", - "mister", - "mlle", - "mme", - "mr", - "mrs", - "ms", - "mstr", - "op", - "ord", - "phd", - "prof", - "pvt", - "rep", - "reps", - "res", - "rev", - "sen", - "sens", - "sfc", - "sgt", - "sir", - "sr", - "supt", - "surg" - //miss - //misses - ], - Value: ["no"] -}; - -//unpack the compact terms into the misc lexicon.. -let abbreviations = {}; -const keys = Object.keys(compact); -for (let i = 0; i < keys.length; i++) { - const arr = compact[keys[i]]; - for (let i2 = 0; i2 < arr.length; i2++) { - abbreviations[arr[i2]] = [keys[i], "Abbreviation"]; - } -} -module.exports = abbreviations; diff --git a/src/world/more-data/index.js b/src/world/more-data/index.js deleted file mode 100644 index b464c3fe7..000000000 --- a/src/world/more-data/index.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = [ - require('./abbreviations'), - require('./irregularAdjectives').lexicon, - require('./numbers').lexicon, - require('./orgWords'), -]; diff --git a/src/world/more-data/irregularAdjectives.js b/src/world/more-data/irregularAdjectives.js deleted file mode 100644 index cd7e0f837..000000000 --- a/src/world/more-data/irregularAdjectives.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; -//adjectives that have irregular conjugations to adverb, comparative, and superlative forms -const toAdverb = { - bad: 'badly', - best: 'best', - early: 'early', - fast: 'fast', - good: 'well', - hard: 'hard', - icy: 'icily', - idle: 'idly', - late: 'late', - latter: 'latter', - little: 'little', - long: 'long', - low: 'low', - male: 'manly', - public: 'publicly', - simple: 'simply', - single: 'singly', - special: 'especially', - straight: 'straight', - vague: 'vaguely', - well: 'well', - whole: 'wholly', - wrong: 'wrong' -}; - -const toComparative = { - grey: 'greyer', - gray: 'grayer', - green: 'greener', - yellow: 'yellower', - red: 'redder', - good: 'better', - well: 'better', - bad: 'worse', - sad: 'sadder', - big: 'bigger' -}; - -const toSuperlative = { - nice: 'nicest', - late: 'latest', - hard: 'hardest', - inner: 'innermost', - outer: 'outermost', - far: 'furthest', - worse: 'worst', - bad: 'worst', - good: 'best', - big: 'biggest', - large: 'largest' -}; - -const combine = function(lexicon, obj, tag) { - let keys = Object.keys(obj); - for (let i = 0; i < keys.length; i++) { - lexicon[keys[i]] = 'Comparable'; - if (lexicon[obj[keys[i]]] === undefined) { - lexicon[obj[keys[i]]] = tag; - } - } - return lexicon; -}; -let lexicon = combine({}, toSuperlative, 'Superlative'); -lexicon = combine(lexicon, toComparative, 'Comparative'); -lexicon = combine(lexicon, toAdverb, 'Adverb'); - -module.exports = { - lexicon: lexicon, - toAdverb: toAdverb, - toComparative: toComparative, - toSuperlative: toSuperlative -}; diff --git a/src/world/more-data/misc.js b/src/world/more-data/misc.js deleted file mode 100644 index f49f8ab68..000000000 --- a/src/world/more-data/misc.js +++ /dev/null @@ -1,18 +0,0 @@ -//words that can't be compressed, for whatever reason -module.exports = { - '20th century fox': 'Organization', - '3m': 'Organization', - '7 eleven': 'Organization', - '7-eleven': 'Organization', - g8: 'Organization', - 'motel 6': 'Organization', - vh1: 'Organization', - q1: 'Date', - q2: 'Date', - q3: 'Date', - q4: 'Date', - //misc - records: 'Plural', - '&': 'Conjunction', - was: ['Copula', 'PastTense'] -}; diff --git a/src/world/more-data/numbers.js b/src/world/more-data/numbers.js deleted file mode 100644 index 269f912dc..000000000 --- a/src/world/more-data/numbers.js +++ /dev/null @@ -1,156 +0,0 @@ -'use strict'; -const cardinal = { - ones: { - // 'a': 1, - zero: 0, - one: 1, - two: 2, - three: 3, - four: 4, - five: 5, - six: 6, - seven: 7, - eight: 8, - nine: 9 - }, - teens: { - ten: 10, - eleven: 11, - twelve: 12, - thirteen: 13, - fourteen: 14, - fifteen: 15, - sixteen: 16, - seventeen: 17, - eighteen: 18, - nineteen: 19 - }, - tens: { - twenty: 20, - thirty: 30, - forty: 40, - fourty: 40, //support typo - fifty: 50, - sixty: 60, - seventy: 70, - eighty: 80, - ninety: 90 - }, - multiples: { - hundred: 1e2, - thousand: 1e3, - // grand: 1e3, - million: 1e6, - billion: 1e9, - trillion: 1e12, - quadrillion: 1e15, - quintillion: 1e18, - sextillion: 1e21, - septillion: 1e24 - } -}; - -const ordinal = { - ones: { - zeroth: 0, - first: 1, - second: 2, - third: 3, - fourth: 4, - fifth: 5, - sixth: 6, - seventh: 7, - eighth: 8, - ninth: 9 - }, - teens: { - tenth: 10, - eleventh: 11, - twelfth: 12, - thirteenth: 13, - fourteenth: 14, - fifteenth: 15, - sixteenth: 16, - seventeenth: 17, - eighteenth: 18, - nineteenth: 19 - }, - tens: { - twentieth: 20, - thirtieth: 30, - fortieth: 40, - fourtieth: 40, //support typo - fiftieth: 50, - sixtieth: 60, - seventieth: 70, - eightieth: 80, - ninetieth: 90 - }, - multiples: { - hundredth: 1e2, - thousandth: 1e3, - millionth: 1e6, - billionth: 1e9, - trillionth: 1e12, - quadrillionth: 1e15, - quintillionth: 1e18, - sextillionth: 1e21, - septillionth: 1e24 - } -}; - -//used for the units -const prefixes = { - yotta: 1, - zetta: 1, - exa: 1, - peta: 1, - tera: 1, - giga: 1, - mega: 1, - kilo: 1, - hecto: 1, - deka: 1, - deci: 1, - centi: 1, - milli: 1, - micro: 1, - nano: 1, - pico: 1, - femto: 1, - atto: 1, - zepto: 1, - yocto: 1, - - square: 1, - cubic: 1, - quartic: 1 -}; - -//create an easy mapping between ordinal-cardinal -let toOrdinal = {}; -let toCardinal = {}; -let lexicon = {}; -Object.keys(ordinal).forEach(k => { - let ord = Object.keys(ordinal[k]); - let card = Object.keys(cardinal[k]); - for (let i = 0; i < card.length; i++) { - toOrdinal[card[i]] = ord[i]; - toCardinal[ord[i]] = card[i]; - lexicon[ord[i]] = ['Ordinal', 'TextValue']; - lexicon[card[i]] = ['Cardinal', 'TextValue']; - if (k === 'multiples') { - lexicon[ord[i]].push('Multiple'); - lexicon[card[i]].push('Multiple'); - } - } -}); - -module.exports = { - toOrdinal: toOrdinal, - toCardinal: toCardinal, - cardinal: cardinal, - ordinal: ordinal, - prefixes: prefixes, - lexicon: lexicon -}; diff --git a/src/world/more-data/orgWords.js b/src/world/more-data/orgWords.js deleted file mode 100644 index bc26b83e5..000000000 --- a/src/world/more-data/orgWords.js +++ /dev/null @@ -1,210 +0,0 @@ -//nouns that also signal the title of an unknown organization -//todo remove/normalize plural forms -const orgWords = [ - 'administration', - 'agence', - 'agences', - 'agencies', - 'agency', - 'airlines', - 'airways', - 'army', - 'assoc', - 'associates', - 'association', - 'assurance', - 'authority', - 'autorite', - 'aviation', - 'bank', - 'banque', - 'board', - 'boys', - 'brands', - 'brewery', - 'brotherhood', - 'brothers', - 'building society', - 'bureau', - 'cafe', - 'caisse', - 'capital', - 'care', - 'cathedral', - 'center', - 'central bank', - 'centre', - 'chemicals', - 'choir', - 'chronicle', - 'church', - 'circus', - 'clinic', - 'clinique', - 'club', - 'co', - 'coalition', - 'coffee', - 'collective', - 'college', - 'commission', - 'committee', - 'communications', - 'community', - 'company', - 'comprehensive', - 'computers', - 'confederation', - 'conference', - 'conseil', - 'consulting', - 'containers', - 'corporation', - 'corps', - 'corp', - 'council', - 'crew', - 'daily news', - 'data', - 'departement', - 'department', - 'department store', - 'departments', - 'design', - 'development', - 'directorate', - 'division', - 'drilling', - 'education', - 'eglise', - 'electric', - 'electricity', - 'energy', - 'ensemble', - 'enterprise', - 'enterprises', - 'entertainment', - 'estate', - 'etat', - 'evening news', - 'faculty', - 'federation', - 'financial', - 'fm', - 'foundation', - 'fund', - 'gas', - 'gazette', - 'girls', - 'government', - 'group', - 'guild', - 'health authority', - 'herald', - 'holdings', - 'hospital', - 'hotel', - 'hotels', - 'inc', - 'industries', - 'institut', - 'institute', - 'institute of technology', - 'institutes', - 'insurance', - 'international', - 'interstate', - 'investment', - 'investments', - 'investors', - 'journal', - 'laboratory', - 'labs', - // 'law', - 'liberation army', - 'limited', - 'local authority', - 'local health authority', - 'machines', - 'magazine', - 'management', - 'marine', - 'marketing', - 'markets', - 'media', - 'memorial', - 'mercantile exchange', - 'ministere', - 'ministry', - 'military', - 'mobile', - 'motor', - 'motors', - 'musee', - 'museum', - // 'network', - 'news', - 'news service', - 'observatory', - 'office', - 'oil', - 'optical', - 'orchestra', - 'organization', - 'partners', - 'partnership', - // 'party', - 'people\'s party', - 'petrol', - 'petroleum', - 'pharmacare', - 'pharmaceutical', - 'pharmaceuticals', - 'pizza', - 'plc', - 'police', - 'polytechnic', - 'post', - 'power', - 'press', - 'productions', - 'quartet', - 'radio', - 'regional authority', - 'regional health authority', - 'reserve', - 'resources', - 'restaurant', - 'restaurants', - 'savings', - 'school', - 'securities', - 'service', - 'services', - 'social club', - 'societe', - 'society', - 'sons', - 'standard', - 'state police', - 'state university', - 'stock exchange', - 'subcommittee', - 'syndicat', - 'systems', - 'telecommunications', - 'telegraph', - 'television', - 'times', - 'tribunal', - 'tv', - 'union', - 'university', - 'utilities', - 'workers' -]; - -module.exports = orgWords.reduce(function(h, str) { - h[str] = 'Noun'; - return h; -}, {}); diff --git a/src/world/tags/index.js b/src/world/tags/index.js new file mode 100644 index 000000000..bfac2b2da --- /dev/null +++ b/src/world/tags/index.js @@ -0,0 +1,24 @@ +const nouns = require('./tags/nouns') +const verbs = require('./tags/verbs') +const values = require('./tags/values') +const misc = require('./tags/misc') +const inferTags = require('./inference/index') + +//extend tagset with new tags +const addIn = function(obj, tags) { + Object.keys(obj).forEach(k => { + tags[k] = obj[k] + }) +} + +const build = () => { + let tags = {} + addIn(nouns, tags) + addIn(verbs, tags) + addIn(values, tags) + addIn(misc, tags) + // do the graph-stuff + tags = inferTags(tags) + return tags +} +module.exports = build() diff --git a/src/world/tags/inference/_color.js b/src/world/tags/inference/_color.js new file mode 100644 index 000000000..f63586738 --- /dev/null +++ b/src/world/tags/inference/_color.js @@ -0,0 +1,37 @@ +// i just made these up +const colorMap = { + Noun: 'blue', + + Verb: 'green', + Negative: 'green', + + Date: 'red', + Value: 'red', + + Adjective: 'magenta', + + Preposition: 'cyan', + Conjunction: 'cyan', + Determiner: 'cyan', + Adverb: 'cyan', +} + +/** add a debug color to some tags */ +const addColors = function(tags) { + Object.keys(tags).forEach(k => { + if (colorMap[k]) { + tags[k].color = colorMap[k] + return + } + tags[k].isA.some(t => { + if (colorMap[t]) { + tags[k].color = colorMap[t] + return true + } + return false + }) + }) + return tags +} + +module.exports = addColors diff --git a/src/world/tags/inference/_isA.js b/src/world/tags/inference/_isA.js new file mode 100644 index 000000000..2ab615ddf --- /dev/null +++ b/src/world/tags/inference/_isA.js @@ -0,0 +1,21 @@ +const unique = function(arr) { + return arr.filter((v, i, a) => a.indexOf(v) === i) +} + +//add 'downward' tags (that immediately depend on this one) +const inferIsA = function(tags) { + Object.keys(tags).forEach(k => { + let tag = tags[k] + let len = tag.isA.length + for (let i = 0; i < len; i++) { + let down = tag.isA[i] + if (tags[down]) { + tag.isA = tag.isA.concat(tags[down].isA) + } + } + // clean it up + tag.isA = unique(tag.isA) + }) + return tags +} +module.exports = inferIsA diff --git a/src/world/tags/inference/_lineage.js b/src/world/tags/inference/_lineage.js new file mode 100644 index 000000000..14776e2bc --- /dev/null +++ b/src/world/tags/inference/_lineage.js @@ -0,0 +1,16 @@ +// a lineage is all 'incoming' tags that have this as 'isA' +const inferLineage = function(tags) { + let keys = Object.keys(tags) + keys.forEach(k => { + let tag = tags[k] + tag.lineage = [] + // find all tags with it in their 'isA' set + for (let i = 0; i < keys.length; i++) { + if (tags[keys[i]].isA.indexOf(k) !== -1) { + tag.lineage.push(keys[i]) + } + } + }) + return tags +} +module.exports = inferLineage diff --git a/src/world/tags/inference/_notA.js b/src/world/tags/inference/_notA.js new file mode 100644 index 000000000..04c2b4c5d --- /dev/null +++ b/src/world/tags/inference/_notA.js @@ -0,0 +1,31 @@ +const unique = function(arr) { + return arr.filter((v, i, a) => a.indexOf(v) === i) +} + +// crawl the tag-graph and infer any conflicts +// faster than doing this at tag-time +const inferNotA = function(tags) { + let keys = Object.keys(tags) + keys.forEach(k => { + let tag = tags[k] + tag.notA = tag.notA || [] + tag.isA.forEach(down => { + if (tags[down] && tags[down].notA) { + // borrow its conflicts + let notA = typeof tags[down].notA === 'string' ? [tags[down].isA] : tags[down].notA || [] + tag.notA = tag.notA.concat(notA) + } + }) + // any tag that lists us as a conflict, we conflict it back. + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + if (tags[key].notA.indexOf(k) !== -1) { + tag.notA.push(key) + } + } + // clean it up + tag.notA = unique(tag.notA) + }) + return tags +} +module.exports = inferNotA diff --git a/src/world/tags/inference/index.js b/src/world/tags/inference/index.js new file mode 100644 index 000000000..1dc88a7c7 --- /dev/null +++ b/src/world/tags/inference/index.js @@ -0,0 +1,38 @@ +const inferColor = require('./_color') +const inferIsA = require('./_isA') +const inferNotA = require('./_notA') +const lineage = require('./_lineage') + +const validate = function(tags) { + // cleanup format + Object.keys(tags).forEach(k => { + let tag = tags[k] + // ensure isA is an array + tag.isA = tag.isA || [] + if (typeof tag.isA === 'string') { + tag.isA = [tag.isA] + } + // ensure notA is an array + tag.notA = tag.notA || [] + if (typeof tag.notA === 'string') { + tag.notA = [tag.notA] + } + }) + return tags +} + +// build-out the tag-graph structure +const inferTags = function(tags) { + // validate data + tags = validate(tags) + // build its 'down tags' + tags = inferIsA(tags) + // infer the conflicts + tags = inferNotA(tags) + // debug tag color + tags = inferColor(tags) + // find incoming links + tags = lineage(tags) + return tags +} +module.exports = inferTags diff --git a/src/world/tags/tags/misc.js b/src/world/tags/tags/misc.js new file mode 100644 index 000000000..b677f762e --- /dev/null +++ b/src/world/tags/tags/misc.js @@ -0,0 +1,103 @@ +const anything = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Value'] + +module.exports = { + //--Adjectives-- + Adjective: { + notA: ['Noun', 'Verb', 'Adverb', 'Value'], + }, + // adjectives that can conjugate + Comparable: { + isA: ['Adjective'], + }, + // better + Comparative: { + isA: ['Adjective'], + }, + // best + Superlative: { + isA: ['Adjective'], + notA: ['Comparative'], + }, + + NumberRange: { + isA: ['Contraction'], + }, + Adverb: { + notA: ['Noun', 'Verb', 'Adjective', 'Value'], + }, + + // Dates: + //not a noun, but usually is + Date: { + notA: ['Verb', 'Conjunction', 'Adverb', 'Preposition', 'Adjective'], + }, + Month: { + isA: ['Date', 'Singular'], + notA: ['Year', 'WeekDay', 'Time'], + }, + WeekDay: { + isA: ['Date', 'Noun'], + }, + + //glue + Determiner: { + notA: anything, + }, + Conjunction: { + notA: anything, + }, + Preposition: { + notA: anything, + }, + + // what, who, why + QuestionWord: { + notA: ['Determiner'], + }, + + // peso, euro + Currency: {}, + // ughh + Expression: { + notA: ['Noun', 'Adjective', 'Verb', 'Adverb'], + }, + // dr. + Abbreviation: {}, + + // internet tags + Url: { + notA: ['HashTag', 'PhoneNumber', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'], + }, + PhoneNumber: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention', 'Email'], + }, + HashTag: {}, + AtMention: { + isA: ['Noun'], + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'Email'], + }, + Emoji: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'], + }, + Emoticon: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'], + }, + Email: { + notA: ['HashTag', 'Verb', 'Adjective', 'Value', 'AtMention'], + }, + + //non-exclusive + Auxiliary: { + notA: ['Noun', 'Adjective', 'Value'], + }, + Acronym: { + notA: ['Plural', 'RomanNumeral'], + }, + Negative: { + notA: ['Noun', 'Adjective', 'Value'], + }, + // if, unless, were + Condition: { + notA: ['Verb', 'Adjective', 'Noun', 'Value'], + }, +} diff --git a/src/world/tags/tags/nouns.js b/src/world/tags/tags/nouns.js new file mode 100644 index 000000000..931dc346b --- /dev/null +++ b/src/world/tags/tags/nouns.js @@ -0,0 +1,115 @@ +const entity = ['Person', 'Place', 'Organization'] + +module.exports = { + Noun: { + notA: ['Verb', 'Adjective', 'Adverb'], + }, + // - singular + Singular: { + isA: 'Noun', + notA: 'Plural', + }, + //a specific thing that's capitalized + ProperNoun: { + isA: 'Noun', + }, + + // -- people + Person: { + isA: ['ProperNoun', 'Singular'], + notA: ['Place', 'Organization'], + }, + FirstName: { + isA: 'Person', + }, + MaleName: { + isA: 'FirstName', + notA: ['FemaleName', 'LastName'], + }, + FemaleName: { + isA: 'FirstName', + notA: ['MaleName', 'LastName'], + }, + LastName: { + isA: 'Person', + notA: ['FirstName'], + }, + Honorific: { + isA: 'Noun', + notA: ['FirstName', 'LastName'], + }, + + // -- places + Place: { + isA: 'Singular', + notA: ['Person', 'Organization'], + }, + Country: { + isA: ['Place', 'ProperNoun'], + notA: ['City'], + }, + City: { + isA: ['Place', 'ProperNoun'], + notA: ['Country'], + }, + Region: { + isA: ['Place', 'ProperNoun'], + }, + Address: { + isA: 'Place', + }, + + //---Orgs--- + Organization: { + isA: ['Singular', 'ProperNoun'], + notA: ['Person', 'Place'], + }, + SportsTeam: { + isA: 'Organization', + }, + School: { + isA: 'Organization', + }, + Company: { + isA: 'Organization', + }, + + // - plural + Plural: { + isA: 'Noun', + notA: ['Singular'], + }, + //(not plural or singular) + Uncountable: { + isA: 'Noun', + }, + Pronoun: { + isA: 'Noun', + notA: entity, + }, + //a word for someone doing something -'plumber' + Actor: { + isA: 'Noun', + notA: entity, + }, + //a gerund-as-noun - 'swimming' + Activity: { + isA: 'Noun', + notA: ['Person', 'Place'], + }, + //'kilograms' + Unit: { + isA: 'Noun', + notA: entity, + }, + //'Canadians' + Demonym: { + isA: ['Noun', 'ProperNoun'], + notA: entity, + }, + //`john's` + Possessive: { + isA: 'Noun', + // notA: 'Pronoun', + }, +} diff --git a/src/world/tags/tags/values.js b/src/world/tags/tags/values.js new file mode 100644 index 000000000..669072ecf --- /dev/null +++ b/src/world/tags/tags/values.js @@ -0,0 +1,31 @@ +module.exports = { + Value: { + notA: ['Verb', 'Adjective', 'Adverb'], + }, + Ordinal: { + isA: 'Value', + notA: ['Cardinal'], + }, + Cardinal: { + isA: 'Value', + notA: ['Ordinal'], + }, + RomanNumeral: { + isA: 'Cardinal', //can be a person, too + notA: ['Ordinal', 'TextValue'], + }, + TextValue: { + isA: 'Value', + notA: ['NumericValue'], + }, + NumericValue: { + isA: 'Value', + notA: ['TextValue'], + }, + Money: { + isA: 'Cardinal', + }, + Percent: { + isA: 'Value', + }, +} diff --git a/src/world/tags/tags/verbs.js b/src/world/tags/tags/verbs.js new file mode 100644 index 000000000..36b2c8287 --- /dev/null +++ b/src/world/tags/tags/verbs.js @@ -0,0 +1,59 @@ +module.exports = { + Verb: { + notA: ['Noun', 'Adjective', 'Adverb', 'Value'], + }, + // walks + PresentTense: { + isA: 'Verb', + notA: ['PastTense', 'Copula', 'FutureTense'], + }, + // neutral form - 'walk' + Infinitive: { + isA: 'PresentTense', + notA: ['PastTense', 'Gerund'], + }, + // walking + Gerund: { + isA: 'PresentTense', + notA: ['PastTense', 'Copula', 'FutureTense'], + }, + // walked + PastTense: { + isA: 'Verb', + notA: ['FutureTense'], + }, + // will walk + FutureTense: { + isA: 'Verb', + }, + + // is + Copula: { + isA: 'Verb', + }, + // would have + Modal: { + isA: 'Verb', + notA: ['Infinitive'], + }, + // had walked + PerfectTense: { + isA: 'Verb', + notA: 'Gerund', + }, + Pluperfect: { + isA: 'Verb', + }, + // shown + Participle: { + isA: 'Verb', + }, + // show up + PhrasalVerb: { + isA: 'Verb', + }, + //'up' part + Particle: { + isA: 'PhrasalVerb', + }, +} diff --git a/src/world/unpack/conjugations.js b/src/world/unpack/conjugations.js deleted file mode 100644 index 08ccb2c06..000000000 --- a/src/world/unpack/conjugations.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -//supported verb forms: -const forms = [ - null, - 'PastTense', - 'PresentTense', - 'Gerund', - 'Participle', -]; -// -const unpackVerbs = function(str) { - let verbs = str.split('|'); - return verbs.reduce((h, s) => { - let parts = s.split(':'); - let prefix = parts[0]; - let ends = parts[1].split(','); - //grab the infinitive - let inf = prefix + ends[0]; - if (ends[0] === '_') { - inf = prefix; - } - h[inf] = {}; - //we did the infinitive, now do the rest: - for (let i = 1; i < forms.length; i++) { - let word = parts[0] + ends[i]; - if (ends[i] === '_') { - word = parts[0]; - } - if (ends[i]) { - h[inf][forms[i]] = word; - } - } - return h; - }, {}); -}; -module.exports = unpackVerbs; diff --git a/src/world/unpack/index.js b/src/world/unpack/index.js deleted file mode 100644 index 3f3ca6c70..000000000 --- a/src/world/unpack/index.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; -const unpack = { - words: require('efrt-unpack'), - plurals: require('./plurals'), - conjugations: require('./conjugations'), - keyValue: require('./key-value') -}; -/* - == supported plugin fields == - name - words - efrt packed - tags - stringified - regex - key-value - patterns - key-value - plurals - plural-unpack - conjugations - conjugation-unpack -*/ - -const unpackPlugin = function(str) { - let obj = str; - if (typeof str === 'string') { - obj = JSON.parse(str); - } - //words is packed with efrt - if (obj.words && typeof obj.words === 'string') { - obj.words = unpack.words(obj.words); - } - //patterns is pivoted as key-value - if (obj.patterns) { - obj.patterns = unpack.keyValue(obj.patterns); - } - //regex, too - if (obj.regex) { - obj.regex = unpack.keyValue(obj.regex); - } - //plurals is packed in a ad-hoc way - if (obj.plurals && typeof obj.plurals === 'string') { - obj.plurals = unpack.plurals(obj.plurals); - } - //conjugations is packed in another ad-hoc way - if (obj.conjugations && typeof obj.conjugations === 'string') { - obj.conjugations = unpack.conjugations(obj.conjugations); - } - return obj; -}; -module.exports = unpackPlugin; diff --git a/src/world/unpack/key-value.js b/src/world/unpack/key-value.js deleted file mode 100644 index 8ba042d42..000000000 --- a/src/world/unpack/key-value.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -//pivot k:[val,val] -> val:k, val:k -const keyValue = function(obj) { - let keys = Object.keys(obj); - let isCompressed = true; - if (keys[0] && typeof obj[keys[0]] === 'string') { - isCompressed = false; - } - return keys.reduce((h, k) => { - if (isCompressed === true) { - let arr = obj[k]; - arr.forEach((a) => { - if (h[a]) { - //convert val to an array - if (typeof h[a] === 'string') { - h[a] = [h[a]]; - } - //add it - h[a].push(k); - } else { - h[a] = k; - } - }); - } else { - h[k] = obj[k]; - } - return h; - }, {}); -}; -module.exports = keyValue; diff --git a/src/world/unpack/plurals.js b/src/world/unpack/plurals.js deleted file mode 100644 index ea67ea78d..000000000 --- a/src/world/unpack/plurals.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; -const unpackPlurals = function(str) { - return str.split(/,/g).reduce((h, s) => { - let arr = s.split(/\|/g); - if (arr.length === 3) { - h[arr[0] + arr[1]] = arr[0] + arr[2]; - } else if (arr.length === 2) { - h[arr[0]] = arr[0] + arr[1]; - } else { - h[arr[0]] = arr[0]; - } - return h; - }, {}); -}; -module.exports = unpackPlurals; diff --git a/test/client/index.html b/test/client/index.html deleted file mode 100644 index 9fb662b6d..000000000 --- a/test/client/index.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - -

-  
-    browser-based test of compromise
-    

running ...

-
- - - - diff --git a/test/unit/docs/docs.test.js b/test/unit/docs/docs.test.js deleted file mode 100644 index 97744e5ee..000000000 --- a/test/unit/docs/docs.test.js +++ /dev/null @@ -1,83 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var docs = require('../../../docs/api'); -var freshPrince = require('../lib/freshPrince'); - -test('generic-methods-run:', function(t) { - var getters = { - found: true, - length: true - }; - var skip = { - whitespace: true, - insertAt: true, - debug: true, //too noisy - forEach: true, - filter: true, - map: true, - find: true, - reduce: true, - }; - var needString = { - insertBefore: true, - insertAfter: true, - match: true, - splitOn: true, - splitBefore: true, - splitAfter: true - }; - - var r = nlp(freshPrince); - Object.keys(docs.generic).forEach(function(type) { - Object.keys(docs.generic[type]).forEach(function(fn) { - //simply call this method to see if it throws an error - var func = function() { - if (getters[fn]) { - //getters dont have a '()' - return r[fn]; - } else if (needString[fn]) { - //give a dummy param - return r[fn]('fun'); - } else if (skip[fn]) { - //these are too fancy to call - return typeof r[fn] === 'function'; - } else { - //call this method - return r[fn](); - } - }; - - t.doesNotThrow(func, true, fn); - }); - }); - t.end(); -}); - -test('subsets-methods-exist:', function(t) { - var addParam = { - sentences: { - append: true, - prepend: true - } - }; - var r = nlp(freshPrince); - Object.keys(docs.subsets).forEach(function(subset) { - //each subset - t.doesNotThrow(function() { - return r[subset](), true, subset + '()'; - }); - //each method in that subset - Object.keys(docs.subsets[subset]).forEach(function(method) { - var func = function() { - if (addParam[subset] && addParam[subset][method]) { - r[subset]()[method]('fun'); - } else { - r[subset]()[method](); - } - }; - var msg = subset + '().' + method; - t.doesNotThrow(func, true, msg); - }); - }); - t.end(); -}); diff --git a/test/unit/docs/eval.test.js b/test/unit/docs/eval.test.js deleted file mode 100644 index 2a738a4bd..000000000 --- a/test/unit/docs/eval.test.js +++ /dev/null @@ -1,41 +0,0 @@ -var test = require('tape'); -var docs = require('../../../docs/api'); -//gotta include this for the 'eval()' -var nlp = require('../lib/nlp'); // eslint-disable-line no-unused-vars - -var flat = []; -Object.keys(docs.generic).forEach(k => { - var obj = docs.generic[k]; - Object.keys(obj).forEach(k2 => { - obj[k2].title = k + '().' + k2 + '()'; - flat.push(obj[k2]); - }); -}); -Object.keys(docs.subsets).forEach(k => { - var obj = docs.subsets[k]; - Object.keys(obj).forEach(k2 => { - obj[k2].title = k + '().' + k2 + '()'; - flat.push(obj[k2]); - }); -}); - -test('docs-eval:', function(t) { - flat.forEach(o => { - var code = o.example; - try { - code = `(function(){ - ` + - code + - ` - })()`; - eval(code); - t.ok(true, o.title); - // t.doesNotThrow(eval(code)) - } catch (e) { - console.log(o.title); - console.log(e); - t.fail(o.title); - } - }); - t.end(); -}); diff --git a/test/unit/extend/addConjugations.test.js b/test/unit/extend/addConjugations.test.js deleted file mode 100644 index 537719e25..000000000 --- a/test/unit/extend/addConjugations.test.js +++ /dev/null @@ -1,23 +0,0 @@ - -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('addConjugations', function(t) { - var conjugations = { - woo: { - PastTense: 'wooed' - } - }; - nlp.addConjugations(conjugations); - var doc = nlp('woo the crush'); - t.equal(doc.verbs().length, 1, 'has inf in lexicon'); - - doc.verbs().toPastTense(); - t.equal(doc.out(), 'wooed the crush', 'conjugated from infinitive'); - t.equal(doc.verbs().length, 1, 'still has 1 verb'); - - doc.verbs().toInfinitive(); - t.equal(doc.out(), 'woo the crush', 'conjugated back tp infinitive'); - - t.end(); -}); diff --git a/test/unit/extend/addPatterns.test.js b/test/unit/extend/addPatterns.test.js deleted file mode 100644 index 62f9e6dee..000000000 --- a/test/unit/extend/addPatterns.test.js +++ /dev/null @@ -1,16 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('addpatterns-test', function(t) { - var patterns = { - 'master of #Noun': 'Person', - 'captain of the #Noun+': 'Person', - }; - nlp.addPatterns(patterns); - var doc = nlp('he is the master of ceremonies and captain of the Utah baseball team'); - var arr = doc.people().data(); - t.equal(arr.length, 2, 'found both'); - t.equal(arr[0].normal, 'master of ceremonies', 'first one'); - t.equal(arr[1].normal, 'captain of the utah baseball team', 'second-one'); - t.end(); -}); diff --git a/test/unit/extend/addPlurals.test.js b/test/unit/extend/addPlurals.test.js deleted file mode 100644 index d4e1101a9..000000000 --- a/test/unit/extend/addPlurals.test.js +++ /dev/null @@ -1,25 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('addPlurals-test', function(t) { - var plurals = { - mather: 'mathii', - algebra: 'algebri' - }; - nlp.addPlurals(plurals); - var doc = nlp('the mather did many algebri'); - var arr = doc.nouns().data(); - t.equal(arr.length, 2, 'found both'); - t.equal(arr[0].singular, 'mather', 'singular-form'); - t.equal(arr[0].plural, 'mathii', 'plural-form'); - - t.equal(arr[1].singular, 'algebra', 'singular-form2'); - t.equal(arr[1].plural, 'algebri', 'plural-form2'); - - doc.nouns().toPlural(); - t.equal(doc.out(), 'the mathii did many algebri', 'toPlural'); - doc.nouns().toSingular(); - t.equal(doc.out(), 'the mather did many algebra', 'toSingular'); - - t.end(); -}); diff --git a/test/unit/extend/addTags.test.js b/test/unit/extend/addTags.test.js deleted file mode 100644 index 641772e8b..000000000 --- a/test/unit/extend/addTags.test.js +++ /dev/null @@ -1,95 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('tagset-change-isA-basic', function(t) { - nlp.addTags({ - Doctor: { - isA: 'Person' - } - }); - nlp.addWords({ - surgeon: 'Doctor', - 'surgeon general': 'Doctor' - }); - var doc = nlp('the surgeon operated'); - - //basic isA - t.equal(doc.match('#Doctor').out('normal'), 'surgeon', 'surgeon is a doctor'); - t.equal(doc.people().length, 1, 'doctor is a person'); - - doc = nlp('lkjsdf').tag('#Person'); - t.equal(doc.match('#Doctor').length, 0, 'person isnt a doctor, necessarily'); - - doc = nlp('lkjsdf').tag('#Doctor'); - t.equal(doc.match('#Person').length, 1, 'post-hoc tags work, too'); - - //multi-word - doc = nlp('the surgeon general operated'); - t.equal(doc.match('#Doctor').out('normal'), 'surgeon general', 'multi-word'); - t.equal(doc.match('#Person').out('normal'), 'surgeon general', 'multi-word-isA'); - t.end(); -}); - -test('tagset-change-isA', function(t) { - nlp.addTags({ - Doctor: { - isA: 'Person', - notA: ['Foo'] - } - }); - nlp.addWords({ - lkjj: 'Foo' - }); - var doc = nlp('he is lkjj'); - t.equal(doc.match('#Foo').out('normal'), 'lkjj', 'init-there'); - doc.match('lkjj').tag('#Doctor'); - - t.equal(doc.match('#Doctor').out('normal'), 'lkjj', 'doctor-tag-there'); - t.equal(doc.match('#Foo').out('normal'), '', 'foo-is-gone'); - - t.end(); -}); - -test('tagset-remove-downward', function(t) { - nlp.addTags({ - Doctor: { - isA: 'Person' - }, - Surgeon: { - isA: 'Doctor' - } - }); - var doc = nlp('george is a person.'); - doc.match('george').tag('Surgeon'); - - t.ok(doc.has('#Surgeon'), 'Surgeon-tag-there'); - t.ok(doc.has('#Doctor'), 'doctor-tag-there'); - t.ok(doc.has('#Person'), 'person-tag-there'); - - //remove one in the middle.. - doc.match('george').unTag('Person'); - t.ok(doc.has('#Person') === false, 'person-tag-gone'); - t.ok(doc.has('#Doctor') === false, 'doctor-tag-gone'); - t.ok(doc.has('#Surgeon') === false, 'Surgeon-tag-gone'); - t.end(); -}); - -test('tagset-remove-half-downward', function(t) { - nlp.addTags({ - Doctor: { - isA: 'Person' - }, - Surgeon: { - isA: 'Doctor' - } - }); - var doc = nlp('george is a person.'); - doc.match('george').tag('Surgeon'); - - //remove one just under the top.. - doc.match('george').unTag('Doctor'); - t.ok(doc.has('#Person') === true, 'person-tag-there'); - t.ok(doc.has('#Doctor') === false, 'doctor-tag-gone'); - t.ok(doc.has('#Surgeon') === false, 'Surgeon-tag-gone'); - t.end(); -}); diff --git a/test/unit/extend/addWords.test.js b/test/unit/extend/addWords.test.js deleted file mode 100644 index b7a266828..000000000 --- a/test/unit/extend/addWords.test.js +++ /dev/null @@ -1,25 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('persistent-lexicon-change', function(t) { - nlp = nlp.clone(); - var doc = nlp('he is James'); - t.equal(doc.places().length, 0, 'default-no-place'); - t.equal(doc.people().length, 1, 'default-one-person'); - - nlp.addWords({ - james: 'Place' - }); - doc = nlp('he is James'); - t.equal(doc.places().length, 1, 'now-one-place'); - t.equal(doc.people().length, 0, 'now-no-person'); - - nlp.addWords({ - foo: 'Place' - }); - doc = nlp('he is James'); - t.equal(doc.places().length, 1, 'still-one-place'); - t.equal(doc.people().length, 0, 'still-no-person'); - - t.end(); -}); diff --git a/test/unit/extend/clone.test.js b/test/unit/extend/clone.test.js deleted file mode 100644 index e4712058f..000000000 --- a/test/unit/extend/clone.test.js +++ /dev/null @@ -1,30 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('nlp.clone() -change original', function(t) { - var nlp2 = nlp.clone(); - t.ok(nlp('bat').has('#Noun'), 'nlp1-init'); - t.ok(nlp2('bat').has('#Noun'), 'nlp2-init'); - - //change nlp1 - nlp.addWords({ - bat: 'Man' - }); - t.ok(nlp('bat').has('#Man'), 'nlp1-changed'); - t.ok(nlp2('bat').has('#Man') === false, 'nlp2-unchanged'); - - //change nlp2 - nlp2.addWords({ - bat: 'ManTwo' - }); - t.ok(nlp('bat').has('#ManTwo') === false, 'nlp1-changed'); - t.ok(nlp2('bat').has('#ManTwo') === true, 'nlp2-unchanged'); - - //try nlp3 - var nlp3 = nlp.clone(); - t.ok(nlp3('bat').has('#Noun'), 'nlp3-normal-default'); - t.ok(nlp3('bat').has('#Man') === false, 'nlp3-normal'); - t.ok(nlp3('bat').has('#ManTwo') === false, 'nlp3-normal-again'); - - t.end(); -}); diff --git a/test/unit/extend/lexicon.test.js b/test/unit/extend/lexicon.test.js deleted file mode 100644 index 532948afb..000000000 --- a/test/unit/extend/lexicon.test.js +++ /dev/null @@ -1,43 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -var lexicon = { - 'Jardas al Abid': 'Place', - 'Umm Ar Rizam': 'Place', - Tobruk: 'Place' -}; - -test('user-lex-with-hyphenation:', function(t) { - var sentence = - 'A suicide attack hit the centre of Jardas-al-Abid killing one person (and the attacker) and injuring more than twenty.'; - var found = nlp(sentence, lexicon).places().data()[0] || {}; - t.equal('jardas al abid', found.normal, 'found-place1'); - t.equal(lexicon, lexicon, 'lexicon-unchanged'); - t.end(); -}); - -test('user-lex-with-possessive form:', function(t) { - var sentence = - "A suicide attack hit Jardas al Abid's center killing one person (and the attacker) and injuring more than twenty."; - var found = nlp(sentence, lexicon).places().data()[0] || {}; - t.equal("jardas al abid's", found.normal, 'found-place2'); - t.equal(lexicon, lexicon, 'lexicon-unchanged'); - t.end(); -}); - -test('user-lex-with-proper name in front:', function(t) { - var sentence = - "A suicide attack hit Lybia's Jardas al Abid city killing one person (and the attacker) and injuring more than twenty."; - var found = nlp(sentence, lexicon).places().data()[0] || {}; - t.equal('jardas al abid', found.normal, 'found-place3'); - t.equal(lexicon, lexicon, 'lexicon-unchanged'); - t.end(); -}); - -test('user-lex-with-punctuation:', function(t) { - var sentence = 'A suicide attack hit Jardas al Abid, which killed one person (and the attacker) and injured more than twenty.'; - var found = nlp(sentence, lexicon).places().data()[0] || {}; - t.equal('jardas al abid', found.normal, 'found-place4'); - t.equal(lexicon, lexicon, 'lexicon-unchanged'); - t.end(); -}); diff --git a/test/unit/extend/plugin.test.js b/test/unit/extend/plugin.test.js deleted file mode 100644 index 582c6c80f..000000000 --- a/test/unit/extend/plugin.test.js +++ /dev/null @@ -1,29 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('basic-plugin', function(t) { - var plugin = { - words: { - trex: 'Dinosaur' - }, - tags: { - Dinosaur: { - isA: 'Animal' - }, - Animal: { - isA: 'Noun' - } - }, - regex: { - uuu: 'Exaggeration' - } - }; - nlp.plugin(plugin); - var doc = nlp('i saw a HUUUUGE trex'); - - t.equal(doc.match('#Exaggeration').out('normal'), 'huuuuge', 'regex-works'); - t.equal(doc.match('#Dinosaur').out('normal'), 'trex', 'lexicon-works'); - t.equal(doc.match('#Animal').out('normal'), 'trex', 'tagset-works'); - - t.end(); -}); diff --git a/test/unit/extend/tagset.test.js b/test/unit/extend/tagset.test.js deleted file mode 100644 index c549d588d..000000000 --- a/test/unit/extend/tagset.test.js +++ /dev/null @@ -1,34 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('extend-tagset-flat', function(t) { - var tagSet = { - Color: {} - }; - var lexicon = { - 'mother of pearl': 'Color' - }; - nlp.addTags(tagSet); - var m = nlp('it is mother of pearl', lexicon).match('#Color+'); - t.equal(m.out('normal'), 'mother of pearl', 'text found'); - t.ok(m.has('#Noun'), 'it does not get in the way of the tagger'); - t.end(); -}); - -test('extend-tagset-nested', function(t) { - var tagSet = { - Color: {}, - OffWhite: { - isA: 'Color' - }, - }; - nlp.addTags(tagSet); - var lexicon = { - 'mother of pearl': 'OffWhite' - }; - var m = nlp('it is mother of pearl', lexicon).match('#OffWhite'); - t.equal(m.out('normal'), 'mother of pearl', 'text found'); - t.ok(m.has('#Noun'), 'it does not get in the way of the tagger'); - t.ok(m.has('#Color'), 'has isA tag, too'); - t.end(); -}); diff --git a/test/unit/extend/tokenize.test.js b/test/unit/extend/tokenize.test.js deleted file mode 100644 index 7123969c0..000000000 --- a/test/unit/extend/tokenize.test.js +++ /dev/null @@ -1,43 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('tokenize() runs without pos-tagging', function(t) { - var str = 'Miss Hoover, I glued my head to my shoulder.'; - var r = nlp.tokenize(str); - t.equal(r.out('text'), str, 'tokenize output is same'); - - t.equal(r.list.length, 1, 'sentence-parser-working'); - - var found = r.match('#Noun').found; - t.equal(found, false, 'no sneaky-tagging'); - - t.end(); -}); -test('em-dash, en-dash', function(t) { - // '-': //dash - // '–': //en-dash - // '—': //em-dash - var doc = nlp('fun-time'); - t.equal(doc.terms().length, 2, 'dash'); - doc = nlp('fun–time'); - t.equal(doc.terms().length, 2, 'en-dash'); - doc = nlp('fun—time'); - t.equal(doc.terms().length, 2, 'em-dash'); - - //not a full word, either - doc = nlp('fun - time'); - t.equal(doc.terms().length, 2, 'dash-word'); - doc = nlp('fun – time'); - t.equal(doc.terms().length, 2, 'en-dash-word'); - doc = nlp('fun — time'); - t.equal(doc.terms().length, 2, 'em-dash-word'); - - //numeric forms are split, but contractions too - doc = nlp('20-20'); - t.equal(doc.terms().length, 3, 'dash-num'); - doc = nlp('20–20'); - t.equal(doc.terms().length, 3, 'en-dash-num'); - doc = nlp('20—20'); - t.equal(doc.terms().length, 3, 'em-dash-num'); - t.end(); -}); diff --git a/test/unit/lib/fns.js b/test/unit/lib/fns.js deleted file mode 100644 index bf1863450..000000000 --- a/test/unit/lib/fns.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict' - -var pad = function(str, width, char) { - char = char || '.' - str = str.toString() - while (str.length < width) { - str += char - } - return str -} - -//helpers to make test output messages nicer -var str_test = function(got, input, want, t) { - var msg = pad("'" + got + "'", 20) + "(want: '" + want + "' )" //'\'' + input + - t.equal(got, want, msg) - return -} - -var arr_test = function(got, input, want, t) { - got = JSON.stringify(got) - want = JSON.stringify(want) - var msg = pad("'" + got + "'") + " (want: '" + want + "' )" //'\'' + input + - t.equal(got, want, msg) - return -} - -var has_pos = function(r, tags) { - var terms = r.terms() - for (var i = 0; i < terms.list.length; i++) { - var t = terms.list[i].terms[0] - if (!t.tags[tags[i]]) { - return false - } - } - return true -} - -var pos_test = function(r, tags, t) { - var str = '' - var got = r - .terms() - .list.map(function(ts) { - var term = ts.terms[0] - str += ' ' + term.normal - return Object.keys(term.tags)[0] - }) - .join(', ') - var msg = pad('"' + str.trim() + '"', 30) + pad(tags.join(', '), 45) + got - t.equal(has_pos(r, tags), true, msg) - return -} - -var terms_test = function(terms, want, t, isText) { - var str = '' - var got = terms.map(function(term) { - str += ' ' + term.text - if (isText) { - return term.text - } - return term.normal - }) - var msg = pad('"' + str + '"', 38) + ' got: [' + got.join(',') + '] want: [' + want.join(',') + ']' - t.deepEqual(got, want, msg) -} - -var isArray = function(someVar) { - if (Object.prototype.toString.call(someVar) === '[object Array]') { - return true - } - return false -} - -module.exports = { - str_test: str_test, - pos_test: pos_test, - terms_test: terms_test, - arr_test: arr_test, - isArray: isArray -} diff --git a/test/unit/lib/freshPrince.js b/test/unit/lib/freshPrince.js deleted file mode 100644 index 1e9f6a858..000000000 --- a/test/unit/lib/freshPrince.js +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = `Now this is a story all about how my life got flipped-turned upside down. -and I'd like to take a minute, just sit right there, I'll tell you how I became the prince of a town called Bel-Air. - -In west Philadelphia born and raised, on the playground was where I spent most of my days. -Chillin' out maxin' relaxin' all cool, and all shooting some b-ball outside of the school. -When a couple of guys who were up to no good started making trouble in my neighborhood, -I got in one little fight and my mom got scared, she said, "You're movin' with your auntie and uncle in Bel-Air". - -I begged and pleaded with her day after day but she packed my suitcase and sent me on my way. -She gave me a kiss and then she gave me my ticket. I put my Walkman on and said, "I might as well kick it". - -First class, yo, this is bad. Drinking orange juice out of a champagne glass. -Is this what the people of Bel-Air living like? Hmm, this might be alright. - -But wait I hear they're prissy, bourgeois, all that. Is this the type of place that they just send this cool cat? -I don't think so, I'll see when I get there. -I hope they're prepared for the prince of Bel-Air. - -Well, the plane landed and when I came out. There was a dude who looked like a cop standing there with my name out. -I ain't trying to get arrested yet, I just got here. -I sprang with the quickness like lightning, disappeared. - -I whistled for a cab and when it came near. The license plate said "Fresh" and it had dice in the mirror. -If anything I could say that this cab was rare, but I thought, "Nah, forget it" – "Yo, home to Bel-Air"! - -I pulled up to the house about 7 or 8 and I yelled to the cabbie, "Yo home smell ya later". -I looked at my kingdom, I was finally there. To sit on my throne as the Prince of Bel-Air. -`; diff --git a/test/unit/lib/friends.js b/test/unit/lib/friends.js deleted file mode 100644 index f598c2b26..000000000 --- a/test/unit/lib/friends.js +++ /dev/null @@ -1,277 +0,0 @@ -module.exports = `Hey you guys! -Hey! -Hey, what are you doing? -Oh, figuring out our wedding plans. -That's funny, we were doing the same thing! -Yeah! -It's really crazy! The hall, the dress, the food... I-I had no idea how expensive this stuff was! -Yeah it is really pricey. I mean, I freaked when I first heard the numbers. -So what did you two do about it? -It was pretty simple actually, I came up with a couple of cost-cutting solutions, wrote out a list and Monica told me to go to hell. -There's no way around it Pheebs, you just gonna have to accept the fact that this is gonna cost you a lot of money. -I heard that weddings are like a 40 billion dollar a year industry. -Yeah, and I'm responsible for just like half of that. -But really, it does seem like this money could be put to better use? -Are you serious? -Yeah! Now, how would you feel if we gave all the wedding money to charity and we just got married at City Hall? -I think it would make me wanna marry you even more. -I've got to say you guys, that's an incredible gesture! -Maybe you do that next time you get married! -No, no, no. The next time it's gonna be a Hawaii at sunset. But maybe the time after that! -Hey! -Hey! -What's going on? -Our adoption social worker is coming by today so we are cleaning the apartment. -We? -You know you don't want me to help. You can't have it both ways! -Hey, is this person who decides whether or not you... get a baby? -Kind of. She's coming by to interview us and see where we live. -And it has to go perfectly, because if she doesn't like something about us she can keep us off every adoption list in the state. -Hey, maybe I should stop by! She could be a soap opera fan! It's very impressive when the little people know a celebrity. -Little people? -Celebrity. -Ok, so I think I'm just about done here, unless you have any bad stuff hidden somewhere, like... porn or cigarettes? -What...? NO! -Chandler? -I don't, and I'm offended by the insinuation! -Ok, so there's not a magazine under the couch, or a pack of cigarettes taped to the back of the toilet tank, or a filthy video in the VCR? -I'll admit to the cigarettes and the magazine, but that tape is not mine. -It isn't mine! -Well, I guess we'll never know whose it is! -May I help you? -Yes. We're here to make a rather sizeable donation to the children. -Well, any contribution, large or small, is always appreciated. -Well, I think you're gonna appreciate it the crap out of this one -Well, this is very generous! -And we don't want any recognition. This is completely anonymous. -Completely anonymous. From two kind strangers. -Mr. X and Phoebe Buffay. -Well if you like, we can include your names in our newsletter. -Not necessary. -Buffay is spelled B-U-F-F-A-Y. -And "X" is spelled uhm... "Mike Hannigan". -Right. Well, on behalf of the children: thank you both very much. -Sure, I so glad we did this. It feels so good! -It does. It feels really good! -Oh, look! And we get these free t-shirts! -Oh, actually, that's the shirt I wore to the gym. -Mhm... it's moist. -Hi! -Hi! Emma will be up in a minute! -Oh, good! -Oh hey Ross... Listen, I heard about you and Charlie. I'm really sorry. -Oh, that's OK. I'm sure there are tons of other beautiful paleontologists out there. -Absolutely. -There was one! She's it! All the rest look like they should live under a bridge! -So, uhm... what are you gonna do today? -Well, I was thinking of taking Emma to the playground! -Oh my God, what!? -Like I said I was thinking of taking Emma to the museum of knives and fire! -Ok, look, Ross. I do not want Emma going to the playground. -Be-caaauuuse... -All right, well, if you must know... I had a traumatic... swing incident... when I was little. -Seriously? -Yes, I was 4 years old and I was on the swing and then all of a sudden my hair got tangled in the chain. And to get me out my mom had to-had to cut a big chunk of my hair! And it was uneven for weeks! -And you made it through that? I wonder who's gonna play you in the movie! -Ok, fine! You can make fun of me. I do not want Emma going there. And I was thinking Claire Danes. -Look, I'm sorry to hear about your tragedy, ok? But the swings are perfectly safe, and besides Emma loves them. You know what, you should come with us and you'll see! -Ross, those things go like 40 miles an hour! Ok? When you're... and there is that moment when you are at the top, when you just don't know if you're gonna return back to earth! -Space is filled with orbiting children. Look, please, just come on, you know, when you’ll see the look on Emma’s face, I swear you won’t regret it. -All right! -Good, you don’t want to be one of those mothers who pass on their irrational fears on their children, do you? -Irrational, huh? All right, well, I’ll remember that the next time you freak out about a spider in your apartment! -Oh, yeah, that’s the same, I am sure there are thirty different species of poisonous swings! -Oh my God, the adoption lady is early! -Ok, ok, here we go. -Ok. -Here we go. Stand up straight. -Hello, is this the creepy residence? -We’re waiting for the adoption lady, but, hey, I’m glad you’re here. I was cleaning this morning and I found this . I don’t know if you wanna use it, but… -Awe, this is so sweet of you! But you know what? I won’t be needing a veil, I actually won’t be wearing a dress at all! -I told you! I am not coming to a naked wedding! -No, no, no, we’re not having a big reception, we took the money we were gonna spend on a wedding and we donate them to the children charity. -That’s crazy! . I am sorry. I just can’t imagine giving up my one wedding day like that! -We, you know, we’re different! We don’t care about having a huge party. All right, well, who cares, I don’t need a pretty veil and a fancy dress. -That’s right. You’re making a commitment and that’s the same, whether you do that at the Plaza or, where are you gonna do it? -City Hall. -Ow! Oh, that sounds nice! I am just there for jury duty. They really spruce that place up! -It’s ok, it’s ok. I made my decision. What I really want is a great big wedding -Yay! -But you already gave all your money to charity! -Well, I’ll just ask for it back! -I don’t think you can do that! -Why not! This is her wedding day, this is way more important than some stupid kids! -That’s sweet, honey, but save something for the adoption Lady. -Ok, careful. -Ok. -Careful, watch her hair. WATCH HER HAIR! -Rach, she’s got like three hairs! -I know but they’re just so beautiful! Oh, my God, I just pulled one out. -I promise you she’s safe! No watch how much she loves this. -Ok. -Ready sweety? -Ok. -Here we go! -Ok, careful, ok. Oh, she’s smiling! Oh my God, she does like it! -See, I told you! -Awe! Oh my God! Looks, she’s a little dare-devil! Oh, let me push, can I push? -Oh, absolutely! -Ok. Oh God. Get the camera, it’s in the diaper bag. -Ok! Ow! -We’re seriously asking for our money back? -It’s for our wedding day! Right, now, is this guy gay or straight, because one of us gonna have to start flirting. -Wow! Are you here to make another donation the same day? I don’t think that that’s ever happened before. -Gay, go. -Oh my God, I love your shirt! -The donation we made earlier, we k…, we w…, we want it back. -Excuse me? -Yeah. See, that money was for a big wedding, that we thought we didn’t want, but it turns out we do. -So you’re asking us to refund your donation to the children? -Yeah! This feels really good. -I am sorry. I am, but this wedding is just really important to me. -Hey, it’s not my business, besides it’s probably a good thing. We really would have been spoiling the children, all those food, and warm clothing… -Hey, that’s not fair! A person’s wedding is important! And especially to me! Ok? I didn’t have a graduation party! And I didn’t go to Prom. And I spent my sweet sixteen being chased round a tire yard by an escaped mental patient who is his own words wanted to “kill me” or whatever. So I deserve a real celebration and I am not gonna let some sweaty little man make me feel badly about it. -She could have been talking about either one of us. -Hi, I am Laura, I am here for your adoption interview. -Hi, I am Monica and this is Chandler. Please come in. -Thank you! -Would you like something to drink? -Oh, water would be fine. -Ok. Great. I am so glad that you are here. We’re really excited about getting this process started. -Oh, because we love kids. Love ‘em to death.Well, not actually to death, that's just a figure of speech - we love kids the appropriate amount... as allowed by law. -Your place is just lovely. -Ah, thank you. This building does have a wholesome family feel to it. -You know, I... I feel like I've been here before. Are any other couples in the building adopting? -Is that that couple on the first floor? Because we should get a baby before them. Yeah! That guy tried to sell me drugs. -But other than that... wholesome, wholesome building. -Oh... -What? -I just realized why I remember this place. -Really? What is it? -Oh, it's nothing. I went on a date with a guy who lived in this building and it didn't end very well. -Ohh... that wouldn't by any chance be... Joey Tribbiani? -Yes! -Of course it was! -Yeah, we had a really great night and in the morning he promised he would call me and he didn't. -RAT BASTARD! -So you're not friends with him? -OH GOD NO! Nope, no, no, no. No! No, no. Nope! No, no, no, no, no, no, no, no, no. NO! No! -Well, I'm sorry I brought it up. So, are either one of you planning on staying at home with your child... -OW! -What was that? -Oh, it's just some crazy guy who roams the halls here. He's great with kids though. -Oh, oh Ross, oh my God, are you okay? -SON OF A BITCH! -Ross, see! I told you, those swings are evil! Alright, that is it. That is the last time Emma is getting on one of those things for her entire life. -No! No, no, no, no, okay, it wasn't the swing's fault. It was my fault and kind of that kids fault. Who is still laughing. Nice. -Ross, c'mon, please. Can we just get out of here, before somebody else gets hurt? -No wait, okay, okay, I have an idea. I want you to get on the swing, okay? And you'll see that there's nothing to be afraid of. -I know what this is all about... You've always been jealous of my hair. -Look, I just think you're an adult, okay? And you should get over your silly fears. -Alright fine. I'll do it. -Good. -If you hold a spider. -WHAT? WHERE? WHERE? -IF you hold a spider. -I know. -Guys? Everything ok? It's me, Joe... -AAAAAAAAAAAAAAAAAAAAA......AAAaaa-doption!! -What's going on? -Oh, just like I said. That crazy... Bert... roaming the halls. -Guys!? -Keep on roaming Bert! We don't want any crazy today! -What's going on? -WE'LL TALK TO YOU LATER, BERT. EVERYTHNG'S FINE!! -Everything doesn't sound fine! -Is he alright out there by himself? -Oh yeah! He has a caretaker. His older brother... Ernie. -Bert and Ernie! -You can't make this stuff up! -You never told me about that guy on your sweet sixteen. Oh, ugh. I'm sorry about that. -Oh! It ended okay. One of my friends shot him. -Well, hey, at least you're getting a proper wedding. I mean, you really deserve that. -Yeah, I really do. You know, I had nothing growing up. Just like the kids I took the money from. -No! No, no. I see where this is going. Don't make me go back there. -Look, I can't have a wedding with this money now. It's tainted. -Alright, fine. We'll give the money back. -And if that guy at the charity gives us a hard time, my friend hasn't shot anyone in a really long time. -Well, I must say, this seems like a lovely environment to raise a child in. -Oh, by the way, you are more than welcome to look under any of the furniture, because, believe me, you won't find any porn or cigarettes under there! -Oh! Well, actually, before we look around, let me make sure I have everything I need up to here... -Why don't I show you the baby's room? -What the hell are you doing? -Well, you wouldn't let me in, so I thought you were in trouble. -Well, we're not. -But you called me 'Bert'!? That's our code word for danger! -We don't have a code word. -We don't? We really should. From now on, 'Bert' will be our code word for danger. -So that was the baby's room. -What room should we see next? -Any room that isn't behind this couch! -. -I did not care for that! -You have to get out of here. You slept with our social worker and you never called her back and she is still pissed, so she can't see you. -Ok, ok! -Ok! -What? -I forgot my bat. -Oh my God! -And for the last time, we do not want to be friends with you! And we don't want to buy your bat! -What are you doing here? -Bert! Bert! Bert! Bert! -Are you friends with him? -I can explain... Joey... -Uhm... ok... uhm... Well, yeah... You have got some nerve, coming back here. I can't believe you never called me. -Excuse me? -Oh... yeah... Probably you don't even remember my name. It's Joey, by the way. And don't bother telling me yours, because I totally remember it... lady. Yeah! I waited weeks for you to call me. -I gave you my number, you never called me. -No, no! Don't try to turn this around on me, ok? I'm not some kind of... social work, ok, that you can just... do. -Well, I'm pretty sure I gave you my number. -Really? Think about it. Come on! You're a beautiful woman, smart, funny, we had a really good time, huh? If I had your number, why wouldn't I call you? -I don't know... Well, maybe I'm wrong... I'm sorry... -No, no, hey, no! Too late for apologies... ok? You broke my heart. You know how many women I had to sleep with to get over you? -Joey, wait! -I'm sorry that you had to see that. I'm so embarrassed... -Oh, that's really ok. -Yeah, that we totally understand. Dating is hard. -Boy, you people are nice... And I've got to say... I think you're going to make excellent parents. -LAURA! -We're back! -Are you here to take more money? Because, I think what you're looking for is an ATM. -No, no, we're here to give the money back. -Yeah, because you know what, it's... it's all about the children. -Although... it's also about the wedding... Ugh, alright... here. No... Oh God... Oh! -If I haven't said so already sir, congratulations! -Now... what do you think we should do? -You know what? It's not your decision anymore. -What? -On behalf of the Children of New York, I reject your money. -But... but... but we're giving you this! -Yeah... And I'm giving it back to you... Come on! Consider it a contribution. -Well, this is very generous! -Please, take the check, go have a great wedding and a wonderful life together. -Well, I mean... It sounds good to me. And that way we can save up, come back in a few years and make an even bigger donation. -Absolutely! And when you do, make sure you ask for Brian. -Oh, is that you? -No! -Hello...? Oh hi... Oh my God...! Really...? I can't wait to tell Chandler... Ok, goodbye. -Wrong number? -It was Laura... She gave us a great report and we are officially on the waiting list. -That's great! -Now we just have to wait for a call and... and someone tells us there's a baby waiting for us. Oh... -Hello...? Have you seen Joey's bat? - -Ok... I got a spider. There were two, I picked the bigger one. -Ok... -Ok... -This feels perfectly normal. Ok, get on the swing! -Ok... O-k... -Ok... -whoo... ok... wow... ok... OH! -See? -A-alright! I can do this. -There you go! Good for you! And you know what, I'm actually getting used to this little guy. I don't really even feel him in here anymore. -That's because he's on your neck. -Well... Whaa... aaah... aaahhh... -ROSS! -`; diff --git a/test/unit/lib/nlp.js b/test/unit/lib/nlp.js deleted file mode 100644 index 10db6c6a6..000000000 --- a/test/unit/lib/nlp.js +++ /dev/null @@ -1,9 +0,0 @@ -if (typeof process !== undefined && typeof module !== undefined) { - if (process.env.TESTENV === 'prod') { - console.warn('== production build test 🚀 =='); - // module.exports = require('../../builds/efrt'); - module.exports = require('../../../'); - } else { - module.exports = require('../../../src/'); - } -} diff --git a/test/unit/lib/pennSample.js b/test/unit/lib/pennSample.js deleted file mode 100644 index bcd9e256b..000000000 --- a/test/unit/lib/pennSample.js +++ /dev/null @@ -1,325 +0,0 @@ -//(very) small subset of the Penn-treebank that should always pass -module.exports = [ - { - text: - 'Dr. Talcott led a team of researchers from the National Cancer Institute and the medical schools of Harvard University and Boston University.', - pos: 'NNP, NNP, VBD, DT, NN, IN, NNS, IN, DT, NNP, NNP, NNP, CC, DT, JJ, NNS, IN, NNP, NNP, CC, NNP, NNP' - }, - { - text: 'The monthly sales have been setting records every month since March.', - pos: 'DT, JJ, NNS, VBP, VBN, VBG, NNS, DT, NN, IN, NNP' - }, - { - text: ' Cray Computer will be a concept stock, he said.', - pos: 'NNP, NNP, MD, VB, DT, NN, NN, PRP, VBD' - }, - { - text: 'Esso said the Whiting field started production Tuesday.', - pos: 'NNP, VBD, DT, NNP, NN, VBD, NN, NNP' - }, - { - text: 'Pick a country, any country.', - pos: 'VB, DT, NN, DT, NN' - }, - { - text: 'They fell into oblivion after the 1929 crash.', - pos: 'PRP, VBD, IN, NN, IN, DT, CD, NN' - }, - { - text: 'Political and currency gyrations can whipsaw the funds.', - pos: 'JJ, CC, NN, NNS, MD, VB, DT, NNS' - }, - { - text: 'They cite a lack of imbalances that provide early warning signals of a downturn.', - pos: 'PRP, VBP, DT, NN, IN, NNS, WDT, VBP, JJ, NN, NNS, IN, DT, NN' - }, - { - text: 'Characters drink Salty Dogs, whistle Johnny B. Goode and watch Bugs Bunny reruns.', - pos: 'NNS, VBP, NNP, NNP, VBP, NNP, NNP, NNP, CC, VBP, NNP, NNP, NNS' - }, - { - text: 'They read Mickey Spillane and talk about Groucho and Harpo.', - pos: 'PRP, VBP, NNP, NNP, CC, VBP, IN, NNP, CC, NNP' - }, - { - text: ' Consider Jim Courter.', - pos: 'VB, NNP, NNP' - }, - { - text: 'But it resists yielding political ground.', - pos: 'CC, PRP, VBZ, VBG, JJ, NN' - }, - { - text: ' In Asia, as in Europe, a new order is taking shape, Mr. Baker said.', - pos: 'IN, NNP, IN, IN, NNP, DT, JJ, NN, VBZ, VBG, NN, NNP, NNP, VBD' - }, - { - text: 'And South Carolina says it is getting results.', - pos: 'CC, NNP, NNP, VBZ, PRP, VBZ, VBG, NNS' - }, - { - text: " It was full of violence and gangs and kids cutting class, says Linda Ward, the school's principal.", - pos: 'PRP, VBD, JJ, IN, NN, CC, NNS, CC, NNS, VBG, NN, VBZ, NNP, NNP, DT, NN, NN' - }, - { - text: 'I believe in the system.', - pos: 'PRP, VBP, IN, DT, NN' - }, - { - text: 'Mrs. Yeargin declined.', - pos: 'NNP, NNP, VBD' - }, - { - text: 'Yeargin won widespread local support.', - pos: 'NNP, VBD, JJ, JJ, NN' - }, - { - text: 'But Learning Materials matched on 66.5 of 69 subskills.', - pos: 'CC, NNP, NNPS, VBD, IN, CD, IN, CD, NNS' - }, - { - text: 'The two banks merged in 1985.', - pos: 'DT, CD, NNS, VBD, IN, CD' - }, - { - text: "He said the company's core business remains strong.", - pos: 'PRP, VBD, DT, NN, NN, NN, VBZ, JJ' - }, - { - text: 'Estimated volume was a moderate 3.5 million ounces.', - pos: 'VBN, NN, VBD, DT, JJ, CD, CD, NNS' - }, - { - text: 'Mr. Gillespie at Viacom says the ratings are rising.', - pos: 'NNP, NNP, IN, NNP, VBZ, DT, NNS, VBP, VBG' - }, - { - text: 'Ad Notes....', - pos: 'NNP, NNPS' - }, - { - text: 'The business had been handled by VanSant Dugdale, Baltimore.', - pos: 'DT, NN, VBD, VBN, VBN, IN, NNP, NNP, NNP' - }, - { - text: ' The economy is clearly slowing, says Robert Black, president of the Richmond Federal Reserve Bank.', - pos: 'DT, NN, VBZ, RB, VBG, VBZ, NNP, NNP, NN, IN, DT, NNP, NNP, NNP, NNP' - }, - { - text: 'They will mature Dec. 21.', - pos: 'PRP, MD, VB, NNP, CD' - }, - { - text: 'Lancaster Colony Corp. said it acquired Reames Foods Inc. in a cash transaction.', - pos: 'NNP, NNP, NNP, VBD, PRP, VBD, NNP, NNP, NNP, IN, DT, NN, NN' - }, - { - text: 'NL is officially making the offer.', - pos: 'NNP, VBZ, RB, VBG, DT, NN' - }, - { - text: "The Japanese fret openly about the U.S. public's rancor.", - pos: 'DT, NNP, NN, RB, IN, DT, NNP, NN, NN' - }, - { - text: 'They operate ships and banks.', - pos: 'PRP, VBP, NNS, CC, NNS' - }, - { - text: - 'Adds Takeshi Kondo, senior vice president of C. Itoh America Inc.: We have a great interest in making investments, particularly in new ventures.', - pos: 'VBZ, NNP, NNP, JJ, NN, NN, IN, NNP, NNP, NNP, NNP, PRP, VBP, DT, JJ, NN, IN, VBG, NNS, RB, IN, JJ, NNS' - }, - { - text: 'But many banks are turning away from strict price competition.', - pos: 'CC, JJ, NNS, VBP, VBG, RB, IN, JJ, NN, NN' - }, - { - text: 'One big reason: thin margins.', - pos: 'CD, JJ, NN, JJ, NNS' - }, - { - text: 'Buy a new Chevrolet.', - pos: 'VB, DT, JJ, NNP' - }, - { - text: 'Buy a diamond necklace.', - pos: 'VB, DT, NN, NN' - }, - { - text: 'They are keeping a close watch on the yield on the S&P 500.', - pos: 'PRP, VBP, VBG, DT, JJ, NN, IN, DT, NN, IN, DT, NNP, CD' - }, - { - text: 'In fact, the market has always tanked.', - pos: 'IN, NN, DT, NN, VBZ, RB, VBN' - }, - { - text: 'Always.', - pos: 'RB' - }, - { - text: 'China pulled out of the program in July.', - pos: 'NNP, VBD, VB, IN, DT, NN, IN, NNP' - }, - { - text: 'But regulators are wary.', - pos: 'CC, NNS, VBP, JJ' - }, - { - text: 'He also is a consensus manager, insiders say.', - pos: 'PRP, RB, VBZ, DT, NN, NN, NNS, VBP' - }, - { - text: 'Compromises are possible.', - pos: 'NNS, VBP, JJ' - }, - { - text: 'The company acknowledges some problems.', - pos: 'DT, NN, VBZ, DT, NNS' - }, - { - text: - 'A number of cities including Minneapolis, Philadelphia and Houston have vacant grain elevators, Eggers says.', - pos: 'DT, NN, IN, NNS, VBG, NNP, NNP, CC, NNP, VBP, JJ, NN, NNS, NNP, VBZ' - }, - { - text: - 'They suffered from malnutrition, chest diseases, cardiovascular disorders, skin problems, infectious diseases and the aftereffects of assaults and rape.', - pos: 'PRP, VBD, IN, NN, NN, NNS, JJ, NNS, NN, NNS, JJ, NNS, CC, DT, NNS, IN, NNS, CC, NN' - }, - { - text: 'That was the law.', - pos: 'DT, VBD, DT, NN' - }, - { - text: 'It was censorship.', - pos: 'PRP, VBD, NN' - }, - { - text: 'It was outrageous.', - pos: 'PRP, VBD, JJ' - }, - { - text: 'But the court disagreed.', - pos: 'CC, DT, NN, VBD' - }, - { - text: 'The man was Charles Z. Wick.', - pos: 'DT, NN, VBD, NNP, NNP, NNP' - }, - { - text: ' Bob has handled the extraordinary growth of the company quite brilliantly, said Mr. Newhouse.', - pos: 'NNP, VBZ, VBN, DT, JJ, NN, IN, DT, NN, RB, RB, VBD, NNP, NNP' - }, - { - text: - 'This species of congressional action is predicated on an interpretation of the appropriations clause that is erroneous and unconstitutional.', - pos: 'DT, NN, IN, JJ, NN, VBZ, VBN, IN, DT, NN, IN, DT, NNS, NN, WDT, VBZ, JJ, CC, JJ' - }, - { - text: 'President Reagan learned that lesson.', - pos: 'NNP, NNP, VBD, DT, NN' - }, - { - text: 'Mr. Sidak served as an attorney in the Reagan administration.', - pos: 'NNP, NNP, VBD, IN, DT, NN, IN, DT, NNP, NN' - }, - { - text: 'The death of the Herald, a newsstand paper in a freeway town, was perhaps inevitable.', - pos: 'DT, NN, IN, DT, NNP, DT, NN, NN, IN, DT, NN, NN, VBD, RB, JJ' - }, - { - text: ' The Herald was a survivor from a bygone age, said J. Kendrick Noble, a media analyst with PaineWebber Inc.', - pos: 'DT, NNP, VBD, DT, NN, IN, DT, JJ, NN, VBD, NNP, NNP, NNP, DT, NNS, NN, IN, NNP, NNP' - }, - { - text: 'The reaction in the newsroom was emotional.', - pos: 'DT, NN, IN, DT, NN, VBD, JJ' - }, - { - text: - 'The program traders, on the other hand, portray old-fashioned stock pickers as the Neanderthals of the industry.', - pos: 'DT, NN, NNS, IN, DT, JJ, NN, VBP, JJ, JJ, NN, NNS, IN, DT, NNS, IN, DT, NN' - }, - { - text: 'Reducing volatility.', - pos: 'VBG, NN' - }, - { - text: 'Ballot watchers say attention already is focused on the 1990 elections.', - pos: 'NN, NNS, VBP, NN, RB, VBZ, VBN, IN, DT, CD, NNS' - }, - { - text: 'Colleges, she says, are eyeing registration through 900 service.', - pos: 'NNS, PRP, VBZ, VBP, VBG, NN, IN, CD, NN' - }, - { - text: 'FAMILY PETS are improving recovery rates of patients at Columbia Hospital, Milwaukee.', - pos: 'NN, NNS, VBP, VBG, NN, NNS, IN, NNS, IN, NNP, NNP, NNP' - }, - { - text: 'The appointment takes effect Nov. 13.', - pos: 'DT, NN, VBZ, NN, NNP, CD' - }, - { - text: 'Heiwado Co.', - pos: 'NNP, NNP' - }, - { - text: 'Guaranteed by Svenska Handelsbanken.', - pos: 'VBN, IN, NNP, NNP' - }, - { - text: 'Mitsubishi Pencil Co.', - pos: 'NNP, NNP, NNP' - }, - { - text: 'Koizumi Sangyo Corp.', - pos: 'NNP, NNP, NNP' - }, - { - text: 'A stadium craze is sweeping the country.', - pos: 'DT, NN, NN, VBZ, VBG, DT, NN' - }, - { - text: 'Stock prices closed higher in Stockholm, Amsterdam and Frankfurt and lower in Zurich.', - pos: 'NN, NNS, VBD, JJR, IN, NNP, NNP, CC, NNP, CC, JJR, IN, NNP' - }, - { - text: 'A faster version, the SuperDot, was launched in 1984.', - pos: 'DT, JJR, NN, DT, NNP, VBD, VBN, IN, CD' - }, - { - text: 'Valley Federal is currently being examined by regulators.', - pos: 'NNP, NNP, VBZ, RB, VBG, VBN, IN, NNS' - }, - { - text: 'Columbia has only about 10 million common shares in public hands.', - pos: 'NNP, VBZ, RB, IN, CD, CD, JJ, NNS, IN, JJ, NNS' - }, - { - text: 'But the concept is workable.', - pos: 'CC, DT, NN, VBZ, JJ' - }, - { - text: "Mr. Spiegel's next career move is a subject of speculation on Wall Street.", - pos: 'NNP, NNP, JJ, NN, NN, VBZ, DT, NN, IN, NN, IN, NNP, NNP' - }, - { - text: 'Wedtech management used the merit system.', - pos: 'NNP, NN, VBD, DT, NN, NN' - }, - { - text: 'Numerous other scandals, among them the ones at HUD, have the same characteristics as Wedtech.', - pos: 'JJ, JJ, NNS, IN, PRP, DT, NNS, IN, NNP, VBP, DT, JJ, NNS, IN, NNP' - }, - { - text: 'Railroad companies and some ports are reaping a sudden windfall of business.', - pos: 'NN, NNS, CC, DT, NNS, VBP, VBG, DT, JJ, NN, IN, NN' - }, - { - text: ' The recent rally in precious metals was a result of uncertainty and volatility in equities, he said.', - pos: 'DT, JJ, NN, IN, JJ, NNS, VBD, DT, NN, IN, NN, CC, NN, IN, NNS, PRP, VBD' - } -]; diff --git a/test/unit/match/capture.test.js b/test/unit/match/capture.test.js deleted file mode 100644 index 4ae6c0e53..000000000 --- a/test/unit/match/capture.test.js +++ /dev/null @@ -1,52 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('match-capture-group', function(t) { - var m = nlp('John eats glue').match('[john]'); - t.equal(m.out('text'), 'John', 'capture-group-simple'); - - m = nlp('John Smith eats glue').match('[#Person+]'); - t.equal(m.out('text'), 'John Smith', 'capture-two'); - - m = nlp('ralf eats the glue').match('ralf [#Verb] the'); - t.equal(m.out('normal'), 'eats', 'simple subset'); - - m = nlp('ralf eats the glue').match('[ralf #Verb] the'); - t.equal(m.out('normal'), 'ralf eats', 'two-word capture'); - - m = nlp('i saw ralf eat the glue Mrs. Hoover').match('ralf [#Verb the glue] mrs'); - t.equal(m.out('normal'), 'eat the glue', 'three-word capture'); - - m = nlp('ralf eats the glue').match('* [#Verb]'); - t.equal(m.out('normal'), 'eats', 'capture after wildcard'); - - m = nlp('ralf eats the glue').match('ralf eats [*]'); - t.equal(m.out('normal'), 'the glue', 'wildcard capture at the end'); - - m = nlp('ralf eats the glue').match('ralf eats [*] glue'); - t.equal(m.out('normal'), 'the', 'wildcard capture in the middle'); - - m = nlp('saw the Toronto International Documentary Film Festival yesterday').match('saw the? [#Noun+] yesterday'); - t.equal(m.trim().out('text'), 'Toronto International Documentary Film Festival', 'greedy capture'); - - t.end(); -}); - -test('replace-capture-group', function(t) { - var m = nlp('John eats glue').replace('john [#Verb]', 'sniffs'); - t.equal(m.out('text'), 'John sniffs glue', 'capture-group-simple'); - // - // m = nlp('John eats glue. john is fun.').replace('[john]', '$1 smith'); - // t.equal(m.out('text'), 'John smith eats glue. john smith is fun.', 'capture-group-multiple'); - // - // m = nlp('John Smith eats glue').replace('[#Person+]', 'dr. $1'); - // t.equal(m.out('text'), 'dr. John Smith eats glue', 'capture-two'); - // - // m = nlp('ralf eats the glue').replace('ralf [#Verb]', 'he $1'); - // t.equal(m.out('text'), 'he eats the glue', 'simple subset'); - // - // m = nlp('John eats the glue').replace('the [#Noun]', 'the cyber-$1'); - // t.equal(m.out('text'), 'John eats the cyber-glue', 'capture-group as subset'); - // - t.end(); -}); diff --git a/test/unit/match/encoding.test.js b/test/unit/match/encoding.test.js deleted file mode 100644 index 3bfcdbc10..000000000 --- a/test/unit/match/encoding.test.js +++ /dev/null @@ -1,63 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('encoding-match:', function(t) { - var r = nlp('it is * nice'); - var str = r.match('is \\*').trim().out(); - t.equal(str, 'is *', 'encode asterix'); - - // r = nlp('it is + nice'); - // str = r.match('is \\+ nice').trim().out(); - // t.equal(str, 'is + nice', 'encode plus'); - - t.end(); -}); - -test('reserved-word-in-src:', function(t) { - var r = nlp('buy eggs constructor yeah prototype'); - t.equal(r.has(`backburner`), false, 'single'); - t.equal(r.has(`#Foo`), false, 'tag'); - t.equal(r.has(`(upcoming|backburner)`), false, 'anyOf'); - t.equal(r.has(`lala+`), false, 'manyOf'); - t.equal(r.has(`nword{2,4}`), false, 'someOf'); - t.end(); -}); - -test('reserved-word-in-match:', function(t) { - var r = nlp('fo foo fulala repeat'); - t.equal(r.has(`constructor`), false, 'single'); - t.equal(r.has(`#constructor`), false, 'tag'); - t.equal(r.has(`(upcoming|constructor)`), false, 'anyOf'); - t.equal(r.has(`constructor+`), false, 'manyOf'); - t.equal(r.has(`constructor{2,4}`), false, 'someOf'); - t.end(); -}); - -test('test-infinite-loop', function(t) { - var weirdDoc = nlp('^ ? * . + $'); - weirdDoc.match('is?'); - weirdDoc.match('.?'); - weirdDoc.match('*'); - weirdDoc.match('.+'); - weirdDoc.match('+'); - weirdDoc.match('?'); - weirdDoc.match('.'); - weirdDoc.match('? * . +'); - weirdDoc.not('?'); - weirdDoc.not('*'); - weirdDoc.not('^'); - weirdDoc.not('$'); - weirdDoc.not('+'); - weirdDoc.not('? * . +'); - t.ok(true, 'didnt regress'); - - var str = 'And you are?. Marshal'; - var have = nlp(str).sentences().out(); - t.equal(have, str, 'regression #1'); - - str = `- where is she.Oh. you guys don't know?`; - have = nlp(str).sentences().out(); - t.equal(have, str, 'regression #2'); - - t.end(); -}); diff --git a/test/unit/match/if.test.js b/test/unit/match/if.test.js deleted file mode 100644 index 6e43b8ff0..000000000 --- a/test/unit/match/if.test.js +++ /dev/null @@ -1,33 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('if-basic:', function(t) { - var r = nlp('spencer is here'); - var m = r.if('asdf'); - t.equal(m.out('text'), '', 'if-negative'); - - m = r.if('spencer'); - t.equal(m.out('text'), 'spencer is here', 'if-positive'); - - r = nlp('spencer is here. john was here.'); - m = r.if('is'); - t.equal(m.out('normal'), 'spencer is here.', 'if-partial'); - - t.end(); -}); - -test('ifNo:', function(t) { - var r = nlp('spencer is here'); - //ifNo - var m = r.ifNo('spencer'); - t.equal(m.out('text'), '', 'ifNo-positive'); - - m = r.ifNo('asdf'); - t.equal(m.out('text'), 'spencer is here', 'ifNo-negative'); - - r = nlp('spencer is here. john was here.'); - m = r.ifNo('is'); - t.equal(m.out('normal'), 'john was here.', 'if-no-partial'); - - t.end(); -}); diff --git a/test/unit/match/insert.test.js b/test/unit/match/insert.test.js deleted file mode 100644 index 2d85a346c..000000000 --- a/test/unit/match/insert.test.js +++ /dev/null @@ -1,44 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('insert-basic :', function(t) { - var m = nlp('the dog sat').insertBefore('and'); - t.equal(m.out('text'), 'and the dog sat', 'and-dog'); - - m = nlp('the dog sat').insertAfter('patiently'); - t.equal(m.out('text'), 'the dog sat patiently', 'sat-patiently'); - - m = nlp('the dog sat'); - m.match('dog').insertBefore('nice'); - t.equal(m.out('text'), 'the nice dog sat', 'nice-dog'); - - m = nlp('a dog sat'); - m.match('sat').insertAfter('quickly'); - t.equal(m.out('text'), 'a dog sat quickly', 'sat-quickly'); - - m = nlp('a dog sat'); - m.match('a dog sat').insertAfter('quickly'); - t.equal(m.out('text'), 'a dog sat quickly', 'multi-match-quickly'); - - m = nlp('a dog sat'); - m.match('asdf').insertAfter('no no no'); - t.equal(m.out('text'), 'a dog sat', 'no no no no'); - - t.end(); -}); - -test('insert-subset-include :', function(t) { - var m = nlp('the dog is nice'); - var sub = m.match('is'); - sub.insertAfter('really'); - t.equal(sub.out('normal'), 'is really', 'is-really'); - t.equal(m.out('normal'), 'the dog is really nice', 'dog-is-really-nice'); - - m = nlp('the dog climbed the fence'); - sub = m.match('climbed'); - sub.insertBefore('really'); - t.equal(sub.out('normal'), 'really climbed', 'really-quickly'); - t.equal(m.out('normal'), 'the dog really climbed the fence', 'dog-really-climbed'); - - t.end(); -}); diff --git a/test/unit/match/match.test.js b/test/unit/match/match.test.js deleted file mode 100644 index 3aa34b931..000000000 --- a/test/unit/match/match.test.js +++ /dev/null @@ -1,187 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('==Match ==', function(T) { - T.test('term-match :', function(t) { - [ - ['quick', 'quick', true], - ['Quick', 'Quick', true], - ['quick', 's', false], - ['quick', '#Adjective', true], - ['quick', '#Noun', false], - ['quick', '(fun|nice|quick|cool)', true], - ['quick', '(fun|nice|good)', false] - ].forEach(function(a) { - var m = nlp(a[0]).match(a[1]); - var msg = a[0] + ' matches ' + a[1] + ' ' + a[2]; - t.equal(m.found, a[2], msg); - }); - t.end(); - }); - - T.test('sentence-match:', function(t) { - [ - ['the dog played', 'the dog', 'the dog'], - ['the dog played', 'the dog played', 'the dog played'], - ['the dog played', 'the #Noun', 'the dog'], - ['the dog played', 'the #Noun played', 'the dog played'], - ['the dog played', 'the cat played', ''], - ['the dog played', 'the #Adjective played', ''], - ['the dog played', 'the (cat|dog|piano) played', 'the dog played'], - ['the dog played', 'the (cat|piano) played', ''], - ['the dog played', 'the . played', 'the dog played'], - //optional - ['the dog played', 'the dog quickly? played', 'the dog played'], - ['the dog played', 'the dog #Adverb? played', 'the dog played'], - ['the dog quickly played', 'the dog #Adverb? played', 'the dog quickly played'], - ['the dog quickly played', 'the dog #Adverb played', 'the dog quickly played'], - ['the dog quickly played', 'the dog . played', 'the dog quickly played'], - ['the dog quickly played', 'the dog .? played', 'the dog quickly played'], - // ['the dog played', 'the dog .? played', 'the dog played'], - - //leading/trailing logic - ['the dog played', 'the dog played$', 'the dog played'], - ['the dog played', 'the dog', 'the dog'], - ['the dog played', 'the dog$', ''], - ['the dog played', 'the dog$ played', ''], - ['the dog played', '^the dog', 'the dog'], - ['the dog played', 'dog played', 'dog played'], - ['the dog played', '^dog played', ''], - ['the dog played', '^played', ''], - ['the dog played', '^the', 'the'], - - ['john eats glue', 'john eats glue', 'john eats glue'], - ['john eats glue', 'john eats', 'john eats'], - ['john eats glue', 'eats glue', 'eats glue'], - ['john eats glue', 'eats glue all day', ''], - - //test contractions - // [`if you don't mind`, `you don't mind`, `you don't mind`], - [`if you don't mind`, `you don't care`, ``], - // [`if you don't mind`, `you don't`, `you don't`], - // [`if you don't mind`, `don't mind`, `don't mind`], - [`if you didn't care`, `didn't`, `didn't`], - // [`if you wouldn't care, i'll eat here`, `i'll eat`, `i'll eat`], //omg hard one - - // [`don't go`, `do not`, `don't`], - [`do not go`, `do not`, `do not`] - // [`i dunno`, `do not`, `dunno`], - //bugs - // [`really remind me to buy`, '#Adverb? #Infinitive (me|us) (to|for)', `really remind me to`], - ].forEach(function(a) { - var m = nlp(a[0]).match(a[1]); - if (!m.found) { - t.equal(a[2], '', 'no-match: ' + a[0] + ' - -' + a[1]); - } else { - var msg = "'" + a[0] + "' - " + a[1] + " - - have : '" + m.out('normal') + "'"; - t.equal(m.out('normal'), a[2], msg); - } - }); - t.end(); - }); - - test('match-from-array :', function(t) { - var m = nlp('spencer is really cool').match(['spencer']); - t.equal(m.out('normal'), 'spencer', 'just-spencer'); - t.equal(m.length, 1, 'one-result'); - - m = nlp('spencer is really cool').match([]); - t.equal(m.out('normal'), '', 'empty match'); - t.equal(m.length, 0, 'zero-results'); - - m = nlp('spencer is really cool'); - var r = m.match(['spencer', 'really']).toUpperCase(); - t.equal(r.out('text'), 'SPENCER REALLY', 'match-spencer-really'); - t.equal(r.length, 2, 'two-results'); - - t.equal(m.out('text'), 'SPENCER is REALLY cool', 'match-spencer-really'); - t.equal(m.length, 1, 'still-one-result'); - t.end(); - }); - - test('match-from-object :', function(t) { - var m = nlp('spencer is really cool').match({ - spencer: true - }); - t.equal(m.out('normal'), 'spencer', 'just-spencer'); - t.equal(m.length, 1, 'one-result'); - t.end(); - }); - - test('tag-match-tag :', function(t) { - var m = nlp('apple is cool'); - m.match(['apple', 'susan']).tag('Person'); - var p = m.people(); - t.equal(p.out('normal'), 'apple', 'apple-tagged'); - t.equal(m.length, 1, 'one-result'); - t.end(); - }); - - test('lump-match:', function(t) { - var m = nlp('hello one two three hello'); - m.match('one two three').lump(); - - t.equal(m.has('hello'), true, 'has-unlumped'); - t.equal(m.has('one two three'), true, 'has-lumped'); - t.equal(m.has('hello one two three'), true, 'word+lumped'); - t.equal(m.has('one two three hello'), true, 'lumped+word'); - - t.equal(m.has('one'), false, 'no-partial1'); - t.equal(m.has('two'), false, 'no-partial2'); - t.equal(m.has('three'), false, 'no-partial3'); - t.equal(m.has('one two'), false, 'no-partial4'); - t.equal(m.has('two three'), false, 'no-partial5'); - t.equal(m.has('hello one two'), false, 'no-partial6'); - t.equal(m.has('three hello'), false, 'no-partial7'); - t.equal(m.has('two three hello'), false, 'no-partial8'); - t.end(); - }); - - test('before-match:', function(t) { - var r = nlp('one two three four five').before('two'); - t.equal(r.out('normal'), 'one', 'before-two'); - - r = nlp('one two three four five').before('three . five'); - t.equal(r.out('normal'), 'one two', 'before-several'); - - r = nlp('one two three four five').before('one two'); - t.equal(r.out('normal'), '', 'no-before-start'); - - // r = nlp('one two three four').before('.'); //tricky - // t.equal(r.out('normal'), '', 'before-any'); - - r = nlp('one two three four. No, not here. He said two days a week.').before('two'); - var arr = r.out('array'); - t.equal(arr[0], 'one', 'before-twice-1'); - t.equal(arr[1], 'he said', 'before-twice-2'); - - r = nlp('it was all the way over to two. It was the number two.').before('it'); - t.equal(r.found, false, 'no-empty-matches'); - - t.end(); - }); - - test('after-match:', function(t) { - var r = nlp('one two three four five').after('two'); - t.equal(r.out('normal'), 'three four five', 'after-one'); - - r = nlp('one two three four five').after('one . three'); - t.equal(r.out('normal'), 'four five', 'after-several'); - - r = nlp('one two three four five').after('four five'); - t.equal(r.out('normal'), '', 'no-afters-end'); - - r = nlp('one two three four').after('.'); - t.equal(r.out('normal'), 'two three four', 'after-any'); - - r = nlp('one two three four. No, not here. He said two days a week.').after('two'); - var arr = r.out('array'); - t.equal(arr[0], 'three four', 'after-twice-1'); - t.equal(arr[1], 'days a week', 'after-twice-2'); - - r = nlp('all the way over to two. It was the number two.').after('two'); - t.equal(r.found, false, 'no-empty-matches'); - - t.end(); - }); -}); diff --git a/test/unit/match/match_tricky.test.js b/test/unit/match/match_tricky.test.js deleted file mode 100644 index 3a5ca3e3f..000000000 --- a/test/unit/match/match_tricky.test.js +++ /dev/null @@ -1,123 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('fancy match', function(t) { - [ - //misc - ['doug is good', '', 0], - ['doug is good', '.', 3], - ['doug is good', '.?', 3], - ['doug is good', '.+', 3], - - //contractions - ['he\'s nice', 'he is', 2], - ['he\'s nice', 'is nice', 2], - ['he\'s nice', 'he\'s', 1], - ['he\'s nice', 'he\'s nice', 3], - ['he\'s nice', 'nice', 1], - - //over/under - ['he is nice', 'is nice and good', 0], - ['is nice', 'he is nice', 0], - - //dot - ['doug is good', 'doug is good', 3], - ['doug is good', 'doug . good', 3], - ['doug is good', 'doug is .', 3], - ['doug is good', '. is .', 3], - ['doug is good', '. . .', 3], - ['doug is good', '. . . .', 0], - - //optional miss - ['doug is good', 'doug is really? good', 3], - ['doug is good', 'doug is .? good', 3], //tricky 'greedy optional' bug - ['doug is good', 'doug is #Adverb? good', 3], - //optional has - ['doug is really good', 'doug is really? good', 4], - ['doug is really good', 'doug is .? good', 4], - ['doug is really good', 'doug is #Adverb? good', 4], - //asterix empty - ['doug is good', 'doug *', 3], - ['doug is good', 'doug is *', 3], - ['doug is good', '*', 3], - //asterix positive - ['doug is good', 'doug * good', 3], - ['doug is really good', 'doug * good', 4], - ['doug is really so very good', 'doug * good', 6], - ['doug is really so very good at stuff', 'doug * good', 6], - ['we think doug is really so very good at stuff', 'doug * good', 6], - //asterix negative - ['doug is good', 'doug * bad', 0], - ['doug is good', 'spencer * bad', 0], - ['doug is good', 'spencer *', 0], - ['doug is good', 'doug * is', 2], //another tricky 'greedy optional' bug - ['cool, fun, great, nice', '#Adjective+ great', 3], - - // - ['Dr. Spencer Smith says hi', 'dr', 1], - ['Dr. Spencer Smith says hi', 'dr spencer', 2], - ['Dr. Spencer Smith says hi', 'dr spencer smith', 3], - ['Dr. Spencer Smith says hi', 'dr spencer smith says', 4], - ['Lately, Dr. Spencer Smith says hi', 'lately dr spencer smith', 4], - //start ^ - ['in toronto', '^toronto', 0], - ['toronto', '^toronto', 1], - ['in toronto', '^in toronto', 2], - ['in toronto', 'in ^toronto', 0], - //end $ - ['it snows', 'it snows', 2], - ['it snows', 'snows$', 1], - ['it snows', 'it snows$', 2], - ['it snows', 'it$ snows', 0], - ['it snows', 'foo$', 0], - //negative ! - ['it really snows', 'it #adverb snows', 3], - ['it really snows', 'it !#adverb snows', 0], - ['it really snows. it goes.', 'it !#adverb', 2], - ['it is nice.', '!#adverb', 3], - //max/min {} - ['if it goes really well', 'if .{1,2} well', 0], - ['if it goes really well', 'if .{1,6} well', 5], - ['so i said that spencer is nice', '^.{1,3} spencer', 0], - ['so i said that spencer is nice', '^.{1,6} spencer', 5], - ['one two three four five', 'one two{1,2}', 2], - ['one two three four five', 'one two{1,3}', 2], - ['one two three four five', 'one two{0,3}', 2], - ['one two three four five', 'one .{0,3} two', 2], - ['one two three four five', 'one .{0,3} three', 3], - ['one two three four five', 'one .{1,3} two', 0], - ['one two three four five six seven', 'one .{0,4} six seven', 7], - //optional/consecutive - ['is really walking', 'is #Adverb+? walking', 3], - ['is walking', 'is #Adverb+? walking', 2], - ['is really really walking', 'is #Adverb+? walking', 4], - ['is really not walking', 'is (#Adverb|not)+? walking', 4], - ['is really not quickly walking', 'is (#Adverb|not)+? walking', 5], - ['is walking', 'is (#Adverb|not)+? walking', 2], - ['Phoenix AZ', '#City #Region', 2], - //this isn't working - ['the canadian senate', 'the (united states|canadian) senate', 3], - ['the canadian senate', '(canadian|united states|british)', 1], - ].forEach(function(a) { - var r = nlp(a[0]).match(a[1]).terms() || []; - var msg = '\'' + a[0] + '\' - - - \'' + a[1] + '\' - - got:' + r.length + ' want:' + a[2]; - t.equal(r.length, a[2], msg); - }); - t.end(); -}); - -test('tricky-case', function(t) { - t.equal(nlp('Number II').has('Number II'), true, 'uppercase-match'); - t.equal(nlp('Number I').has('Number I'), true, 'uppercase-match'); - t.end(); -}); - -test('text-as-input', function(t) { - var doc = nlp('he is from Phoenix AZ'); - var m = doc.match('#City'); - var matchWith = doc.match(m).out('normal'); - var without = doc.not(m).out('text'); - t.equal(matchWith, 'phoenix', 'text-as-match'); - t.equal(without, 'he is from AZ', 'text-as-not'); - t.end(); -}); diff --git a/test/unit/match/not.test.js b/test/unit/match/not.test.js deleted file mode 100644 index 591a28238..000000000 --- a/test/unit/match/not.test.js +++ /dev/null @@ -1,79 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('not-basic :', function(t) { - var m = nlp('spencer is really cool').not('brown'); - t.equal(m.out('text'), 'spencer is really cool', 'missing-not'); - t.equal(m.length, 1, 'one-result'); - - m = nlp('spencer is really cool').not('#Adverb'); - t.equal(m.out('text'), 'spencer is cool', 'one-not'); - t.equal(m.length, 2, 'two-result'); - - m = nlp('spencer is really cool').not('#Adverb+'); - t.equal(m.out('text'), 'spencer is cool', 'still-one-not'); - t.equal(m.length, 2, 'two-results'); - - m = nlp('spencer is really cool').not('#Adverb+'); - t.equal(m.out('text'), 'spencer is cool', 'two-not'); - t.equal(m.length, 2, 'two-results'); - - m = nlp('spencer is really cool').not('is #Adverb+'); - t.equal(m.out('text'), 'spencer cool', 'three-not'); - t.equal(m.length, 2, 'two-results'); - - m = nlp('spencer is really cool. John is really nice.').not('#Adverb'); - t.equal(m.out('text'), 'spencer is cool. John is nice.', 'two-terms-matches'); - t.equal(m.length, 4, 'four-results'); - - m = nlp('spencer is really cool. John is really nice.').not('pardon me, #Adverb'); - t.equal(m.out('text'), 'spencer is really cool. John is really nice.', 'tricky-no-match'); - t.equal(m.length, 2, 'two-original-results'); - - t.end(); -}); - -test('not-from-array :', function(t) { - var m = nlp('spencer is really cool').not(['spencer']); - t.equal(m.out('normal'), 'is really cool', 'not-spencer'); - t.equal(m.length, 1, 'one-results'); - - m = nlp('spencer is really cool').not(['']); - t.equal(m.out('normal'), 'spencer is really cool', 'not-spencer'); - t.equal(m.length, 1, 'one-results'); - - m = nlp('spencer is really cool').not(['spencer', 'really']); - t.equal(m.out('normal'), 'is cool', 'not-spencer-really'); - t.equal(m.length, 2, 'two-results'); - t.end(); -}); - -//test object-form -test('not-from-object :', function(t) { - var m = nlp('spencer is not really cool.'); - var r = m.not({ - not: true, - really: true - }); - t.equal(m.out('normal'), 'spencer is not really cool.', 'double-obj-remains'); - t.equal(r.out('normal'), 'spencer is cool.', 'spencer-double-obj'); - - m = nlp('everyone is cool. I said hi to everyone.').not({ - everyone: true, - totally: true - }); - t.equal(m.out('normal'), 'is cool. i said hi to', 'not-everyone'); - - m = nlp('spencer is really, secretly, very cool.'); - var adv = m.adverbs().not({ - really: true - }); - t.equal(adv.out('normal'), 'secretly very', 'not-subset'); - t.equal(adv.length, 2, 'one-result'); - - var adv2 = m.adverbs().not('secretly'); - t.equal(adv2.out('normal'), 'really very', 'not-subset2'); - t.equal(adv2.length, 2, 'two-results'); - - t.end(); -}); diff --git a/test/unit/match/pluck.test.js b/test/unit/match/pluck.test.js deleted file mode 100644 index 6a963314d..000000000 --- a/test/unit/match/pluck.test.js +++ /dev/null @@ -1,119 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var terms_test = function(r, arr, t) { - var have = r.out('array').join(' - '); - arr = arr.join(' - '); - var msg = have + ' == ' + arr; - t.equal(have, arr, msg); -}; - -test('pluck-people :', function(t) { - [ - ['Sally Daniels went to the park with Don Douglas', ['sally daniels', 'don douglas']], - ['Then Sally went to the park with all her friends.', ['sally']], - ['Oh say can you see? By the dawn\'s early rise.', []], - ['All the base are belong to us.', []] - ].forEach(function(a) { - var terms = nlp(a[0]).people(); - terms_test(terms, a[1], t); - }); - t.end(); -}); - -test('pluck-places :', function(t) { - [ - ['Toronto is the biggest city in Canada', ['toronto', 'canada']], - ['Beijing China grows each year. It is usually sunny.', ['beijing china']], - ['How long is the flight from SFO to LAX? Both in the USA!', ['sfo', 'lax', 'usa']], - ['Oh say can you see? By the dawn\'s early rise.', []] - ].forEach(function(a) { - var terms = nlp(a[0]).places(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); - -test('pluck nouns :', function(t) { - [ - ['Cat eats meat.', ['cat', 'meat']], - ['Running, swimming, jumping.', []], - ['John Doe ran the race', ['john doe', 'race']] - ].forEach(function(a) { - var terms = nlp(a[0]).nouns(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); - -test('pluck-adjectives ', function(t) { - [['Nice dog is eating', ['nice']], ['Beautiful, dirty, rich.', ['beautiful', 'dirty', 'rich']]].forEach(function(a) { - var terms = nlp(a[0]).adjectives(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); - -test('pluck verbs :', function(t) { - [ - ['Cat eats meat.', ['eats']], - ['Beijing China grows each year. It is usually sunny.', ['grows', 'is usually']], - ['Running, swimming, jumping.', ['running', 'swimming', 'jumping']] - ].forEach(function(a) { - var terms = nlp(a[0]).verbs(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); - -test('pluck adverbs :', function(t) { - [ - ['Eat gently, slowly.', ['gently', 'slowly']], - ['John quickly ate the food', ['quickly']], - ['all spectators immediately started cheering hard', ['immediately', 'hard']], - ['walk softly and carry a big stick', ['softly']] - ].forEach(function(a) { - var terms = nlp(a[0]).adverbs(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); - -test('pluck dates :', function(t) { - [ - ['Toronto is best in January', ['january']], - ['My birthday is June 5th', ['june 5th']], - ['Oh say can you see? By the dawn\'s early rise.', []] - ].forEach(function(a) { - var terms = nlp(a[0]).dates(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); - -test('pluck values :', function(t) { - [ - ['The 5 books in Toronto are best in January', ['5']], - ['My harddrive is 5 Gb', ['5 gb']], - ['he is seven', ['seven']], - ['add eight and five', ['eight', 'five']], - ['My birthday is June 5th 1999', ['5th', '1999']], - ['Oh say can you see? By the dawn\'s early rise.', []] - ].forEach(function(a) { - var terms = nlp(a[0]).values(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); - -test('pluck organizations :', function(t) { - [ - ['The 5 books in Toronto are best in January', []], - ['My birthday is June 5th', []], - ['Oh say can you see? By the dawn\'s early rise.', []], - ['Google may purchase Cannabis Inc', ['google', 'cannabis inc']] - ].forEach(function(a) { - var terms = nlp(a[0]).organizations(); - terms_test(terms, a[1], t, true); - }); - t.end(); -}); diff --git a/test/unit/match/prefix.test.js b/test/unit/match/prefix.test.js deleted file mode 100644 index 7a411538e..000000000 --- a/test/unit/match/prefix.test.js +++ /dev/null @@ -1,37 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('prefix/infix/suffix basic', function(t) { - var r = nlp('it is funny and weird'); - var m = r.match('_nny', true); - t.equal(m.out('normal'), 'funny', 'suffix-match'); - m = r.match('fu_', true); - t.equal(m.out('normal'), 'funny', 'prefix_match'); - m = r.match('_nn_', true); - t.equal(m.out('normal'), 'funny', 'infix-match'); - - m = r.match('_ff', true); - t.equal(m.out('normal'), '', 'no-false-suffix'); - m = r.match('ff_', true); - t.equal(m.out('normal'), '', 'no-false-prefix'); - m = r.match('_ff_', true); - t.equal(m.out('normal'), '', 'no-false-infix'); - - m = r.match('_', true); - t.equal(m.out('normal'), '', 'no-throw1'); - m = r.match(' _ ', true); - t.equal(m.out('normal'), '', 'no-throw2'); - m = r.match(' __ ', true); - t.equal(m.out('normal'), '', 'no-throw3'); - m = r.match(' _ _ ', true); - t.equal(m.out('normal'), '', 'no-throw4'); - - m = r.match('w_', true); - t.equal(m.out('normal'), 'weird', 'one-char-one-word'); - m = r.match('_r_', true); - t.equal(m.out('normal'), 'weird', 'one-char-one-word2'); - m = r.match('_y', true); - t.equal(m.out('normal'), 'funny', 'one-char-one-word3'); - - t.end(); -}); diff --git a/test/unit/match/regex.test.js b/test/unit/match/regex.test.js deleted file mode 100644 index 491e90ca7..000000000 --- a/test/unit/match/regex.test.js +++ /dev/null @@ -1,19 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('regex-match:', function(t) { - var doc = nlp('it is waaaay cool'); - var m = doc.match('/aaa/'); - t.equal(m.out('normal'), 'waaaay', 'basic-match'); - - m = doc.match('/[ao]{2}/'); - t.equal(m.out('array').length, 2, 'trickier-match'); - - m = doc.match('is /aaam?/ .'); - t.equal(m.out('normal'), 'is waaaay cool', 'trickier-match'); - - m = doc.match('#Copula /a+/ /ool$/'); - t.equal(m.out('normal'), 'is waaaay cool', 'even-trickier-match'); - - t.end(); -}); diff --git a/test/unit/match/remove.test.js b/test/unit/match/remove.test.js deleted file mode 100644 index c7cdb7478..000000000 --- a/test/unit/match/remove.test.js +++ /dev/null @@ -1,49 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('remove-basic :', function(t) { - var m = nlp('the brown cat played').match('brown').delete().all(); - t.equal(m.out('text'), 'the cat played', 'brown-cat'); - - m = nlp('the nice brown cat played').match('nice brown').delete().all(); - t.equal(m.out('text'), 'the cat played', 'nice-brown'); - - m = nlp('the nice brown cat played').match('#Adjective').delete().all(); - t.equal(m.out('text'), 'the cat played', 'adj-each'); - - m = nlp('the nice brown cat played').match('#Adjective+').delete().all(); - t.equal(m.out('text'), 'the cat played', 'adj-consecutive'); - - t.end(); -}); - -test('remove-match :', function(t) { - var m = nlp('the brown cat played').delete('brown'); - t.equal(m.out('text'), 'the cat played', 'brown-cat'); - - m = nlp('the brown cat played. The brown dog sat down.').delete('brown'); - t.equal(m.out('text'), 'the cat played. The dog sat down.', 'brown-cat'); - - m = nlp('the nice brown cat played. The nice dog waited.').delete('nice brown'); - t.equal(m.out('text'), 'the cat played. The nice dog waited.', 'nice-brown'); - - m = nlp('the nice brown cat played. The cute dogs ate.').delete('#Adjective'); - t.equal(m.out('text'), 'the cat played. The dogs ate.', 'adj-each'); - - m = nlp('the nice brown cat played. The cute dogs ate.').delete('#Adjective+'); - t.equal(m.out('text'), 'the cat played. The dogs ate.', 'adj-consecutive'); - - t.end(); -}); - -test('remove-logic :', function(t) { - var m = nlp('spencer kelly is here').match('spencer kelly').delete('spencer'); - t.equal(m.out('normal'), 'kelly', 'remove(reg) returns this'); - - m = nlp('spencer kelly is here').match('spencer kelly').delete().all(); - t.equal(m.out('normal'), 'is here', 'remove() returns parent'); - - m = nlp('spencer kelly is here').match('spencer kelly').delete('notfound'); - t.equal(m.out('normal'), 'spencer kelly', 'remove(notfound) returns this'); - t.end(); -}); diff --git a/test/unit/match/replace.test.js b/test/unit/match/replace.test.js deleted file mode 100644 index 7927d76b5..000000000 --- a/test/unit/match/replace.test.js +++ /dev/null @@ -1,57 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('replace-basic :', function(t) { - var m = nlp('the dog played').match('dog').replace('cat').all(); - t.equal(m.out('text'), 'the cat played', 'dog-cat'); - - m = nlp('the dog played').match('the dog').replace('a cat').all(); - t.equal(m.out('text'), 'a cat played', 'a-cat'); - - m = nlp('the dog played').match('#Noun').replace('snake').all(); - t.equal(m.out('text'), 'the snake played', 'snake'); - - m = nlp('the pit bull played').match('#Noun+').replace('snake').all(); - t.equal(m.out('text'), 'the snake played', 'pit bull'); - - m = nlp('the pit bull dog played').match('#Noun+').replace('grey snake').all(); - t.equal(m.out('text'), 'the grey snake played', 'pit bull dog'); - - t.end(); -}); - -test('match-replace :', function(t) { - [ - ['the dog played', 'the dog', 'the cat', 'the cat played'], - ['the dog played', 'the #Noun', 'the cat', 'the cat played'], - ['the dog played', 'the (dog|hamster|pet-snake)', 'the cat', 'the cat played'], - ['the boy and the girl', 'the #Noun', 'the house', 'the house and the house'], - ['the boy and the girl', 'the cat', 'the house', 'the boy and the girl'] - ].forEach(function(a) { - var str = nlp(a[0]).replace(a[1], a[2]).out('text'); - var msg = str + ' -- ' + a[3]; - t.equal(str, a[3], msg); - }); - - t.end(); -}); - -test('replace-with-punctuation', function(t) { - var doc = nlp('Simon, how is Pamela and Jason?'); - var str = doc.match('#Person').replace('PERSON').all().out(); - t.equal(str, 'PERSON, how is PERSON and PERSON?', 'replace-with-punctuation'); - t.end(); -}); - -test('structured-object-replace :', function(t) { - var r = nlp('fun times in cool town'); - var term = r.match('times'); - r.replace(term, 'day'); - t.equal(r.out(), 'fun day in cool town', 'structured-replace'); - - r = nlp('fun times in cool town'); - var terms = r.match('cool town'); - r.replace(terms, 'shitsville'); - t.equal(r.out(), 'fun times in shitsville', 'structured-replace-multi'); - t.end(); -}); diff --git a/test/unit/misc.test.js b/test/unit/misc.test.js deleted file mode 100644 index fd6b5c463..000000000 --- a/test/unit/misc.test.js +++ /dev/null @@ -1,61 +0,0 @@ -var test = require('tape') -var nlp = require('./lib/nlp') - -//make sure it can handle garbage inputs -test('garbage:', function(t) { - var garbage = ['', ' ', null, '\n\n', [], {}] - garbage.forEach(function(g, i) { - var num = nlp(g).list.length - var msg = typeof g + ' text input #' + i - t.equal(num, 0, msg) - }) - var str = nlp(2).out() - t.equal(str, '2', 'integer-casted') - str = nlp(2.2).out() - t.equal(str, '2.2', 'float-casted') - - //garbage in lexicon too - str = nlp('hello', null).out() - t.equal(str, 'hello', 'null-lexicon') - - str = nlp('hello', 2).out() - t.equal(str, 'hello', 'int-lexicon') - t.end() -}) - -test('extra exports:', function(t) { - t.ok(nlp.version, 'version number exported') - - t.doesNotThrow(function() { - nlp.verbose(true) - nlp.verbose(false) - }, 'can set verbosity') - - t.end() -}) - -test('misc:', function(t) { - var str = '2 million five hundred thousand and fifty nine is bigger than 2882' - var m = nlp(str) - m.values().toNumber() - t.equal(m.out('normal'), '2500059 is bigger than 2882', str) - - str = '2 million five hundred thousand and fifty nine is bigger than 2882' - m = nlp(str) - m.values().toNice() - t.equal(m.out('text'), '2,500,059 is bigger than 2,882', str) - - str = 'doug is 5 years old' - m = nlp(str) - m.values().toText() - t.equal(m.out('normal'), 'doug is five years old', str) - - var r = nlp('Homer, have you been eating that sandwich again?').terms().slice(0, 3) - t.equal(r.out('text'), 'Homer, have you', 'result.slice') - - // str = 'men go'; - // m = nlp(str).sentences().toPastTense().nouns().toSingular(); - // t.equal(m.out('normal'), 'a man went', str); - - t.end() -}) diff --git a/test/unit/out/offset.test.js b/test/unit/out/offset.test.js deleted file mode 100644 index af2a332bf..000000000 --- a/test/unit/out/offset.test.js +++ /dev/null @@ -1,48 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var freshPrince = require('../lib/freshPrince'); - -test('offsets-equals-substr:', function(t) { - var r = nlp(freshPrince); - var arr = r.verbs().out('offsets'); - arr.forEach(function(obj) { - var substr = freshPrince.substr(obj.offset, obj.length); - t.equal(obj.text, substr, "'" + obj.text + "' offset " + obj.offset); - }); - t.end(); -}); - -test('index-output:', function(t) { - var str = `I am the very model of a modern Major-General. I've information vegetable, animal, and mineral`; - var arr = nlp(str).match('model').out('index'); - t.equal(arr[0].term, 4, 'which term'); - t.equal(arr[0].sentence, 0, 'which sentence'); - t.equal(arr[0].sentenceTerm, 4, 'which sentence-term'); - - arr = nlp(str).match('vegetable').out('index'); - t.equal(arr[0].term, 13, 'which term'); - t.equal(arr[0].sentence, 1, 'which sentence'); - t.equal(arr[0].sentenceTerm, 3, 'which sentence-term'); - t.end(); -}); - -test('offset-with-whitespace:', function(t) { - var str = `I am the very model of a modern Major-General. I've information vegetable, animal, and mineral`; - var place = nlp(str).match('animal').first().out('offset')[0]; - - //full term offset - var substr = str.substring(place.offset, place.offset + place.length); - t.equal(substr, ' animal,', 'offset+length'); - - //no-punctuation or whitespace offset - substr = str.substring(place.wordStart, place.wordEnd); - t.equal(substr, 'animal', 'wordStart-wordEnd'); - - str = 'hello there. I work for the F.B.I. in ft. Mede. hello there!'; - var r = nlp(str); - var o = r.sentences(1).out('offsets')[0]; - substr = str.substring(o.wordStart, o.wordEnd); - t.equal(substr, 'I work for the F.B.I. in ft. Mede', 'keeps-internal-punctuation'); - - t.end(); -}); diff --git a/test/unit/out/out.test.js b/test/unit/out/out.test.js deleted file mode 100644 index 2885dd8d6..000000000 --- a/test/unit/out/out.test.js +++ /dev/null @@ -1,86 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('topk:', function(t) { - var str = 'it is good. it was nice. she is cool.'; - var r = nlp(str); - var arr = r.verbs().out('topk'); - t.equal(arr[0].normal, 'is', '#1 is'); - t.equal(arr[0].count, 2, 'two is count'); - - t.equal(arr[1].normal, 'was', 'one was count'); - t.equal(arr[1].count, 1, 'one was count'); - - arr = nlp('we\'re cool. they are fun').terms().out('freq'); - t.equal(arr[0].normal, 'are', 'contraction- are'); - t.equal(arr[0].count, 2, 'are combined'); - - t.end(); -}); - -test('out-tags:', function(t) { - var str = 'texas rangers are a baseball team'; - var r = nlp(str); - var arr = r.out('tags'); - t.equal(arr.length, 6, '6 terms'); - t.equal(arr[0].normal, 'texas', 'texas #1'); - t.equal(arr[1].normal, 'rangers', 'rangers #2'); - t.equal(arr[2].normal, 'are', 'are #2'); - t.ok(arr[0].tags.indexOf('SportsTeam') !== -1, 'they are a sportsteam'); - t.end(); -}); - -test('out-array:', function(t) { - var str = 'texas rangers are a baseball team. They do not play in houston.'; - var r = nlp(str).verbs(); - var arr = r.out('array'); - t.equal(arr.length, 2, '2 verbs'); - t.equal(arr[0], 'are', 'are #1'); - t.equal(arr[1], 'do not play', 'do not play #2'); - t.end(); -}); - -test('out-csv:', function(t) { - var str = 'John, Jill McGraw, and Moe were swimming'; - var have = nlp(str).people().out('csv'); - var want = 'john\njill,mcgraw\nmoe'; - t.equal(have, want, str + ' -> ' + have); - t.end(); -}); - -test('out-newlines:', function(t) { - var str = 'John, Jill McGraw, and Moe were swimming'; - var have = nlp(str).people().out('newlines'); - var want = 'John,\nJill McGraw,\nMoe'; - t.equal(have, want, want + ' -> ' + have); - t.end(); -}); - -test('out-custom:', function(t) { - var doc = nlp('The competent drum work of Don Brewer?'); - var arr = doc.out({ - text: true, - normal: false, - tags: true, - sdf: true, - root: true - }); - arr = arr[0]; - t.equal(arr[0].text, 'The', 'has text'); - t.equal(arr[5].root, 'don', 'has root'); - t.equal(arr[5].sdf, undefined, 'has no sdf'); - t.equal(arr[0].tags.Determiner, true, 'has tags'); - t.end(); -}); - -test('out-others:', function(t) { - var str = 'texas rangers are a baseball team. They do not play in houston.'; - var r = nlp(str).verbs(); - var txt = r.out('text'); - t.notEqual(r.out('html'), txt, 'html-out'); - t.notEqual(r.out('grid'), txt, 'grid-out'); - t.notEqual(r.out('root'), txt, 'grid-out'); - t.notEqual(r.out('color'), txt, 'color-out'); - t.notEqual(r.out('tags'), txt, 'tags-out'); - t.end(); -}); diff --git a/test/unit/out/sort.test.js b/test/unit/out/sort.test.js deleted file mode 100644 index 997fb8dd1..000000000 --- a/test/unit/out/sort.test.js +++ /dev/null @@ -1,76 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var fns = require('../lib/fns'); - -test('sortAlpha:', function(t) { - var str = 'John xoo, John fredman, John davis, John fredman,'; - var r = nlp(str); - r = r.people(); - r.sort('alpha'); - var want = ['john davis', 'john fredman', 'john fredman', 'john xoo']; - fns.arr_test(r.out('array'), str, want, t); - t.end(); -}); - -test('sortChronological:', function(t) { - var str = 'John xoo, John fredman, John davis'; - var r = nlp(str); - r = r.people(); - r.sort('alphabetical'); - r.sort('chronological'); - var want = ['john xoo', 'john fredman', 'john davis']; - fns.arr_test(r.out('array'), str, want, t); - t.end(); -}); - -test('reverse:', function(t) { - var str = 'John xoo, John fredman, John davis'; - var r = nlp(str); - r = r.people(); - r.sort('alphabetical'); - r.reverse(); - var want = ['john xoo', 'john fredman', 'john davis']; - fns.arr_test(r.out('array'), str, want, t); - t.end(); -}); - -test('length:', function(t) { - var str = 'Amy, John Fredman, Dr. Bill, Alexis Smithsonian'; - var r = nlp(str); - r = r.people(); - r.sort('length'); - r.reverse(); - var want = ['amy', 'dr bill', 'john fredman', 'alexis smithsonian']; - fns.arr_test(r.out('array'), str, want, t); - t.end(); -}); - -test('wordCount:', function(t) { - var str = 'John Fredman, Amy, Dr. Bill G. Gates'; - var r = nlp(str); - r = r.people(); - r.sort('wordCount'); - r.reverse(); - var want = ['dr bill g gates', 'john fredman', 'amy']; - fns.arr_test(r.out('array'), str, want, t); - t.end(); -}); - -test('unique:', function(t) { - var str = 'John xoo, John fredman, john xoo, John davis'; - var r = nlp(str); - r = r.people(); - r.unique(); - var want = ['john xoo', 'john fredman', 'john davis']; - fns.arr_test(r.out('array'), str, want, t); - t.end(); -}); - -test('frequency:', function(t) { - var str = 'John xoo, John fredman, john xoo, John davis'; - var r = nlp(str).people(); - var a = r.out('frequency'); - t.equal(a[0].normal, 'john xoo', 'topk is sorted'); - t.equal(a[0].count, 2, 'topk finds two'); - t.end(); -}); diff --git a/test/unit/result/case.test.js b/test/unit/result/case.test.js deleted file mode 100644 index 6df0da1bd..000000000 --- a/test/unit/result/case.test.js +++ /dev/null @@ -1,31 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('sanity-check case:', function(t) { - var str = 'John xoo, John fredman'; - var r = nlp(str); - str = r.toUpperCase().out('text'); - t.equal(str, 'JOHN XOO, JOHN FREDMAN', 'uppercase'); - - str = r.toLowerCase().out('text'); - t.equal(str, 'john xoo, john fredman', 'lowercase'); - - str = r.toCamelCase().out('text'); - t.equal(str, 'JohnXoo,JohnFredman', 'camelcase'); - t.end(); -}); - -test('tricky case:', function(t) { - var str = 'i am spencer kelly here with Amy Adams.'; - var r = nlp(str); - r.people().toUpperCase(); - str = r.out('text'); - t.equal(str, 'i am SPENCER KELLY here with AMY ADAMS.', 'tricky-uppercase'); - - str = 'the Spencer Kelly Festival of Silly Walks'; - r = nlp(str); - r.match('#TitleCase+').toCamelCase(); - t.equal(r.out('text'), 'the SpencerKellyFestival of SillyWalks', 'tricky-camelcase'); - - t.end(); -}); diff --git a/test/unit/result/clone.test.js b/test/unit/result/clone.test.js deleted file mode 100644 index e6a907a8d..000000000 --- a/test/unit/result/clone.test.js +++ /dev/null @@ -1,33 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('clone:', function(t) { - var arr = [ - 'he eats the alligator', - 'Jumanji is the best move. He eats cheese.', - 'Uperman is wayyyy better than batman!' - ]; - arr.forEach(function(str) { - var m = nlp(str); - var neg = m.clone().sentences().toNegative(); - var past = m.clone().sentences().toPastTense(); - var fut = m.clone().sentences().toFutureTense(); - var adv = m.clone().verbs().insertBefore('really'); - var rm = m.clone().verbs().delete('#Verb'); - var out = m.out(); - t.equal(out, str, 'equals input - ' + out); - t.notEqual(str, neg.out(), 'neg not equal - ' + str); - t.notEqual(str, past.out(), 'past not equal - ' + str); - t.notEqual(str, fut.out(), 'future not equal - ' + str); - t.notEqual(str, adv.out(), 'adv not equal - ' + str); - t.notEqual(str, rm.out(), 'rm not equal - ' + str); - }); - t.end(); -}); - -// test('one-liner:', function (t) { -// var str = 'would somebody please think of the children'; -// var have = nlp(str).clone().toUpperCase().parent.out(); -// t.equal(str, have, 'parent-unchanged'); -// t.end(); -// }); diff --git a/test/unit/result/loops.test.js b/test/unit/result/loops.test.js deleted file mode 100644 index 68ddbe2e5..000000000 --- a/test/unit/result/loops.test.js +++ /dev/null @@ -1,79 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('js-loop-map', function(t) { - var text = 'oh hello. please turn on the lights and then take out the garbage too. After that, play some music.'; - var doc = nlp(text); - var arr = doc.map(m => { - return m.terms(0).out('normal'); - }); - t.equal(arr.length, 3, 'right-size'); - t.equal(arr[0], 'oh', 'oh-first'); - t.equal(arr[1], 'please', 'please-first'); - t.equal(arr[2], 'after', 'after-first'); - t.end(); -}); - -test('js-loop-reduce', function(t) { - var text = 'oh hello. please turn on the lights and then take out the garbage too. After that, play some music.'; - var doc = nlp(text); - var list = doc.reduce((arr, m) => { - arr.push(m.terms(0).out('normal')); - return arr; - }, []); - t.equal(list.length, 3, 'right-size'); - t.equal(list[0], 'oh', 'oh-first'); - t.equal(list[1], 'please', 'please-first'); - t.equal(list[2], 'after', 'after-first'); - - var txt = doc.reduce((str, m) => { - str += m.terms(0).out('normal'); - return str; - }, ''); - t.equal(txt, 'ohpleaseafter', 'reduce-to-a-string'); - t.end(); -}); - -test('js-loop-filter', function(t) { - var text = 'oh hello. please turn on the lights and then take out the garbage too. After that, play some music.'; - var doc = nlp(text); - t.equal(doc.list.length, 3, 'before-filter'); - var doc2 = doc.filter(m => { - return m.terms().out('array').length > 2; - }); - t.equal(doc.list.length, 3, 'same-after-filter'); - t.equal(doc2.list.length, 2, 'new array smaller'); - t.end(); -}); - -test('js-loop-forEach', function(t) { - var text = 'oh hello. please turn on the lights and then take out the garbage too. After that, play some music.'; - var doc = nlp(text); - var arr = []; - doc.forEach(m => { - arr.push(m.firstTerm().out('normal')); - }); - t.equal(arr.length, 3, 'right-size'); - t.equal(arr[0], 'oh', 'oh-first'); - t.equal(arr[1], 'please', 'please-first'); - t.equal(arr[2], 'after', 'after-first'); - t.end(); -}); - -test('js-loop-find', function(t) { - var text = 'oh hello. please turn on the lights and then take out the garbage too. After that, play some music.'; - var doc = nlp(text); - t.equal(doc.list.length, 3, 'before-filter'); - var doc2 = doc.find(m => { - return m.terms(0).out('normal') === 'after'; - }); - t.equal(doc.list.length, 3, 'same-after-filter'); - t.equal(doc2.list.length, 1, 'found one'); - t.equal(doc2.out(), 'After that, play some music.', 'found the right one'); - - var doc3 = doc.find(m => { - return m.terms(0).out('normal') === 'missing term'; - }); - t.equal(doc3, undefined, 'missing value returns undefined'); - t.end(); -}); diff --git a/test/unit/result/lump.test.js b/test/unit/result/lump.test.js deleted file mode 100644 index 2592ce15c..000000000 --- a/test/unit/result/lump.test.js +++ /dev/null @@ -1,53 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('lumper:', function(t) { - var str = 'we live in Toronto Canada and it is cold.'; - var r = nlp(str); - t.equal(r.wordCount(), 9, '9 words start'); - - r.match('#Place+').lump(); - t.equal(r.out('text'), str, 'output unchanged'); - t.equal(r.wordCount(), 8, '8 words now'); - - var term = r.list[0].terms[3]; - t.ok(term.tags.Country, 'has-country-tag'); - t.ok(term.tags.City, 'has-city-tag'); - t.ok(term.tags.Noun, 'has-shared-noun-tag'); - t.end(); -}); - -test('lumper-multiple-matches:', function(t) { - var str = 'imagine if Patrick Watson and Emma Stone got married'; - var r = nlp(str); - t.equal(r.wordCount(), 9, '9 words start'); - - r.match('#Person+').lump(); - t.equal(r.out('text'), str, 'output unchanged'); - t.equal(r.wordCount(), 7, '7 words now'); - - var term = r.list[0].terms[2]; - t.ok(term.tags.FirstName, 'has-firstname-tag'); - t.ok(term.tags.Person, 'has-person-tag'); - - term = r.list[0].terms[4]; - t.ok(term.tags.FirstName, 'has-firstname-tag2'); - t.ok(term.tags.Person, 'has-person-tag2'); - t.end(); -}); - -test('lumper-long:', function(t) { - var str = 'I think Sir Patrick James Watson is cool'; - var r = nlp(str); - t.equal(r.wordCount(), 8, '8 words start'); - - r.match('#Person+').lump(); - t.equal(r.out('text'), str, 'output unchanged'); - t.equal(r.wordCount(), 5, '5 words now'); - - var term = r.list[0].terms[2]; - t.ok(term.tags.FirstName, 'has-firstname-tag'); - t.ok(term.tags.Person, 'has-person-tag'); - - t.end(); -}); diff --git a/test/unit/result/normalize.test.js b/test/unit/result/normalize.test.js deleted file mode 100644 index 75aef9567..000000000 --- a/test/unit/result/normalize.test.js +++ /dev/null @@ -1,122 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var str_test = require('../lib/fns').str_test; - -test('sentence():', function(t) { - [ - ['he is good', 'he is good'], - ['Jack and Jill went up the hill.', 'jack and jill went up the hill.'], - ['Mr. Clinton did so.', 'mr clinton did so.'], - ['he is good', 'he is good'], - ['Jack and Jill went up the hill. She got water.', 'jack and jill went up the hill. she got water.'], - ['Joe', 'joe'], - ['just-right', 'just right'], - ['camel', 'camel'], - ['4', '4'], - ['four', 'four'], - ['john smith', 'john smith'], - ['Dr. John Smith-McDonald', 'dr john smith mcdonald'], - ['Contains no fruit juice. \n\n All rights reserved', 'contains no fruit juice. all rights reserved'] - ].forEach(function(a) { - var str = nlp(a[0]).out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('normalize():', function(t) { - [ - [' so... you like DONUTS? have all the donuts in the WORLD!!!', 'so you like donuts? have all the donuts in the world!'], - ['This is a test. .', 'this is a test.'], - ['Björk, the singer-songwriter...', 'bjork the singer songwriter'], - ['the so-called “fascist dictator”', 'the so called "fascist dictator"'], - // ['the so-called ❛singer-songwriter❜', 'the so called \'singer songwriter\''], - // ['the so-called ❛group of seven❜', 'the so called \'group of 7\''], - ['Director of the F.B.I.', 'director of the fbi'], - ].forEach(function(a) { - var str = nlp(a[0]).normalize().out('text'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('possessives', function(t) { - var doc = nlp(`Corey Hart's pudding and Google's advertising`); - doc = doc.normalize({ - possessives: true, - case: false - }); - t.equal(doc.out(), 'Corey Hart pudding and Google advertising', 'normalize possessives'); - t.end(); -}); - -test('optional params', function(t) { - var doc = nlp(`John Smith bought automobiles (for us)`).normalize({ - case: true, - possessives: true, - parentheses: true, - // plurals: true, - verbs: true, - }); - t.equal(doc.out(), 'john smith buy automobiles', 'many-on'); - t.end(); -}); - -test('honorifics', function(t) { - var tests = [ - ['rear admiral Smith', 'smith'], - ['Lieutenant John Smith', 'john smith'], - // ['Admiral Davis Jr', 'davis jr'], - ['Field marshal Herring', 'herring'], - ['General Lou Gobbells of the US air force', 'lou gobbells of the us air force'], - ['Rear admiral John', 'john'], - ['Lieutenant general James Baker', 'james baker'], - ['Lieutenant colonel Bing Crosby', 'bing crosby'], - ['Major Tom', 'tom'], - ['major effort by President Xi', 'major effort by xi'], - ['Corporal John Herring', 'john herring'], - ['sergeant major Harold', 'harold'], - ['Second lieutenant Semore Hirthman', 'semore hirthman'], - ['first lady Michelle obama', 'michelle obama'], - ['prime minister Stephen Hawking', 'stephen hawking'], - //no names - // ['first lieutenant', '1st lieutenant'], - // ['Sergeant', 'sergeant'], - ]; - tests.forEach((a) => { - var doc = nlp(a[0]); - doc = doc.normalize({ - honorifics: true, - case: true - }); - t.equal(doc.out('normal'), a[1], a[0]); - }); - t.end(); -}); - -test('elipses-whitespace:', function(t) { - var doc = nlp('about this ...').normalize(); - t.equal(doc.out('text'), 'about this', 'normalize seperate elipses'); - - doc = nlp('about this ...').toLowerCase(); - t.equal(doc.out('text'), 'about this ...', 'lowercase elipses'); - - doc = nlp('about this...').normalize(); - t.equal(doc.out('text'), 'about this', 'normalize attatched elipses'); - t.end(); -}); - -test('more-normalize:', function(t) { - var doc = nlp(`i saw first lady michelle obama`); - doc.normalize({ - honorifics: true - }); - t.equal(doc.out('text'), 'i saw michelle obama', 'normalize honorifics'); - - doc = nlp(`google's tax return`); - doc.normalize({ - possessives: true - }); - t.equal(doc.out('text'), 'google tax return', 'normalize possessives'); - t.end(); -}); diff --git a/test/unit/result/punctuation.test.js b/test/unit/result/punctuation.test.js deleted file mode 100644 index 98242f942..000000000 --- a/test/unit/result/punctuation.test.js +++ /dev/null @@ -1,34 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('getPunctuation', function(t) { - var doc = nlp('he is green and cool'); - var arr = doc.match('#Adjective').getPunctuation(); - t.deepEqual(arr, ['', ''], 'both-empty'); - - doc = nlp('he is green, and cool!'); - arr = doc.match('#Adjective').getPunctuation(); - t.deepEqual(arr, [',', '!'], 'both-punctuations'); - - doc = nlp('he is green, and cool! He is Kermit, the frog.'); - arr = doc.match('#Comma').getPunctuation(); - t.deepEqual(arr, [',', ','], 'both-sentences'); - - doc = nlp('he is Kermit, the frog.'); - var char = doc.terms().getPunctuation(2); - t.equal(char, ',', 'support-num-param'); - t.end(); -}); - -test('setPunctuation', function(t) { - var doc = nlp('he is green and cool'); - doc.match('#Adjective and').firstTerm().setPunctuation(','); - t.equal(doc.text(), 'he is green, and cool', 'oxford-comma'); - - doc = nlp('he is green, and cool'); - t.equal(doc.has('#Comma'), true, 'has-comma-tag'); - doc.match('green').firstTerm().setPunctuation('!'); - t.equal(doc.text(), 'he is green! and cool', 'exclaim'); - t.equal(doc.has('#Comma'), false, 'no-more-comma-tag'); - t.end(); -}); diff --git a/test/unit/result/result_fns.test.js b/test/unit/result/result_fns.test.js deleted file mode 100644 index 500753a10..000000000 --- a/test/unit/result/result_fns.test.js +++ /dev/null @@ -1,21 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('result methods', function(t) { - var text = 'this :cookie: <3 💯 so good. It is really nice. Yes it is <3'; - - //has method - var m = nlp(text); - t.equal(m.match('#Emoji').found, true, 'nlp.has positive'); - t.equal(m.match('#SportsTeam').found, false, 'nlp.has neg'); - - //filter string - var small = m.if('#Emoji'); - t.equal(small.out('normal'), 'this :cookie: <3 💯 so good. yes it is <3', 'nlp.filter string'); - - //filter method - small = m.ifNo('#Emoji'); - t.equal(small.out('normal'), 'it is really nice.', 'nlp.filter method'); - - t.end(); -}); diff --git a/test/unit/result/setTag.test.js b/test/unit/result/setTag.test.js deleted file mode 100644 index 8b3b387ac..000000000 --- a/test/unit/result/setTag.test.js +++ /dev/null @@ -1,39 +0,0 @@ -var test = require('tape') -var nlp = require('../lib/nlp') - -test('custom-tags-persist', function(t) { - var r = nlp('i am two years older now') - var two = r.match('#Value').tag('#FunTag') - two.replaceWith('never') - t.equal(two.has('#FunTag'), false, 'custom tag is forgotten') - - r = nlp('i am two years older now') - two = r.match('#Value').tag('#FunTag') - two.replaceWith('three', true) - t.equal(two.has('#FunTag'), true, 'custom tag is kept') - - r = nlp('i am two years older now') - two = r.match('#Value').tag('#FunTag') - two.toUpperCase() - two.values().toNumber() - t.equal(two.has('#FunTag'), true, 'custom tag stays over transformations') - - r = nlp('june 1999') - r.values().toNumber() - var year = r.match('#Year') - t.equal(year.out('normal'), '1999', 'year-stays-a-year') - - //not sure if these should pass.. - // r = nlp('i am two years older now') - // r.match('am').tag('#FunTag') - // r = r.sentences().toFutureTense().toPresentTense().toPastTense() - // var verb = r.match('#FunTag') - // t.equal(verb.out('normal'), 'was', 'tag stays over sentence-change') - - // r = nlp('walked').tag('#FunTag'); - // r = r.verbs().toFutureTense().toPresentTense().toPastTense(); - // verb = r.match('#FunTag'); - // t.equal(verb.out('normal'), 'walked', 'tag stays over verb-change'); - - t.end() -}) diff --git a/test/unit/result/split.test.js b/test/unit/result/split.test.js deleted file mode 100644 index 090bd627c..000000000 --- a/test/unit/result/split.test.js +++ /dev/null @@ -1,70 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var arr_test = require('../lib/fns').arr_test; - -test('splitAfter', function(t) { - [ - ['doug and nancy', 'and', ['doug and', 'nancy']], - ['doug and also nancy', 'and also', ['doug and also', 'nancy']], - ['doug and definetly nancy', 'and #Adverb', ['doug and definetly', 'nancy']], - ['maybe doug but possibly nancy', 'but', ['maybe doug but', 'possibly nancy']], - - ['a x b x c', 'x', ['a x', 'b x', 'c']], - ['a b x c x', 'x', ['a b x', 'c x']], - ['x a b x c', 'x', ['x', 'a b x', 'c']], - ['x x a b c', 'x', ['x', 'x', 'a b c']], - ['a x b x', 'x', ['a x', 'b x']], - ['a x b c x', 'x', ['a x', 'b c x']], - ['x x a b c', 'x', ['x', 'x', 'a b c']], - - ['john, paul, george, ringo', '#Comma', ['john', 'paul', 'george', 'ringo']], - ['doug is really nice', 'is', ['doug is', 'really nice']] - ].forEach(function(a) { - var want = a[2]; - var got = nlp(a[0]).splitAfter(a[1]).out('array'); - arr_test(got, a[0], want, t); - }); - t.end(); -}); - -test('splitBefore', function(t) { - [ - ['doug and nancy', 'and', ['doug', 'and nancy']], - ['doug and also nancy', 'and also', ['doug', 'and also nancy']], - ['doug and definetly nancy', 'and #Adverb', ['doug', 'and definetly nancy']], - ['maybe doug but possibly nancy', 'but', ['maybe doug', 'but possibly nancy']], - ['doug is really nice', 'is', ['doug', 'is really nice']], - - ['a x b x c', 'x', ['a', 'x b', 'x c']], - ['a b x x c', 'x', ['a b', 'x', 'x c']], - ['x a b x c', 'x', ['x a b', 'x c']], - ['x x a b c', 'x', ['x', 'x a b c']], - ['a x b x', 'x', ['a', 'x b', 'x']] - ].forEach(function(a) { - var want = a[2]; - var got = nlp(a[0]).splitBefore(a[1]).out('array'); - arr_test(got, a[0], want, t); - }); - t.end(); -}); - -test('splitOn', function(t) { - [ - ['doug and nancy', 'and', ['doug', 'and', 'nancy']], - ['doug and also nancy', 'and also', ['doug', 'and also', 'nancy']], - ['doug and definetly nancy', 'and #Adverb', ['doug', 'and definetly', 'nancy']], - ['maybe doug but possibly nancy', 'but', ['maybe doug', 'but', 'possibly nancy']], - ['doug is really nice', 'is', ['doug', 'is', 'really nice']], - - ['a x b x c', 'x', ['a', 'x', 'b', 'x', 'c']], - ['a b x x c', 'x', ['a b', 'x', 'x', 'c']], - ['x a b x c', 'x', ['x', 'a b', 'x', 'c']], - ['x x a b c', 'x', ['x', 'x', 'a b c']], - ['a x b x', 'x', ['a', 'x', 'b', 'x']] - ].forEach(function(a) { - var want = a[2]; - var got = nlp(a[0]).splitOn(a[1]).out('array'); - arr_test(got, a[0], want, t); - }); - t.end(); -}); diff --git a/test/unit/result/whitespace.test.js b/test/unit/result/whitespace.test.js deleted file mode 100644 index a8a79dda9..000000000 --- a/test/unit/result/whitespace.test.js +++ /dev/null @@ -1,49 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('sanity-check case:', function(t) { - var m = nlp('john is cool. he is nice'); - m.whitespace.before(' '); - t.equal(m.out('text'), ' john is cool. he is nice'); - - m = nlp('john is cool. he is nice'); - m.whitespace.after(' '); - t.equal(m.out('text'), 'john is cool. he is nice '); - - m = nlp('so john smith is cool.'); - m.people().whitespace.before(' '); - m.people().whitespace.after(' '); - t.equal(m.out('text'), 'so john smith is cool.'); - - t.end(); -}); - -test('slashes-as-whitespace:', function(t) { - var doc = nlp('john is cool/fun'); - t.equal(doc.terms().length, 4, '4 terms'); - t.equal(doc.has('cool'), true, 'has cool'); - t.equal(doc.has('fun'), true, 'has fun'); - t.equal(doc.out('text'), 'john is cool/fun', 'slash in output'); - t.end(); -}); - -test('normalized whitespace', function(t) { - var doc = nlp(`It doesn't matter`); - doc.normalize({ - contractions: false - }); - t.equal(doc.text(), `it doesn't matter`, 'normalized contractionwhitespace'); - t.end(); -}); - -test('punctuation-whitespace-mixing', function(t) { - let doc = nlp(`we released, "Square Up".`); - let arr = doc.terms().map(obj => obj.text()); - t.deepEqual(arr, ['we', ' released,', ' "Square', ' Up".'], 'punctuation 1'); - - doc = nlp('you said ... ?'); - arr = doc.terms().map(obj => obj.text()); - t.deepEqual(arr, ['you', ' said ... ?'], 'punctuation 2'); - - t.end(); -}); diff --git a/test/unit/result/wordcount.test.js b/test/unit/result/wordcount.test.js deleted file mode 100644 index f0b22a6a0..000000000 --- a/test/unit/result/wordcount.test.js +++ /dev/null @@ -1,21 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var str_test = require('../lib/fns').str_test; - -test('==WordCount==', function(t) { - [ - ['he is good', 3], - ['jack and jill went up the hill.', 7], - ['Mr. Clinton did so.', 4], - ['Bill Clinton ate cheese.', 4], - ['5kb of data.', 3], - ['it was five hundred and seventy two.', 7], - ['jack and jill went up the hill. They got water.', 10], - ['Bill Clinton went walking', 4], - ['Bill Clinton will go walking', 5] - ].forEach(function(a) { - var num = nlp(a[0]).terms().length; - str_test(num, a[0], a[1], t); - }); - t.end(); -}); diff --git a/test/unit/subset/adjective/adjective.test.js b/test/unit/subset/adjective/adjective.test.js deleted file mode 100644 index 695ab43d4..000000000 --- a/test/unit/subset/adjective/adjective.test.js +++ /dev/null @@ -1,86 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('==Adjective==', function(T) { - T.test('to_adverb:', function(t) { - [ - ['quick', 'quickly'], - // ['idle', 'idly'], - ['dirty', null], - ['fun', null], - ['full', null], - ['quixotic', 'quixotically'], - ['cute', 'cutely'] - // ['good', 'well'], - // ['low', 'low'] - ].forEach(function(a) { - var arr = nlp(a[0]).adjectives().data(); - var obj = arr[0] || {}; - str_test(obj.adverbForm, a[0], a[1], t); - }); - t.end(); - }); - - T.test(' to_superlative', function(t) { - [ - ['quick', 'quickest'], - ['friendly', 'friendliest'], - // ['caring', 'most caring'], - ['fun', 'most fun'], - ['full', 'fullest'], - // ['quixotic', 'most quixotic'], - ['cute', 'cutest'], - ['large', 'largest'] - ].forEach(function(a) { - var arr = nlp(a[0]).adjectives().data(); - var obj = arr[0] || {}; - str_test(obj.superlative, a[0], a[1], t); - }); - t.end(); - }); - // - T.test(' to_comparative', function(t) { - [ - ['quick', 'quicker'], - ['friendly', 'friendlier'], - // ['caring', 'more caring'], - ['fun', 'more fun'], - ['full', 'fuller'], - // ['quixotic', 'more quixotic'], - ['cute', 'cuter'] - ].forEach(function(a) { - var arr = nlp(a[0]).adjectives().data(); - var obj = arr[0] || {}; - str_test(obj.comparative, a[0], a[1], t); - }); - t.end(); - }); - // - T.test(' to_noun', function(t) { - [ - ['quick', 'quickness'], - ['fancy', 'fanciness'], - // ['ferocious', 'ferociousness'], - // ['', ''], - // [' ', ''], - ['clean', 'cleanliness'] - ].forEach(function(a) { - var arr = nlp(a[0]).adjectives().data(); - var obj = arr[0] || {}; - str_test(obj.nounForm, a[0], a[1], t); - }); - t.end(); - }); - // - T.test(' conjugate', function(t) { - var o = nlp('nice').adjectives().data()[0] || {}; - str_test(o.comparative, 'nice', 'nicer', t); - str_test(o.superlative, 'nice', 'nicest', t); - str_test(o.adverbForm, 'nice', 'nicely', t); - str_test(o.nounForm, 'nice', 'niceness', t); - t.end(); - }); - - T.end(); -}); diff --git a/test/unit/subset/adverb/adverb.test.js b/test/unit/subset/adverb/adverb.test.js deleted file mode 100644 index bfb341c73..000000000 --- a/test/unit/subset/adverb/adverb.test.js +++ /dev/null @@ -1,66 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('==Adverb==', function(T) { - T.test('to_adjective:', function(t) { - [ - ['quickly', 'quick'], - ['garishly', 'garish'], - ['tediously', 'tedious'], - ['frightfully', 'frightful'], - ['tortuously', 'tortuous'], - ['privately', 'private'], - ['unambiguously', 'unambiguous'], - ['cortically', 'cortic'], - ['biradially', 'biradial'], - ['meanly', 'mean'], - ['raspingly', 'rasping'], - ['comprehensively', 'comprehensive'], - ['fervently', 'fervent'], - ['nationally', 'national'], - ['maternally', 'maternal'], - ['flashily', 'flashy'], - ['only', 'only'], - ['narrowly', 'narrow'], - ['blasphemously', 'blasphemous'], - ['abortively', 'abortive'], - ['inoffensively', 'inoffensive'], - ['truly', 'true'], - ['gently', 'gent'], - ['tolerantly', 'tolerant'], - ['enchantingly', 'enchanting'], - ['unswervingly', 'unswerving'], - ['grubbily', 'grubby'], - ['longitudinally', 'longitudinal'], - ['thermodynamically', 'thermodynamic'], - ['mirthfully', 'mirthful'], - ['salaciously', 'salacious'], - ['dourly', 'dour'], - ['credulously', 'credulous'], - ['carefully', 'careful'], - ['knowingly', 'knowing'], - ['geometrically', 'geometrical'], - ['unassailably', 'unassailable'], - ['antecedently', 'antecedent'], - ['adjectively', 'adjective'], - ['hebdomadally', 'hebdomadal'], - ['dizzily', 'dizzy'], - ['obnoxiously', 'obnoxious'], - ['thirstily', 'thirsty'], - ['biennially', 'biennial'], - ['roguishly', 'roguish'], - ['mentally', 'mental'], - ['incessantly', 'incessant'], - ['intelligently', 'intelligent'], - ['perseveringly', 'persevering'], - ['namely', 'name'], - ['formidably', 'formidable'], - ['vertically', 'vertical'] - ].forEach(function(a) { - var o = nlp(a[0]).tag('Adverb').adverbs().data()[0]; - var msg = a[0] + ' -> ' + o.adjectiveForm; - t.equal(o.adjectiveForm, a[1], msg); - }); - t.end(); - }); -}); diff --git a/test/unit/subset/allSubset.test.js b/test/unit/subset/allSubset.test.js deleted file mode 100644 index 341d67050..000000000 --- a/test/unit/subset/allSubset.test.js +++ /dev/null @@ -1,69 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var fns = require('../lib/fns'); -var freshPrince = require('../lib/freshPrince'); - -var subsets = [ - 'acronyms', - 'adjectives', - 'adverbs', - 'contractions', - 'dates', - 'hashTags', - 'organizations', - 'people', - 'phoneNumbers', - 'places', - 'sentences', - 'questions', - 'statements', - 'nouns', - 'urls', - 'values', - 'verbs' -]; - -test('all combined subsets empty:', function(t) { - var r = nlp(freshPrince); - var small = r.all(); - for (var i = 0; i < subsets.length; i++) { - var sub = subsets[i]; - small = small[sub](); - } - t.equal(small.out('text'), '', 'no-uber subset'); - t.end(); -}); - -test('all subsets have a data method:', function(t) { - var r = nlp(freshPrince); - subsets.forEach(function(s) { - var sub = r[s](); - var arr = sub.data(); - t.ok(fns.isArray(arr), s + '.data() is an array'); - }); - t.end(); -}); - -test('all subsets support .all():', function(t) { - var txt = freshPrince; - var r = nlp(txt); - subsets.forEach(function(s) { - var sub = r[s](); - var str = sub.all().out('text'); - var msg = s + '.all() works'; - t.equal(str, txt, msg); - }); - t.end(); -}); - -test('all subsets have an empty 100th element', function(t) { - var txt = freshPrince; - var r = nlp(txt); - subsets.forEach(function(s) { - var sub = r[s](9999); - var str = sub.out('text'); - var msg = s + ' is empty'; - t.equal(str, '', msg); - }); - t.end(); -}); diff --git a/test/unit/subset/contractions/basic.test.js b/test/unit/subset/contractions/basic.test.js deleted file mode 100644 index 0727ea898..000000000 --- a/test/unit/subset/contractions/basic.test.js +++ /dev/null @@ -1,137 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('basic is contractions', function(t) { - var r = nlp(`he is cool.`); - r.contractions().expand(); - t.equal(r.out('text'), `he is cool.`, 'expanded-expand'); - - r = nlp(`he's cool.`); - r.contractions().expand(); - t.equal(r.out('text'), `he is cool.`, 'contracted-expand'); - - r = nlp(`he is cool.`); - r.contractions().contract(); - t.equal(r.out('text'), `he's cool.`, 'expanded-contract'); - - r = nlp(`he's cool.`); - r.contractions().contract(); - t.equal(r.out('text'), `he's cool.`, 'contracted-contract'); - - r = nlp(`that's really great.`); - r.contractions().expand(); - t.equal(r.out('text'), `that is really great.`, 'contracted-expand'); - - r = nlp(`she'll, eat icecream`); - r.contractions().expand(); - t.equal(r.out('text'), `she will eat icecream`, 'with-punctuation'); - - r = nlp("we're not gonna take it, no we're not gonna take it"); - r.contractions().expand(); - t.equal(r.out('text'), `we are not going to take it, no we are not going to take it`, 'expand gonna twice'); - - r = nlp("let's let's we're gonna gonna"); - r.contractions().expand(); - t.equal(r.out('text'), `let us let us we are going to going to`, 'expand consecutive'); - t.end(); -}); - -test('do-not contractions', function(t) { - var r = nlp(`please do not eat the marshmellow`); - r.contractions().expand(); - t.equal(r.out('text'), `please do not eat the marshmellow`, 'expanded-expand'); - - r = nlp(`please don't eat the marshmellow`); - r.contractions().expand(); - t.equal(r.out('text'), `please do not eat the marshmellow`, 'contracted-expand'); - - r = nlp(`please do not eat the marshmellow`); - r.contractions().contract(); - t.equal(r.out('text'), `please don't eat the marshmellow`, 'expanded-contract'); - - r = nlp(`please don't eat the marshmellow`); - r.contractions().contract(); - t.equal(r.out('text'), `please don't eat the marshmellow`, 'contracted-contract'); - - t.end(); -}); - -test('have contractions', function(t) { - var r = nlp(`i have stood`); - r.contractions().expand(); - t.equal(r.out('text'), `i have stood`, 'expanded-expand'); - - r = nlp(`i've stood`); - r.contractions().expand(); - t.equal(r.out('text'), `i have stood`, 'contracted-expand'); - - r = nlp(`i have stood`); - r.contractions().contract(); - t.equal(r.out('text'), `i've stood`, 'expanded-contract'); - - r = nlp(`i've stood`); - r.contractions().contract(); - t.equal(r.out('text'), `i've stood`, 'contracted-contract'); - t.end(); -}); - -test('repeated contract-expand', function(t) { - var r = nlp(`i'm good`); - r.contractions().expand(); - t.equal(r.out('text'), `i am good`, 'expand-1'); - r.contractions().contract(); - t.equal(r.out('text'), `i'm good`, 'contract-1'); - r.contractions().expand(); - t.equal(r.out('text'), `i am good`, 'expand-2'); - r.contractions().contract(); - t.equal(r.out('text'), `i'm good`, 'contract-2'); - - r - .contractions() - .contract() - .contract() - .contract(); - t.equal(r.out('text'), `i'm good`, 'contract-n'); - - r - .contractions() - .expand() - .expand() - .expand(); - t.equal(r.out('text'), `i am good`, 'expand-n'); - t.end(); -}); - -test('contracted', function(t) { - var r = nlp(`I'll go to Toronto. I will see.`); - var str = r - .contractions() - .contracted() - .out('text'); - t.equal(str, `I'll`, 'contracted'); - str = r - .contractions() - .expanded() - .out('text'); - t.equal(str, `I will`, 'expanded'); - t.end(); -}); - -test('would-or-did', function(t) { - var r = nlp(`i'd contemplate`); - var str = r - .contractions() - .expand() - .all() - .out('text'); - t.equal(str, `i would contemplate`, 'i-would'); - - r = nlp(`i'd contemplated`); - str = r - .contractions() - .expand() - .all() - .out('text'); - t.equal(str, `i had contemplated`, 'i-had'); - t.end(); -}); diff --git a/test/unit/subset/contractions/contractions.test.js b/test/unit/subset/contractions/contractions.test.js deleted file mode 100644 index 1540ba061..000000000 --- a/test/unit/subset/contractions/contractions.test.js +++ /dev/null @@ -1,230 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('==contractions==', function(T) { - T.test('possessives-or-contractions:', function(t) { - [ - [`spencer's good`, `spencer is good`], - [`spencer's house`, `spencer's house`], - [`he's good`, `he is good`], - [`spencer's really good`, `spencer is really good`], - [`google's about to earn money`, `google is about to earn money`], - [`they're mark's 'question marks'`, `they are mark's question marks`], - - [`toronto's citizens`, `toronto's citizens`], - [`rocket's red glare`, `rocket's red glare`], - [`everyone's victories`, `everyone's victories`], - [`the tornado's power`, `the tornado's power`], - - [`somebody's walking`, `somebody is walking`], - // [`spencer's walking`, `spencer was walking`], //ambiguous - - [`spencer's walked`, `spencer has walked`], - [`spencer's had problems`, `spencer has had problems`], - [`spencer's got potatoes`, `spencer has got potatoes`], - [`spencer's gotten groceries`, `spencer has gotten groceries`], - [`he's become fat`, `he has become fat`], - [`she's earned money`, `she has earned money`], - [`he's not ever milked a cow`, `he has not ever milked a cow`] - ].forEach(function(a) { - var m = nlp(a[0]); - m.contractions().expand(); - var str = m.out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); - }); - - T.test('contraction-pos:', function(t) { - [ - [`john's good`, `Person`], - [`ankara's good`, `Place`], - [`January's good`, `Date`], - [`john's cousin`, `Person`], - [`ankara's citizens`, `Place`], - [`January's weather`, `Date`] - ].forEach(function(a) { - var term = nlp(a[0]).list[0].terms[0]; - var msg = term.text + ' has tag ' + a[1]; - t.equal(term.tags[a[1]], true, msg); - }); - t.end(); - }); - - T.test('expand:', function(t) { - [ - [`he's a hero`, ['he', 'is']], - [`she's here`, ['she', 'is']], - [`it's a hero`, ['it', 'is']], - [`he'd win`, ['he', 'would']], - [`they'd win`, ['they', 'would']], - [`they've begun`, ['they', 'have']], - [`they'll begun`, ['they', 'will']], - [`we've begun`, ['we', 'have']], - [`don't go`, ['do', 'not']], - // dont expand leading 'nt contraction - [`mustn't go`, ['must', 'not']], - [`haven't gone`, ['have', 'not']], - [`isn't going`, ['is', 'not']], - ['can\'t go', ['can', 'not']], - ['ain\'t going', ['is', 'not']], - ['won\'t go', ['will', 'not']], - - ['i\'d go', ['i', 'would']], - ['she\'d go', ['she', 'would']], - ['he\'d go', ['he', 'would']], - ['they\'d go', ['they', 'would']], - ['we\'d go', ['we', 'would']], - - ['i\'ll go', ['i', 'will']], - ['she\'ll go', ['she', 'will']], - ['he\'ll go', ['he', 'will']], - ['they\'ll go', ['they', 'will']], - ['we\'ll go', ['we', 'will']], - - ['i\'ve go', ['i', 'have']], - ['they\'ve go', ['they', 'have']], - ['we\'ve go', ['we', 'have']], - ['should\'ve go', ['should', 'have']], - ['would\'ve go', ['would', 'have']], - ['could\'ve go', ['could', 'have']], - ['must\'ve go', ['must', 'have']], - - ['i\'m going', ['i', 'am']], - ['we\'re going', ['we', 'are']], - ['they\'re going', ['they', 'are']], - - [`don't`, ['do', 'not']], - [`do not`, ['do', 'not']], - [`dunno`, ['do', 'not', 'know']], - - [`spencer's going`, ['spencer', 'is']], - [`he's going`, ['he', 'is']], - - [`how'd`, ['how', 'did']], - // [`why'd`, ['why', 'did']], - // [`who'd`, ['who', 'did']], - [`when'll`, ['when', 'will']], - [`how'll`, ['how', 'will']], - [`who'll`, ['who', 'will']], - [`who's`, ['who', 'is']], - [`how's`, ['how', 'is']] - ].forEach(function(a) { - var arr = nlp(a[0]).contractions().expand().out('terms'); - var got = arr.map(function(term) { - return term.normal; - }); - var msg = a[0] + ' - - [' + got.join(', ') + '] should be [' + a[1].join(', ') + ']'; - t.deepEqual(got, a[1], msg); - }); - t.end(); - }); - // - T.test('contract:', function(t) { - [ - [`he is a hero`, `he's`], - [`she is here`, `she's`], - [`it is a hero`, `it's`], - [`he would win`, `he'd`], - [`they would win`, `they'd`], - [`they have begun`, `they've`], - [`how will`, `how'll`], - [`when will`, `when'll`], - [`who did`, `who'd`], - [`who is`, `who's`] - ].forEach(function(a) { - var term = nlp(a[0]).contractions().contract().list[0].terms[0]; - str_test(term.normal, a[0], a[1], t); - }); - t.end(); - }); - - T.test('preserve-contractions:', function(t) { - [`he is a hero`, `she is here`, `it is a hero`, `he would win`, `they would win`].forEach(function(a) { - var str = nlp(a[0]).out('normal'); - str_test(str, a[0], a[0], t); - }); - t.end(); - }); - - T.test('reverse-is-consistent:', function(t) { - var str = `doesn't there's i'd i'll can't won't wasn't weren't wouldn't haven't`; - var doc = nlp(str); - doc.contractions().expand(); - doc.contractions().contract(); - doc.contractions().expand(); - doc.contractions().contract(); - t.equal(doc.out(), str, 'idempodent expand/contract'); - t.end(); - }); - - T.test('contraction-supports-whitespace:', function(t) { - [ - ['We\'ve only just begun', 'We have only just begun'], - ['We\'ve only just begun', 'We have only just begun'] - ].forEach(function(a) { - var m = nlp(a[0]); - m.contractions().expand(); - var str = m.out('text'); - str_test(str, a[0], a[1], t); - }); - t.end(); - }); - - T.test('numberRange-contraction:', function(t) { - var r = nlp('june 5-7 1998').match('5 to 7'); - t.equal(r.out('normal'), '5-7', 'june 5-7 numberRange'); - - r = nlp('rooms 99-102').match('99 to 102'); - t.equal(r.out('normal'), '99-102', 'rooms 99-102'); - - r = nlp('around 7.5-8').match('7.5 to 8'); - t.equal(r.out('normal'), '7.5-8', 'around 7.5-8'); - - r = nlp('june 5th-7th 1998').match('5th to 7th'); - t.equal(r.out('normal'), '5th-7th', 'june 5th-7th numberRange'); - - r = nlp('june 5th - 7th 1998').match('5th to 7th'); - t.equal(r.out('text'), ' 5th - 7th', 'june 5th - 7th numberRange'); - - t.end(); - }); - - T.test('numberRange-expand:', function(t) { - var r = nlp('june 5-7 1998'); - r.contractions().expand(); - var str = r.out('normal'); - t.equal(str, 'june 5 to 7 1998', 'june 5-7 numberRange'); - - r = nlp('rooms 99-102'); - r.contractions().expand(); - str = r.out('normal'); - t.equal(str, 'rooms 99 to 102', 'rooms 99-102'); - - r = nlp('june 5th-7th 1998'); - r.contractions().expand(); - str = r.out('normal'); - t.equal(str, 'june 5th to 7th 1998', 'june 5th-7th numberRange'); - - r = nlp('june 5th - 7th 1998'); - r.contractions().expand(); - str = r.out('normal'); - t.equal(str, 'june 5th to 7th 1998', 'june 5th - 7th numberRange'); - - var doc = nlp('measuring 7.5–11 micrometers'); - doc.contractions().expand(); - doc.values().toNice(); - t.equal('measuring 7.5 to 11 micrometers', doc.out(), 'numer-range-emdash'); - doc.values().toText(); - t.equal('measuring seven point five to eleven micrometers', doc.out(), 'numer-range-emdash2'); - - t.end(); - }); - - T.test('not-a-numberRange:', function(t) { - var doc = nlp('twenty-two'); - t.equal(doc.has('#NumberRange'), false, 'twenty-two not numberRange'); - t.end(); - }); -}); diff --git a/test/unit/subset/date/basic_date.test.js b/test/unit/subset/date/basic_date.test.js deleted file mode 100644 index 338e45e84..000000000 --- a/test/unit/subset/date/basic_date.test.js +++ /dev/null @@ -1,64 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('date-parse :', function(t) { - [ - ['june 5th 1999', [5, 5, 1999]], - ['june 5th 1999', [5, 5, 1999]], - ['january 1st 1644', [0, 1, 1644]], - ['jan 1st 1644', [0, 1, 1644]], - ['June 4th 1993', [5, 4, 1993]], - ['March 1st 1987', [2, 1, 1987]], - ['June 22nd 2014', [5, 22, 2014]], - ['may 22nd 2014', [4, 22, 2014]], - ['sep 22nd 2014', [8, 22, 2014]], - ['apr 22nd 2014', [3, 22, 2014]], - ['June 22nd 1997', [5, 22, 1997]], - ['3rd of March 1969', [2, 3, 1969]], - ['2nd of April 1929', [3, 2, 1929]], - ['2nd of jul 1929', [6, 2, 1929]], - //incomplete dates - ['March 1969', [2, null, 1969]], - ['March 18th', [2, 18, null]], - ['August 28th', [7, 28, null]], - ['18th of March', [2, 18, null]], - ['27th of March', [2, 27, null]], - // ['2012-2014', [null, null, 2012]], - // ['1997-1998', [null, null, 1997]], - // ['1998', [null, null, 1998]], - // ['1672', [null, null, 1672]], - // ['2015', [null, null, 2015]], - ['january 5th 1998', [0, 5, 1998]], - ['february 10th', [1, 10, null]], - ['february 30th', [1, 30, null]], - ['jan 1921', [0, null, 1921]] - //invalid dates - // ['303rd of March 1969', [2, null, 1969]], - // ['4103', [null, null, null]], - - // ['January 5th 4032', [0, 5, null]], - ].forEach(function(a) { - var arr = nlp(a[0]).dates().data(); - var o = arr[0].date; - var got = [o.month, o.date, o.year]; - var msg = 'date "' + a[0] + '" got: [' + got.join(',') + '] want: [' + a[1].join(',') + ']'; - t.deepEqual(got, a[1], msg); - }); - t.end(); -}); - -// durations // - -// ['March 7th-11th 1987', [2, 7, 1987]], -// ['June 1st-11th 1999', [5, 1, 1999]], -// ['28th of September to 5th of October 2008', [8, 28, 2008]], -// ['2nd of January to 5th of October 2008', [9, 5, 2008]], -// ['March 7th to june 11th 1987', [2, 7, 1987]], -// ['April 17th to september 11th 1981', [3, 17, 1981]], -// ['June 1st to June 11th 2014', [5, 1, 2014]], -// ['between 13 February and 15 February 1945', [1, 13, 1945]], -// ['between March 7th and june 11th 1987', [2, 7, 1987]], -// ['3rd - 5th of March 1969', [2, 3, 1969]], -// ["September 1939 to April 1945", ["month":null,"day":null,"year":1939]], -// ["June 1969 to April 1975", ["month":null,"day":null,"year":1969]], -// ["2014-1998", ["month":null,"day":null,"year":null]], diff --git a/test/unit/subset/date/misc_date.test.js b/test/unit/subset/date/misc_date.test.js deleted file mode 100644 index 053e18ca7..000000000 --- a/test/unit/subset/date/misc_date.test.js +++ /dev/null @@ -1,40 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('short+long form', function(t) { - var r = nlp('wednesday, january 2nd, 2016'); - var shorter = r.dates().toShortForm().out('normal'); - t.equal(shorter, 'wed jan 2nd 2016'); - - var r2 = nlp('Thurs, feb 2nd, 2016'); - var longer = r2.dates().toLongForm().out('normal'); - t.equal(longer, 'thursday february 2nd 2016'); - - - var doc = nlp('April, June, and Sept'); - shorter = doc.dates().toShortForm().all().out('normal'); - t.equal(shorter, 'apr jun and sept', 'months-short'); - longer = doc.dates().toLongForm().all().out('normal'); - t.equal(longer, 'april june and september', 'months-longer'); - - r2 = nlp('Thurs, feb 2nd, 2016'); - longer = r2.dates().toLongForm().out('normal'); - t.equal(longer, 'thursday february 2nd 2016'); - - - var str = nlp('April, June, and Sept').dates().toShortForm().all().out(); - t.equal('Apr, Jun, and Sept', str, 'toShortForm-comma'); - - str = nlp('Apr, June, and Sept').dates().toLongForm().all().out(); - t.equal('April, June, and September', str, 'toShortForm-comma'); - - doc = nlp('January 10, 2018 7:20 AM'); - var obj = doc.dates().data()[0].date; - t.equal(obj.month, 0, 'month'); - t.equal(obj.date, 10, 'date'); - t.equal(obj.year, 2018, 'year'); - t.equal(obj.time.hour, 7, 'hour'); - t.equal(obj.time.minute, 20, 'minute'); - - t.end(); -}); diff --git a/test/unit/subset/ngrams/edgegram.test.js b/test/unit/subset/ngrams/edgegram.test.js deleted file mode 100644 index 89a359c48..000000000 --- a/test/unit/subset/ngrams/edgegram.test.js +++ /dev/null @@ -1,26 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('edgegram-sizes:', function(t) { - var r = nlp(`he is cool. john was cool. He is really nice.`); - - var arr = r.startGrams(null, 5).data(); - t.equal(arr.length, 0, 'no-overgrams'); - - arr = r.startGrams(null, 4).data(); - t.equal(arr.length, 1, 'one-4-startgram'); - - arr = r.endGrams(null, 4).data(); - t.equal(arr.length, 1, 'one-4-endgram'); - - t.end(); -}); - -test('start-sizes:', function(t) { - var r = nlp(`he is cool. john was cool. He is really nice.`); - var arr = r.startGrams().data(); - t.equal(arr[0].normal, 'he is', 'sorted-by-freq'); - t.equal(arr[0].count, 2, 'normalized-counted'); - t.equal(arr[0].size, 2, 'normalized-counted'); - t.end(); -}); diff --git a/test/unit/subset/ngrams/ngram.test.js b/test/unit/subset/ngrams/ngram.test.js deleted file mode 100644 index fd2f31759..000000000 --- a/test/unit/subset/ngrams/ngram.test.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('ngram-test:', function(t) { - var r = nlp('he is strong. he is cool'); - var arr = r.ngrams().data(); - - t.equal(arr[0].normal, 'he is', 'sorted-by-freq'); - t.equal(arr[0].count, 2, 'normalized-counted'); - t.equal(arr[0].size, 2, 'normalized-counted'); - - t.equal(arr.length, 9, 'ngram-length'); - t.end(); -}); - -test('sort-bigrams:', function(t) { - var r = nlp('he is strong. he is cool'); - var arr = r.ngrams({ - size: 2 - }).data(); - t.equal(arr[0].normal, 'he is', '#1-by-freq'); - t.equal(arr[1].normal, 'is strong', '#2-by-freq'); - t.equal(arr[2].normal, 'is cool', '#3-by-freq'); - t.equal(arr.length, 3, 'ngram-length'); - t.end(); -}); - -test('contractions-support:', function(t) { - var r = nlp('It\'s free for me and free for you'); - var arr = r.ngrams().data(); - var obj = arr.find((o) => o.normal === 'free for'); - t.equal(obj.count, 2, 'dont include empty contraction'); - t.end(); -}); - -test('ngrams-options:', function(t) { - var doc = nlp('one two three four five, one two three four five, one two three four five'); - var arr = doc.ngrams({ - max: 5 - }).data(); - t.equal(arr[0].size, 5, 'ngram-max-size-5'); - arr = doc.ngrams({ - max: 2 - }).data(); - t.equal(arr[0].size, 2, 'ngram-max-size-2'); - arr = doc.ngrams({ - max: 9 - }).data(); - t.equal(arr[0].size, 5, 'ngram-max-size-9'); - - arr = doc.ngrams({ - size: 2 - }).data(); - t.equal(arr[0].size, 2, 'ngram-size-2'); - arr = doc.ngrams({ - size: 4 - }).data(); - t.equal(arr[0].size, 4, 'ngram-size-4'); - t.end(); -}); diff --git a/test/unit/subset/noun/article.test.js b/test/unit/subset/noun/article.test.js deleted file mode 100644 index ad305e696..000000000 --- a/test/unit/subset/noun/article.test.js +++ /dev/null @@ -1,24 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('.article():', function(t) { - [ - ['duck', 'a'], - ['eavesdropper', 'an'], - ['alligator', 'an'], - // ['hour', 'an'], - ['NDA', 'an'], - ['F.B.I', 'an'], - ['N.D.A.', 'an'], - ['eulogy', 'a'], - ['ukalele', 'a'], - ['skateboards', 'the'], - ['John Smith', ''], - ['Tony Danza', ''] - ].forEach(function(a) { - var o = nlp(a[0]).tag('Noun').nouns().data()[0]; - var msg = a[0] + ' -> ' + o.article; - t.equal(o.article, a[1], msg); - }); - t.end(); -}); diff --git a/test/unit/subset/noun/inflect.test.js b/test/unit/subset/noun/inflect.test.js deleted file mode 100644 index bb254aecd..000000000 --- a/test/unit/subset/noun/inflect.test.js +++ /dev/null @@ -1,206 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('==Plurals==', function(T) { - T.test('is_plural():', function(t) { - [ - ['octopus', false], - ['tree', false], - ['trees', true], - // ['i', false], - ['mayor of chicago', false], - ['mayors of chicago', true], - ['octopus', false], - ['octopi', true], - ['eyebrow', false], - ['eyebrows', true], - ['child', false], - ['children', true], - ['spencer\'s', false], - ['toronto\'s', false], - ['circus', false], - ['circuses', true] - // ['simpsons\'', false], - // ['she\'s', false], - ].forEach(function(a) { - var r = nlp(a[0]).nouns(); - var msg = a[0]; - t.equal(r.isPlural().found, a[1], msg); - }); - t.end(); - }); - - T.test('singularize:', function(t) { - [ - // ["Joneses", "Jones"], - ['children', 'child'], - ['women', 'woman'], - ['men', 'man'], - ['people', 'person'], - ['geese', 'goose'], - ['mice', 'mouse'], - ['barracks', 'barracks'], - ['deer', 'deer'], - ['nuclei', 'nucleus'], - ['syllabi', 'syllabus'], - ['fungi', 'fungus'], - ['cacti', 'cactus'], - ['theses', 'thesis'], - ['crises', 'crisis'], - ['phenomena', 'phenomenon'], - ['embryos', 'embryo'], - ['frescos', 'fresco'], - ['ghettos', 'ghetto'], - ['halos', 'halo'], - ['mangos', 'mango'], - ['mementos', 'memento'], - ['mottos', 'motto'], - ['tornados', 'tornado'], - ['tuxedos', 'tuxedo'], - ['volcanos', 'volcano'], - ['crises', 'crisis'], - ['analyses', 'analysis'], - ['aircraft', 'aircraft'], - ['bass', 'bass'], - ['bison', 'bison'], - ['fish', 'fish'], - ['fowl', 'fowl'], - ['kilos', 'kilo'], - ['kimonos', 'kimono'], - ['logos', 'logo'], - ['memos', 'memo'], - ['ponchos', 'poncho'], - ['photos', 'photo'], - ['pimentos', 'pimento'], - ['pros', 'pro'], - ['sombreros', 'sombrero'], - ['tacos', 'taco'], - ['memos', 'memo'], - ['torsos', 'torso'], - ['xylophones', 'xylophone'], - ['quintuplets', 'quintuplet'], - ['worrywarts', 'worrywart'], - ['nerds', 'nerd'], - ['lollipops', 'lollipop'], - ['eyebrows', 'eyebrow'], - // ['mayors of chicago', 'mayor of chicago'], - //test that sungular.singularize()==singular.. - ['mango', 'mango'], - ['memento', 'memento'], - ['motto', 'motto'], - ['tornado', 'tornado'], - ['person', 'person'], - ['goose', 'goose'], - ['mouse', 'mouse'], - ['calves', 'calf'], - ['olives', 'olive'], - ['loaves', 'loaf'], - ['oafs', 'oaf'], - ['wives', 'wife'], - ['roofs', 'roof'], - ['hooves', 'hoof'], - ['buses', 'bus'], - ['tosses', 'toss'], - ['wishes', 'wish'], - ['geniouses', 'genious'], - ['prognoses', 'prognosis'], - ['analyses', 'analysis'], - ['synopses', 'synopsis'], - ['parentheses', 'parenthesis'], - ['theses', 'thesis'], - ['bases', 'base'] - ].forEach(function(a) { - var r = nlp(a[0]).tag('Noun').nouns(); - var str = r.toSingular().out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); - }); - - T.test('pluralize:', function(t) { - [ - ['snake', 'snakes'], - ['ski', 'skis'], - // ["Barrymore", "Barrymores"], - ['witch', 'witches'], - ['box', 'boxes'], - ['gas', 'gases'], - ['kiss', 'kisses'], - ['index', 'indices'], - ['appendix', 'appendices'], - ['criterion', 'criteria'], - ['berry', 'berries'], - ['activity', 'activities'], - ['daisy', 'daisies'], - ['church', 'churches'], - ['fox', 'foxes'], - ['stomach', 'stomachs'], - ['epoch', 'epochs'], - ['knife', 'knives'], - ['half', 'halves'], - ['scarf', 'scarves'], - ['chief', 'chiefs'], - ['spoof', 'spoofs'], - ['cafe', 'cafes'], - ['gulf', 'gulfs'], - ['alternative', 'alternatives'], - ['solo', 'solos'], - ['zero', 'zeros'], - ['avocado', 'avocados'], - ['studio', 'studios'], - ['zoo', 'zoos'], - ['embryo', 'embryos'], - ['hero', 'heroes'], - ['banjo', 'banjos'], - ['cargo', 'cargos'], - ['flamingo', 'flamingos'], - ['fresco', 'frescos'], - ['ghetto', 'ghettos'], - ['halo', 'halos'], - ['mango', 'mangos'], - ['memento', 'mementos'], - ['motto', 'mottos'], - ['tornado', 'tornados'], - ['tuxedo', 'tuxedos'], - ['volcano', 'volcanos'], - ['bus', 'buses'], - ['crisis', 'crises'], - ['analysis', 'analyses'], - ['neurosis', 'neuroses'], - ['aircraft', 'aircraft'], - ['halibut', 'halibut'], - ['moose', 'moose'], - ['salmon', 'salmon'], - ['sheep', 'sheep'], - ['spacecraft', 'spacecraft'], - ['tuna', 'tuna'], - ['trout', 'trout'], - ['armadillo', 'armadillos'], - ['auto', 'autos'], - ['bravo', 'bravos'], - ['bronco', 'broncos'], - ['casino', 'casinos'], - ['combo', 'combos'], - ['gazebo', 'gazebos'], - //test that plural.pluralize()==plural.. - ['snakes', 'snakes'], - ['skis', 'skis'], - // ['mayor of chicago', 'mayors of chicago'], - // ["Barrymores", "Barrymores"], - ['witches', 'witches'], - ['boxes', 'boxes'], - ['gases', 'gases'], - ['spoofs', 'spoofs'], - ['solos', 'solos'], - ['avocados', 'avocados'], - ['studios', 'studios'], - ['zoos', 'zoos'] - ].forEach(function(a) { - var r = nlp(a[0]).tag('Noun').nouns(); - var str = r.toPlural().out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); - }); -}); diff --git a/test/unit/subset/noun/possessive.test.js b/test/unit/subset/noun/possessive.test.js deleted file mode 100644 index bc3ed148f..000000000 --- a/test/unit/subset/noun/possessive.test.js +++ /dev/null @@ -1,21 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('.toPossessive():', function(t) { - [ - ['duck', `duck's`], - ['eavesdropper', `eavesdropper's`], - ['John', `John's`], - ['hour', `hour's`], - ['F.B.I', `F.B.I's`], - ['John Smith', `John Smith's`], - ['skateboards', `skateboards'`], - ['Flanders', `Flanders'`], - // ['she', 'hers'], - ['peaches', `peaches'`] - ].forEach(function(a) { - var doc = nlp(a[0]).tag('Noun').nouns().toPossessive(); - t.equal(doc.out(), a[1], a[0]); - }); - t.end(); -}); diff --git a/test/unit/subset/noun/pronoun.test.js b/test/unit/subset/noun/pronoun.test.js deleted file mode 100644 index 6575f55cf..000000000 --- a/test/unit/subset/noun/pronoun.test.js +++ /dev/null @@ -1,27 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('pronoun:', function(t) { - [ - ['John', 'he'], - ['John Smith', 'he'], - ['Jane', 'she'], - // ['turtle', 'it'], - // ['turtles', 'they'], - // ['Toronto', 'it'], - // ['studying', 'it'], - // ['horses', 'they'], - // ['road bikes', 'they'], - // ['NHL goaltenders', 'they'], - ['Tony Danza', 'he'], - ['Tanya Danza', 'she'], - ['Mrs. Tanya Danza', 'she'] - // ['John G. Fishermore Institute', 'it'], - // ['John Fisher & sons', 'it'], - ].forEach(function(a) { - var str = nlp(a[0]).people().pronoun()[0]; - var msg = a[0] + ' -> ' + str; - t.equal(str, a[1], msg); - }); - t.end(); -}); diff --git a/test/unit/subset/person/person.test.js b/test/unit/subset/person/person.test.js deleted file mode 100644 index 2f744b85b..000000000 --- a/test/unit/subset/person/person.test.js +++ /dev/null @@ -1,159 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -//list of famous names taken from https://gate.ac.uk/gate/plugins/ANNIE/resources/gazetteer/ -var tests = { - 'john stewart': 'Male', - 'martha stewart': 'Female', - // 'Gaugin': 'Male', - // 'Gauguin': 'Male', - 'George Bush': 'Male', - 'Hillary Clinton': 'Female', - 'Hillary Rodham Clinton': 'Female', - // 'John the Baptist': 'Male', - 'Margaret Thatcher': 'Female', - Messiaen: 'Male', - Mozart: 'Male', - Nixon: 'Male', - 'Pope John Paul II': 'Male', - 'Richard Nixon': 'Male', - 'Ronald Reagan': 'Male', - 'Saddam Hussain': 'Male', - 'Saint - Saens': 'Male', - // 'Shostakovich': 'Male', - // 'Strauss': 'Male', - // 'Thatcher': 'Female', - // 'The Queen': 'Female', - // 'the Queen': 'Female', - 'Van Gogh': 'Male', - 'Virgin Mary': 'Female', - Vivaldi: 'Male', - 'van Gogh': 'Male', - 'Carl Marx': 'Male', - Lenin: 'Male', - Stalin: 'Male', - 'George W.Bush': 'Male', - 'Mitt Romney': 'Male', - 'Barack Obama': 'Male', - Obama: 'Male', - 'Lady Gaga': 'Female', - 'Kanye West': 'Male', - 'Abu Hamza': 'Male', - 'Abu Hamza Al - Masri': 'Male', - 'Osama bin Laden': 'Male', - 'Osama Bin Laden': 'Male', - Mubarek: 'Male', - 'Muhammad Ali': 'Male', - 'Jennifer Aniston': 'Female', - 'Tyra Banks': 'Female', - 'Mario Batali': 'Male', - 'David Beckham': 'Male', - 'Halle Berry': 'Female', - 'Tom Brady': 'Male', - 'Matthew Broderick': 'Male', - 'Nathan Lane': 'Male', - 'Mel Brooks': 'Male', - 'Dan Brown': 'Male', - 'Jerry Bruckheimer': 'Male', - 'Kobe Bryant': 'Male', - 'Gisele Bundchen': 'Female', - 'Jim Carrey': 'Male', - 'Dave Chappelle': 'Male', - 'Sean Combs': 'Male', - 'Katie Couric': 'Female', - 'Simon Cowell': 'Male', - 'Tom Cruise': 'Male', - 'Johnny Depp': 'Male', - 'Cameron Diaz': 'Female', - 'Leonardo DiCaprio': 'Male', - 'Celine Dion': 'Female', - 'Jodie Foster': 'Female', - 'John Grisham': 'Male', - 'Tom Hanks': 'Male', - 'Paris Hilton': 'Female', - 'Eric Idle': 'Male', - 'Mike Nichols': 'Male', - 'Peter Jackson': 'Male', - 'LeBron James': 'Male', - 'Derek Jeter': 'Male', - 'Scarlett Johansson': 'Female', - 'Elton John': 'Male', - 'Angelina Jolie': 'Female', - 'Michael Jordan': 'Male', - 'Nicole Kidman': 'Female', - 'Heidi Klum': 'Female', - 'Emeril Lagasse': 'Male', - 'Jay Leno': 'Male', - 'David Letterman': 'Male', - 'Adriana Lima': 'Female', - 'Rush Limbaugh': 'Male', - 'George Lopez': 'Male', - 'Jennifer Lopez': 'Female', - 'George Lucas': 'Male', - 'Paul McCartney': 'Male', - 'Dr. Phil McGraw': 'Male', - 'Phil Mickelson': 'Male', - 'Kate Moss': 'Female', - 'Neil Diamond': 'Male', - "Bill O'Reilly": 'Male', - "Shaquille O'Neal": 'Male', - 'Carson Palmer': 'Male', - 'James Patterson': 'Male', - 'Ty Pennington': 'Male', - 'Regis Philbin': 'Male', - 'Brad Pitt': 'Male', - 'Wolfgang Puck': 'Male', - 'Rachael Ray': 'Female', - 'Nicole Richie': 'Female', - 'Alex Rodriguez': 'Male', - 'Ray Romano': 'Male', - Ronaldinho: 'Male', - 'Valentino Rossi': 'Male', - 'J.K. Rowling': 'Female', - 'Adam Sandler': 'Male', - 'Diane Sawyer': 'Female', - 'Michael Schumacher': 'Male', - 'Ryan Seacrest': 'Male', - 'Jerry Seinfeld': 'Male', - 'Maria Sharapova': 'Female', - 'Jessica Simpson': 'Female', - 'Will Smith': 'Male', - 'Annika Sorenstam': 'Female', - 'Steven Spielberg': 'Male', - 'Bruce Springsteen': 'Male', - 'Howard Stern': 'Male', - 'Rod Stewart': 'Male', - 'Kiefer Sutherland': 'Male', - 'Donald Trump': 'Male', - 'Rick Warren': 'Male', - 'Denzel Washington': 'Male', - 'Sardinia F Jones': 'Female', - 'Andrew Lloyd Webber': 'Male', - 'Michelle Wie': 'Female', - 'Serena Williams': 'Female', - 'Venus Williams': 'Female', - 'Oprah Winfrey': 'Female', - 'Reese Witherspoon': 'Female', - 'Dick Wolf': 'Male', - 'Tiger Woods': 'Male', - 'Renee Zellweger': 'Female', - 'Whitney Houston': 'Female', - 'Adolf Hitler': 'Male', - 'Shania Twain': 'Female', - 'Hulk Hogan': 'Male', - 'Michelle Obama': 'Female', - 'Ashton Kutcher': 'Male', - 'Cardinal Wolsey': 'Male', - 'Slobodan Milosevic': 'Male', - 'Renee Zellweger ': 'Female', - 'Whitney Houston ': 'Female' -}; - -test('celebrity names:', function(t) { - Object.keys(tests).forEach(function(k) { - var str = nlp(k).people().out('text'); - var msg = "'" + k + "' is a person - - have: '" + str + "'"; - t.equal(str, k, msg); - }); - t.end(); -}); diff --git a/test/unit/subset/place/places.test.js b/test/unit/subset/place/places.test.js deleted file mode 100644 index 8626df268..000000000 --- a/test/unit/subset/place/places.test.js +++ /dev/null @@ -1,37 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('known-regions:', function(t) { - [ - ['i want to go to Ohio to see George Harrison', 'ohio'], - ['we are visiting Gloucestershire, before we leave', 'gloucestershire'], - ['manitoba is nice this time of year', 'manitoba'] - ].forEach(function(a) { - var str = nlp(a[0]).match('#Region').out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('unknown-places:', function(t) { - [ - ['live in the Rekcjd Province', 'rekcjd province'], - ['live in the Lekfjs District', 'lekfjs district'], - ['visiting Tojbs Kjeh Region', 'tojbs kjeh region'], - ['visiting the State of Lkjfhe', 'state of lkjfhe'], - ['see you in West Nunavut', 'west nunavut'], - ['see you in western Hunan', 'western hunan'], - ['see you in Northern Hunan province', 'northern hunan province'] - ].forEach(function(a) { - var str = nlp(a[0]).places(0).out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('mixed continents-places:', function(t) { - var doc = nlp('in north africa, eastern asia, guatemala, europe, north america, and japan'); - t.equal(doc.places().length, 6, '6-places'); - t.end(); -}); diff --git a/test/unit/subset/possessives/possessives.test.js b/test/unit/subset/possessives/possessives.test.js deleted file mode 100644 index 8c1152eae..000000000 --- a/test/unit/subset/possessives/possessives.test.js +++ /dev/null @@ -1,37 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('possessives tagger', function(t) { - var arr = [ - `Spencer's`, - `Spencer Kelly's`, - `Spencer C. Kelly's`, - `Union Corp's`, - `Los Angeles's`, - ]; - arr.forEach((a) => { - var doc = nlp(a); - var m = doc.possessives(); - t.equal(m.length, 1, 'one possessive -' + a); - t.equal(m.out(), a, 'possessive match -' + a); - }); - t.end(); -}); - -test('possessives strip', function(t) { - var arr = [ - [`Spencer's`, 'Spencer'], - [`Corey Hart's`, 'Corey Hart'], - [`Corey M. Hart's`, 'Corey M. Hart'], - [`Spencer C. Kelly's`, 'Spencer C. Kelly'], - [`Agility Inc's`, 'Agility Inc'], - [`University of Wisconsin's`, 'University of Wisconsin'], - [`Los Angeles's`, 'Los Angeles'], - ]; - arr.forEach((a) => { - var doc = nlp(a[0]); - doc.possessives().strip(); - t.equal(doc.out('text'), a[1], a[0]); - }); - t.end(); -}); diff --git a/test/unit/subset/quotations/quotation-tag.test.js b/test/unit/subset/quotations/quotation-tag.test.js deleted file mode 100644 index 4ce2c2ea9..000000000 --- a/test/unit/subset/quotations/quotation-tag.test.js +++ /dev/null @@ -1,221 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -function testAllQuotes(a, t) { - var str = nlp(a[0]).match('#Quotation+').out('normal'); - str_test(str, a[0], a[1], t); -} - -test('quotation test:', function(t) { - [ - [`he is "really good"`, `really good`], - [`he is "really good" i guess`, `really good`], - [`he is "good" i guess`, `good`], - [`he is "completely and utterly great" i guess`, `completely and utterly great`], - [`“quote”`, `quote`], - [`“quote is here”`, `quote is here`] - ].forEach(function(a) { - var str = nlp(a[0]).match('#Quotation+').out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('Quotations - U+0022 to U+0022', function (t) { - [ - ['he is \u0022really good\u0022', 'really good'], - ['he is \u0022really good\u0022 i guess', 'really good'], - ['he is not \u0022good\u0022 at all :/', 'good'], - ['\u0022quote\u0022', 'quote'], - ['\u0022a quote here\u0022', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+FF02 to U+FF02', function (t) { - [ - ['he is \uFF02really good\uFF02', 'really good'], - ['he is \uFF02really good\uFF02 i guess', 'really good'], - ['he is not \uFF02good\uFF02 at all :/', 'good'], - ['\uFF02quote\uFF02', 'quote'], - ['\uFF02a quote here\uFF02', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+0027 to U+0027', function (t) { - [ - ['he is \u0027really good\u0027', 'really good'], - ['he is \u0027really good\u0027 i guess', 'really good'], - ['he is not \u0027good\u0027 at all :/', 'good'], - ['\u0027quote\u0027', 'quote'], - ['\u0027a quote here\u0027', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); -// -test('Quotations - U+201C to U+201D', function (t) { - [ - ['he is \u201Creally good\u201D', 'really good'], - ['he is \u201Creally good\u201D i guess', 'really good'], - ['he is not \u201Cgood\u201D at all :/', 'good'], - ['\u201Cquote\u201D', 'quote'], - ['\u201Ca quote here\u201D', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+2018 to U+2019', function (t) { - [ - ['he is \u2018really good\u2019', 'really good'], - ['he is \u2018really good\u2019 i guess', 'really good'], - ['he is not \u2018good\u2019 at all :/', 'good'], - ['\u2018quote\u2019', 'quote'], - ['\u2018a quote here\u2019', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+201F to U+201D', function (t) { - [ - ['he is \u201Freally good\u201D', 'really good'], - ['he is \u201Freally good\u201D i guess', 'really good'], - ['he is not \u201Fgood\u201D at all :/', 'good'], - ['\u201Fquote\u201D', 'quote'], - ['\u201Fa quote here\u201D', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+201B to U+2019', function (t) { - [ - ['he is \u201Breally good\u2019', 'really good'], - ['he is \u201Breally good\u2019 i guess', 'really good'], - ['he is not \u201Bgood\u2019 at all :/', 'good'], - ['\u201Bquote\u2019', 'quote'], - ['\u201Ba quote here\u2019', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+201E to U+201D', function (t) { - [ - ['he is \u201Ereally good\u201D', 'really good'], - ['he is \u201Ereally good\u201D i guess', 'really good'], - ['he is not \u201Egood\u201D at all :/', 'good'], - ['\u201Equote\u201D', 'quote'], - ['\u201Ea quote here\u201D', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+2E42 to U+201D', function (t) { - [ - ['he is \u2E42really good\u201D', 'really good'], - ['he is \u2E42really good\u201D i guess', 'really good'], - ['he is not \u2E42good\u201D at all :/', 'good'], - ['\u2E42quote\u201D', 'quote'], - ['\u2E42a quote here\u201D', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+201A to U+2019', function (t) { - [ - ['he is \u201Areally good\u2019', 'really good'], - ['he is \u201Areally good\u2019 i guess', 'really good'], - ['he is not \u201Agood\u2019 at all :/', 'good'], - ['\u201Aquote\u2019', 'quote'], - ['\u201Aa quote here\u2019', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+00AB to U+00BB', function (t) { - [ - ['he is \u00ABreally good\u00BB', 'really good'], - ['he is \u00ABreally good\u00BB i guess', 'really good'], - ['he is not \u00ABgood\u00BB at all :/', 'good'], - ['\u00ABquote\u00BB', 'quote'], - ['\u00ABa quote here\u00BB', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+2039 to U+203A', function (t) { - [ - ['he is \u2039really good\u203A', 'really good'], - ['he is \u2039really good\u203A i guess', 'really good'], - ['he is not \u2039good\u203A at all :/', 'good'], - ['\u2039quote\u203A', 'quote'], - ['\u2039a quote here\u203A', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+2035 to U+2032', function (t) { - [ - ['he is \u2035really good\u2032', 'really good'], - ['he is \u2035really good\u2032 i guess', 'really good'], - ['he is not \u2035good\u2032 at all :/', 'good'], - ['\u2035quote\u2032', 'quote'], - ['\u2035a quote here\u2032', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+2036 to U+2033', function (t) { - [ - ['he is \u2036really good\u2033', 'really good'], - ['he is \u2036really good\u2033 i guess', 'really good'], - ['he is not \u2036good\u2033 at all :/', 'good'], - ['\u2036quote\u2033', 'quote'], - ['\u2036a quote here\u2033', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+2037 to U+2034', function (t) { - [ - ['he is \u2037really good\u2034', 'really good'], - ['he is \u2037really good\u2034 i guess', 'really good'], - ['he is not \u2037good\u2034 at all :/', 'good'], - ['\u2037quote\u2034', 'quote'], - ['\u2037a quote here\u2034', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+301D to U+301E', function (t) { - [ - ['he is \u301Dreally good\u301E', 'really good'], - ['he is \u301Dreally good\u301E i guess', 'really good'], - ['he is not \u301Dgood\u301E at all :/', 'good'], - ['\u301Dquote\u301E', 'quote'], - ['\u301Da quote here\u301E', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+0060 to U+00B4', function (t) { - [ - ['he is \u0060really good\u00B4', 'really good'], - ['he is \u0060really good\u00B4 i guess', 'really good'], - ['he is not \u0060good\u00B4 at all :/', 'good'], - ['\u0060quote\u00B4', 'quote'], - ['\u0060a quote here\u00B4', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); - -test('Quotations - U+301F to U+301E', function (t) { - [ - ['he is \u301Freally good\u301E', 'really good'], - ['he is \u301Freally good\u301E i guess', 'really good'], - ['he is not \u301Fgood\u301E at all :/', 'good'], - ['\u301Fquote\u301E', 'quote'], - ['\u301Fa quote here\u301E', 'a quote here'] - ].forEach(a => testAllQuotes(a, t)); - t.end(); -}); diff --git a/test/unit/subset/quotations/quotations.test.js b/test/unit/subset/quotations/quotations.test.js deleted file mode 100644 index 400d0cd95..000000000 --- a/test/unit/subset/quotations/quotations.test.js +++ /dev/null @@ -1,73 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('quotation test', function(t) { - var arr = [ - ['so I said "nah forget it"', 'nah forget it'], - ['so I said "nah, forget it" go home to bel-air!', 'nah forget it'], - ['so I said \'nah, forget it\' go home to bel-air!', 'nah forget it'], - ['so I said "nah" go home to bel-air!', 'nah'], - ['so \'as if\' i said', 'as if'], - ['the \'truthiness\' i said', 'truthiness'], - ['yeah, “fun” and stuff', 'fun'], - ['“Fun” and stuff', 'fun'], - //dangling start/end - ['\'twas good cookin', ''], - ['twas good cookin\'', ''], - ['twas \'good cookin\'', 'good cookin'], - ['\'twas \'good cookin\'', 'twas good cookin'], - [`and "Dig Your own grave and Save".`, 'dig your own grave and save'], - ]; - arr.forEach(function(a) { - var r = nlp(a[0]); - var str = r.quotations().out('normal'); - var msg = a[0] + ' - ' + str; - t.equal(str, a[1], msg); - }); - t.end(); -}); - -test('multiple quotation test', function(t) { - var arr = [ - [`My "String" "with many" adjacent "nested" 'quotes'`, - [ - 'string', - 'with many', - 'nested', - 'quotes' - ] - ], - [`My "String 'with manys' adjacent" "nested" 'quotes'`, - [ - 'string with manys adjacent', - 'nested', - 'quotes' - ] - ], - [`"May's" 'third day' 'will be a "really cold" day' "in a" 'really cold "month"'`, - [ - 'may\'s', - 'third day', - 'will be a really cold day', - 'in a', - 'really cold month', - ] - ], - ]; - arr.forEach(function(a) { - var r = nlp(a[0]); - var str = r.quotations().out('array'); - var msg = a[0] + ' - ' + str; - t.deepEqual(str, a[1], msg); - }); - t.end(); -}); - -test('false-positives', function(t) { - var txt = `Probably the renovation right away from the amount of work, which has been done to the property. - I have one two, three, four five six properties, which came on the market in the month. - I think that the number one quite comfortable looking at the two properties, which I'm working on now.`; - var questions = nlp(txt).sentences().isQuestion().out('array'); - t.equal(questions.length, 0, 'no questions here'); - t.end(); -}); diff --git a/test/unit/subset/random.test.js b/test/unit/subset/random.test.js deleted file mode 100644 index 201c25f12..000000000 --- a/test/unit/subset/random.test.js +++ /dev/null @@ -1,41 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('random', function(t) { - var r = nlp('one two three four five six'); - var arr = r.terms().random().out('array'); - t.equal(arr.length, 1, 'default is size 1'); - - arr = r.terms().random(2).out('array'); - t.equal(arr.length, 2, 'size 2'); - - arr = r.terms().random(3).out('array'); - t.equal(arr.length, 3, 'size 3'); - - arr = r.terms().random(4).out('array'); - t.equal(arr.length, 4, 'size 4'); - - arr = r.terms().random(5).out('array'); - t.equal(arr.length, 5, 'size 5'); - - arr = r.terms().random(6).out('array'); - t.equal(arr.length, 6, 'size 6'); - - arr = r.terms().random(7).out('array'); - t.equal(arr.length, 6, '7 is too big'); - - arr = r.terms().random(17).out('array'); - t.equal(arr.length, 6, '17 is too big'); - - t.end(); -}); - -test('random-null', function(t) { - var r = nlp('toronto'); - var arr = r.people().random(5).out('array'); - t.equal(arr.length, 0, 'random can be empty'); - - arr = r.places().random(5).out('array'); - t.equal(arr.length, 1, 'random can be full-match'); - t.end(); -}); diff --git a/test/unit/subset/reference.ignore.js b/test/unit/subset/reference.ignore.js deleted file mode 100644 index ffa42a74d..000000000 --- a/test/unit/subset/reference.ignore.js +++ /dev/null @@ -1,61 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('reference-test', function(t) { - var orig = nlp('is'); - var subset = orig.terms().replace('is', 'was'); - t.equal(orig.out(), 'was', 'terms-original'); - t.equal(subset.out(), 'was', 'terms-subset'); - - orig = nlp('is'); - subset = orig.verbs().replace('is', 'was'); - t.equal(orig.out(), 'was', 'verbs-original'); - t.equal(subset.out(), 'was', 'verbs-subset'); - - orig = nlp('is'); - subset = orig.sentences().replace('is', 'was'); - t.equal(orig.out(), 'was', 'sentences-original'); - t.equal(subset.out(), 'was', 'sentences-subset'); - - orig = nlp('old'); - subset = orig.adjectives().replace('old', 'new'); - t.equal(orig.out(), 'new', 'adjectives-original'); - t.equal(subset.out(), 'new', 'adjectives-subset'); - - orig = nlp('baby'); - subset = orig.nouns().replace('baby', 'adult'); - t.equal(orig.out(), 'adult', 'nouns-original'); - t.equal(subset.out(), 'adult', 'nouns-subset'); - - orig = nlp('9'); - subset = orig.values().replace('9', '5'); - t.equal(orig.out(), '5', 'values-original'); - t.equal(subset.out(), '5', 'values-subset'); - - orig = nlp('toronto'); - subset = orig.topics().replace('toronto', 'vancouver'); - t.equal(orig.out(), 'vancouver', 'topics-original'); - t.equal(subset.out(), 'vancouver', 'topics-subset'); - - t.end(); -}); - -test('.all()-multiple', function(t) { - var orig = nlp('i am from new jersey'); - var sub1 = orig.match('new jersey'); - var sub2 = sub1.match('jersey'); - var sub3 = sub2.replace('jersey', 'york'); - - //check doc.out() - t.equal(orig.out('normal'), 'i am from new york', 'original-text'); - t.equal(sub1.out('normal'), 'new york', 'sub1-text'); - t.equal(sub2.out('normal'), 'york', 'sub2-text'); - t.equal(sub3.out('normal'), 'york', 'sub3-text'); - - //call .all().out() - t.equal(orig.all().out('normal'), 'i am from new york', 'orig-all'); - t.equal(sub1.all().out('normal'), 'i am from new york', 'sub1-all'); - t.equal(sub2.all().out('normal'), 'i am from new york', 'sub2-all'); - t.equal(sub3.all().out('normal'), 'i am from new york', 'sub3-all'); - t.end(); -}); diff --git a/test/unit/subset/reservedwords.test.js b/test/unit/subset/reservedwords.test.js deleted file mode 100644 index 367984d7e..000000000 --- a/test/unit/subset/reservedwords.test.js +++ /dev/null @@ -1,127 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('reserved words:', function(t) { - var reserved = [ - 'abstract', - 'boolean', - 'break', - 'byte', - 'case', - 'catch', - 'char', - 'class', - 'const', - 'constructor', - 'continue', - 'debugger', - 'default', - 'delete', - 'do', - 'double', - 'else', - 'enum', - 'export', - 'extends', - 'false', - 'final', - 'finally', - 'float', - 'for', - 'function', - 'goto', - 'if', - 'implements', - 'import', - 'in', - 'instanceof', - 'int', - 'interface', - 'let', - 'long', - 'native', - 'new', - 'null', - 'package', - 'private', - 'protected', - 'prototype', - 'public', - 'return', - 'short', - 'static', - 'super', - 'switch', - 'synchronized', - 'this', - 'throw', - 'throws', - 'transient', - 'true', - 'try', - 'typeof', - 'var', - 'void', - 'volatile', - 'while', - 'with', - 'yeild', - '__prototype__', - '&&', - '||', - '|', - "'", - '&', - 'Math.PI', - 12e34, - '#§$%', - 'π', - 'привет', - // 'hasOwnProperty', - 'café', - '$$$', - 1e2, - '{}', - '[]', - 'constructor', - 'prototype', - ')&@)^', - ' -@%@', - '-constructor', - '#!^@#$', - '..(' - ]; - var str = reserved.join(' '); - var r = nlp(str); - t.equal(r.out('text'), str, 'reserved-words-are-printed'); - t.equal(r.terms().length, reserved.length, 'reserved-length'); - t.ok(r.verbs().data(), 'runs verb subset'); - t.ok(r.values().data(), 'runs value subset'); - t.ok(r.nouns().data(), 'runs noun subset'); - t.ok(r.ngrams().data(), 'runs ngrams subset'); - t.ok(r.people().data(), 'runs people subset'); - t.ok(r.places().data(), 'runs places subset'); - t.ok(r.adjectives().data(), 'runs adjectives subset'); - t.ok(r.sentences().data(), 'runs sentences subset'); - t.ok(r.dates().data(), 'runs dates subset'); - t.ok(r.contractions().data(), 'runs contractions subset'); - t.ok(r.terms().data(), 'runs terms subset'); - t.end(); -}); - -test('co-erce reserved words', function(t) { - var r = nlp('constructor prototype'); - r.tag('Verb'); - t.ok(r.verbs().data(), 'runs verb subset'); - r.tag('Adjective'); - t.ok(r.adjectives().data(), 'runs adjective subset'); - r.tag('Value'); - t.ok(r.values().data(), 'runs values subset'); - r.tag('Person'); - t.ok(r.people().data(), 'runs values subset'); - r.tag('Noun'); - t.ok(r.nouns().data(), 'runs values subset'); - r.tag('Place'); - t.ok(r.places().data(), 'runs place subset'); - t.end(); -}); diff --git a/test/unit/subset/sentence/inflect.ignore.js b/test/unit/subset/sentence/inflect.ignore.js deleted file mode 100644 index 1e2ffbdae..000000000 --- a/test/unit/subset/sentence/inflect.ignore.js +++ /dev/null @@ -1,44 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('toPlural():', function(t) { - [ - ['cranberry', 'cranberries'], - ['a cranberry', 'the cranberries'], - ['a red cranberry', 'the red cranberries'], - ['mayor of chicago', 'mayors of chicago'], - ['chicago mayor', 'chicago mayors'] - ].forEach(function(a) { - var str = nlp(a[0]).sentences().toPlural().out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('toSingular:', function(t) { - var str = 'i\'d buy those nachos'; - var m = nlp(str).sentences().toSingular(); - t.equal(m.out('normal'), 'i\'d buy that nacho', str); - - str = 'i\'d buy these nachos'; - m = nlp(str).sentences().toSingular(); - t.equal(m.out('normal'), 'i\'d buy this nacho', str); - - str = 'i\'d buy nachos'; - m = nlp(str).sentences().toSingular(); - t.equal(m.out('normal'), 'i\'d buy a nacho', str); - - str = 'i\'d buy the nachos'; - m = nlp(str).sentences().toSingular(); - t.equal(m.out('normal'), 'i\'d buy a nacho', str); - - str = 'i\'d buy the eggs'; - m = nlp(str).sentences().toSingular(); - t.equal(m.out('normal'), 'i\'d buy an egg', str); - - str = 'men go'; - m = nlp(str).sentences().toPast().nouns().toSingular(); - t.equal(m.out('normal'), 'a man went', str); - t.end(); -}); diff --git a/test/unit/subset/sentence/insert.test.js b/test/unit/subset/sentence/insert.test.js deleted file mode 100644 index 67a3f12c5..000000000 --- a/test/unit/subset/sentence/insert.test.js +++ /dev/null @@ -1,38 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('prepend:', function(t) { - var r = nlp('john is nice. he lives in SOHO.'); - r.sentences().prepend('so'); - t.equal(r.out('text'), 'so john is nice. so he lives in SOHO.', 'prepend-without-capital'); - - r = nlp('It is nice. He lives in SOHO.'); - r.sentences().prepend('so'); - t.equal(r.out('text'), 'So it is nice. So he lives in SOHO.', 'prepend-with-capital'); - - r = nlp('John is nice. FBI are in SOHO.'); - r.sentences().prepend('so'); - t.equal(r.out('text'), 'So John is nice. So FBI are in SOHO.', 'prepend-with-persistent-capital'); - - r = nlp('It is nice. He lives in SOHO.'); - r.sentences().prepend('believe me'); - t.equal(r.out('text'), 'Believe me it is nice. Believe me he lives in SOHO.', 'multiple-word-prepend'); - - t.end(); -}); - -test('append:', function(t) { - var r = nlp('john is nice. he lives in SOHO'); - r.sentences().append('not'); - t.equal(r.out('text'), 'john is nice not. he lives in SOHO not', 'append-with-without-period'); - - r = nlp('It is nice! He lives in SOHO? I don\'t know...'); - r.sentences().append('dawg'); - t.equal(r.out('text'), 'It is nice dawg! He lives in SOHO dawg? I don\'t know dawg...', 'append-with-exclamations'); - - r = nlp('It is nice. He lives in SOHO.'); - r.sentences().append('believe me'); - t.equal(r.out('text'), 'It is nice believe me. He lives in SOHO believe me.', 'multiple-word-append'); - - t.end(); -}); diff --git a/test/unit/subset/sentence/misc.test.js b/test/unit/subset/sentence/misc.test.js deleted file mode 100644 index 0fb351185..000000000 --- a/test/unit/subset/sentence/misc.test.js +++ /dev/null @@ -1,13 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('setPunctuation:', function(t) { - var r = nlp('john is nice. he lives in SOHO.'); - r.sentences(1).toExclamation(); - t.equal(r.out(), 'john is nice. he lives in SOHO!', 'toexclamation-change'); - - r = nlp('john is nice. he lives in SOHO'); - r.sentences(1).toExclamation(); - t.equal(r.out(), 'john is nice. he lives in SOHO!', 'toexclamation-insert'); - t.end(); -}); diff --git a/test/unit/subset/sentence/question.test.js b/test/unit/subset/sentence/question.test.js deleted file mode 100644 index d930e5f66..000000000 --- a/test/unit/subset/sentence/question.test.js +++ /dev/null @@ -1,64 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('question-test :', function (t) { - [ - 'which party was it again?', - 'so then which day was it?', - 'he\'s fun?', - 'but who did you really go with??', - 'go where?!', - 'go with who!?', - 'then you said ... ?', - - //no question-mark.. - 'which party was it', - 'which day was it', - // 'but who did you go with', - 'what time did you show up', - `why'd you come so early`, - `when'll you show up`, - `where'd you go afterwards`, - `is it fun`, - `was it fun`, - `did you think it was fun`, - `so, is it fun`, - `so, where'd you go`, - `if you said so, why are you upset`, - `does wayne gretsky skate`, - `would you go to france`, - `can we go to france`, - `can you explain`, - `won't they go to france`, - `wouldn't they go to france`, - `can Jamaican nationals go to france`, - `Anyway the wind blows, what doesn't really matter to me`, - `is wayne gretskzy alive`, - `Do I need no sympathy`, - // `I'm what a poor boy` - ].forEach(function (str) { - var doc = nlp(str); - t.equal(doc.questions().length, 1, str); - t.equal(doc.statements().length, 0, ' -- 0-statements'); - }); - t.end(); -}); - -test('statements-test :', function (t) { - [ - 'the thing is, it isn\'t cool', - 'does the orchestra respond, no.', - 'where there is smoke, there\'s fire', - 'does the orchestra ever suck!', - 'when i go fishing i eat plankton', - 'let me run get a price take about 5-10 minutes to process and then I\'ll send you what I got.', - 'how he got out of his cage, i don\'t know', - 'who else but the rolling stones...', - 'what i\'d like to say is, thanks for the fish', - ].forEach(function (str) { - var doc = nlp(str); - t.equal(doc.statements().length, 1, str); - t.equal(doc.questions().length, 0, ' -- 0-questions'); - }); - t.end(); -}); diff --git a/test/unit/subset/sentence/tense.test.js b/test/unit/subset/sentence/tense.test.js deleted file mode 100644 index 86f726856..000000000 --- a/test/unit/subset/sentence/tense.test.js +++ /dev/null @@ -1,207 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('sentence-change-tense:', function(t) { - [ - ['john walks quickly', 'john walked quickly', 'john will walk quickly'], - ['he is quick', 'he was quick', 'he will be quick'], - ['the stool falls over', 'the stool fell over', 'the stool will fall over'], - ['i usually take the stairs', 'i usually took the stairs', 'i usually will take the stairs'], - ['i usually use the stairs', 'i usually used the stairs', 'i usually will use the stairs'], - ['he finishes first', 'he finished first', 'he will finish first'], - ['our house looks great', 'our house looked great', 'our house will look great'], - //infinitives - // ['he does what he can to stop', 'he did what he could to stop', 'he will do what he can to stop'], - ['goes to sleep', 'went to sleep', 'will go to sleep'], - - //passive - // ['cardboard is made of tree fibre', 'cardboard was made of tree fibre', 'cardboard will be made of tree fibre'], - - //grammatical-number - // ['we do what we can to stop', 'we did what we could to stop', 'we will do what we can to stop'], - - //multi-sentence - [ - 'this is one sentence. This makes two now.', - 'this was one sentence. This made two now.', - 'this will be one sentence. This will make two now.' - ] - - //support negative - // ['this isn\'t one sentence. This doesn\'t make two now.', 'this was not one sentence. This didn\'t make two now.', 'this won\'t be one sentence. This won\'t make two now.'] - ].forEach(function(a) { - var r = nlp(a[0]).sentences(); - - r.toPastTense(); - var str = r.out('text'); - t.equal(str, a[1], 'pastTense-' + str); - - r.toFutureTense(); - str = r.out('text'); - t.equal(str, a[2], 'futureTense-' + str); - - r.toPresentTense(); - str = r.out('text'); - t.equal(str, a[0], 'presentTense-' + str); - }); - t.end(); -}); - -test('copula-form', function(t) { - var m = nlp('john is nice').sentences(); - - m.toPastTense(); - t.equal(m.out(), 'john was nice', 'toPast-1'); - - m.toPresentTense(); - t.equal(m.out(), 'john is nice', 'toPres-1'); - - m.toFutureTense(); - t.equal(m.out(), 'john will be nice', 'toFuture-1'); - - m.toNegative(); - t.equal(m.out(), 'john will not be nice', 'toNeg-future'); - - //negative forms - m.toPastTense(); - t.equal(m.out(), 'john was not nice', 'toPast-neg'); - - m.toPresentTense(); - t.equal(m.out(), 'john is not nice', 'toPres-neg'); - - m.toFutureTense(); - t.equal(m.out(), 'john will not be nice', 'toFuture-neg'); - - t.end(); -}); -// // -test('conjugate-form', function(t) { - var m = nlp('john walks quickly').sentences(); - - m.toPastTense(); - t.equal(m.out(), 'john walked quickly', 'toPast-1'); - - m.toPresentTense(); - t.equal(m.out(), 'john walks quickly', 'toPres-1'); - - m.toFutureTense(); - t.equal(m.out(), 'john will walk quickly', 'toFuture-1'); - - m.toNegative(); - t.equal(m.out(), 'john will not walk quickly', 'toNeg'); - - //negative forms - m.toPastTense(); - t.equal(m.out(), 'john did not walk quickly', 'toPast-neg'); - - m.toPresentTense(); - t.equal(m.out(), 'john does not walk quickly', 'toPres-neg'); - - m.toFutureTense(); - t.equal(m.out(), 'john will not walk quickly', 'toFuture-neg'); - - t.end(); -}); - -test('particle-form', function(t) { - var m = nlp('the stool falls over').sentences(); - - m.toPastTense(); - t.equal(m.out(), 'the stool fell over', 'toPast-1'); - - m.toPresentTense(); - t.equal(m.out(), 'the stool falls over', 'toPres-1'); - - m.toFutureTense(); - t.equal(m.out(), 'the stool will fall over', 'toFuture-1'); - - m.toNegative(); - t.equal(m.out(), 'the stool will not fall over', 'toNeg'); - - //negative forms - m.toPastTense(); - t.equal(m.out(), 'the stool did not fall over', 'toPast-neg'); - - m.toPresentTense(); - t.equal(m.out(), 'the stool does not fall over', 'toPres-neg'); - - m.toFutureTense(); - t.equal(m.out(), 'the stool will not fall over', 'toFuture-neg'); - - t.end(); -}); - -test('contraction-cases', function(t) { - var arr = [[`I'm going to the shops`, `I went to the shops`], [`I'll go to the shops`, `I went to the shops`]]; - arr.forEach(a => { - var str = nlp(a[0]).sentences().toPastTense().out(); - t.equal(str, a[1], 'past-tense ' + a.join(' - ')); - }); - arr = [[`We're looking`, `We looked`], [`We'll look`, `We looked`], [`We are looking`, `We looked`]]; - arr.forEach(a => { - var str = nlp(a[0]).sentences().toPastTense().out(); - t.equal(str, a[1], 'past-tense ' + a.join(' - ')); - }); - arr = [[`I'm going to the shops`, `I will go to the shops`], [`I'll go to the shops`, `I will go to the shops`]]; - arr.forEach(a => { - var str = nlp(a[0]).sentences().toFutureTense().out(); - t.equal(str, a[1], 'future-tense ' + a.join(' - ')); - }); - arr = [[`I'm going to the shops`, `I go to the shops`], [`I'll go to the shops`, `I go to the shops`]]; - arr.forEach(a => { - var str = nlp(a[0]).sentences().toPresentTense().out(); - t.equal(str, a[1], 'present-tense ' + a.join(' - ')); - }); - arr = [[`I'm looking for a bug`, `I look for a bug`], [`I'll look for a bug`, `I look for a bug`]]; - arr.forEach(a => { - var str = nlp(a[0]).sentences().toPresentTense().out(); - t.equal(str, a[1], 'present-tense ' + a.join(' - ')); - }); - var str = nlp('I’m lookin’ for Amanda Hugginkiss').sentences().toPastTense().out(); - t.equal(str, 'i looked for Amanda Hugginkiss', 'present-tense slang'); - t.end(); -}); - - -test('pronoun-specific', function(t) { - //from present - var m = nlp('i am cool').sentences().toPresentTense(); - t.equal(m.out(), 'i am cool', 'toPresent-I'); - m = nlp('i am cool').sentences().toPastTense(); - t.equal(m.out(), 'i was cool', 'toPastTense-I'); - m = nlp('i am cool').sentences().toFutureTense(); - t.equal(m.out(), 'i will be cool', 'toFutureTense-I'); - - //from future - m = nlp('i will be cool').sentences().toFutureTense(); - t.equal(m.out(), 'i will be cool', 'toFutureTense-I-2'); - m = nlp('i will be cool').sentences().toPastTense(); - t.equal(m.out(), 'i was cool', 'toPastTense-I-2'); - m = nlp('i will be cool').sentences().toPresentTense(); - t.equal(m.out(), 'i am cool', 'toPresentTense-I-2'); - - //from past - m = nlp('i was cool').sentences().toPresentTense(); - t.equal(m.out(), 'i am cool', 'toPresentTense-I-3'); - m = nlp('i was cool').sentences().toPastTense(); - t.equal(m.out(), 'i was cool', 'toPastTense-I-3'); - m = nlp('i was cool').sentences().toFutureTense(); - t.equal(m.out(), 'i will be cool', 'toFutureTense-I-3'); - - //with negative - m = nlp('i was not cool').sentences().toPresentTense(); - t.equal(m.out(), 'i am not cool', 'neg-1'); - m = nlp('i wasn\'t cool').sentences().toPastTense(); - t.equal(m.out(), 'i was not cool', 'neg-2'); - m = nlp('i was not cool').sentences().toFutureTense(); - t.equal(m.out(), 'i will not be cool', 'neg-3'); - - //with adverbs - m = nlp('i was really cool').sentences().toPresentTense(); - t.equal(m.out(), 'i am really cool', 'toPresentTense-I-3'); - m = nlp('i was really cool').sentences().toPastTense(); - t.equal(m.out(), 'i was really cool', 'toPastTense-I-3'); - m = nlp('i was really cool').sentences().toFutureTense(); - t.equal(m.out(), 'i will be really cool', 'toFutureTense-I-3'); - t.end(); -}); diff --git a/test/unit/subset/sentence/toContinuous.test.js b/test/unit/subset/sentence/toContinuous.test.js deleted file mode 100644 index 5dd97ece9..000000000 --- a/test/unit/subset/sentence/toContinuous.test.js +++ /dev/null @@ -1,21 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('sentence-to-gerund:', function(t) { - [ - ['john walked', 'john is walking'], - // ['i should win', 'i should be winning'],//support (some) modals? - ['spencer will convert', 'spencer is converting'], - ['everyone will see', 'everyone is seeing'], - ['he is cool', 'he is being cool'], - ['he was good', 'he is being good'], - ['i am fun', 'i am being fun'], - ['i am not fun', 'i am not being fun'], - ['we will sing', 'we are singing'], - ['we really will sing', 'we are really singing'], - ].forEach(function(a) { - var str = nlp(a[0]).sentences().toContinuous().out('normal'); - t.equal(str, a[1], str + ' -> ' + a[1]); - }); - t.end(); -}); diff --git a/test/unit/subset/sentence/toNegative.test.js b/test/unit/subset/sentence/toNegative.test.js deleted file mode 100644 index 7d8237a6d..000000000 --- a/test/unit/subset/sentence/toNegative.test.js +++ /dev/null @@ -1,94 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('==negation==', function(T) { - T.test('negate:', function(t) { - [ - //copula-sentences - [`john is good`, `john is not good`], - [`they are good`, `they are not good`], - [`they will be good`, `they will not be good`], - [`they will really be good`, `they will not really be good`], - //different verb tenses - [`he walks`, `he does not walk`], - [`he will walk`, `he will not walk`], - [`he walked`, `he did not walk`], - [`he has walked`, `he has not walked`], - [`he will have walked`, `he will not have walked`], - [`he is walking`, `he is not walking`], - //add adverbs - [`he really walks`, `he really does not walk`], - [`he will really walk`, `he will not really walk`], - [`he really walked`, `he really did not walk`], - [`he has really walked`, `he has not really walked`], - [`he will have really walked`, `he will not have really walked`], - [`he is really walking`, `he is not really walking`], - //plural noun - [`they walk`, `they do not walk`], - //pronoun + infinitive - [`i like running`, `i do not like running`], - [`they swim`, `they do not swim`], - [`we enjoy playing`, `we do not enjoy playing`], - [`we swim`, `we do not swim`], - [`we do swim`, `we do not swim`], - [`i do care`, `i do not care`], - [`they do care`, `they do not care`], - - //does not, is not, are not, etc. - [`apples are bad`, `apples are not bad`], - [`he does like it`, `he does not like it`], - [`have died yet`, `have not died yet`], - //logical negations - ['john always walks', 'john never walks'], - ['john always walks quickly', 'john never walks quickly'], - ['everybody walks quickly', 'nobody walks quickly'], - - [`has played`, `has not played`], - [`he has played`, `he has not played`], - [`spencer is playing`, `spencer is not playing`], - [`he will play`, `he will not play`], - [`he will be playing`, `he will not be playing`], - [`he had played`, `he had not played`], - [`he plays`, `he does not play`], - [`he played`, `he did not play`], - [`he walked`, `he did not walk`] - // [`he quietly walked`, `he did not quietly walk`], - // [`he quietly walks`, `he does not quietly walk`], - // [`we quietly walked`, `we do not quietly walk`], - // [`we quietly walks`, `we do not quietly walk`] - ].forEach(function(a) { - var str = nlp(a[0]).sentences().toNegative().out('text'); - str_test(str, a[0], a[1], t); - }); - t.end(); - }); - - T.test('sentence un-negate:', function(t) { - [ - //copula-sentences - [`john is not good`, `john is good`], - [`they are not good`, `they are good`], - [`they will not be good`, `they will be good`], - //different verb tenses - [`he does not walk`, `he does walk`], - [`he did not walk`, `he did walk`], - [`he is not walking`, `he is walking`], - [`he has not been walking`, `he has been walking`], - [`he did not walk`, `he did walk`], - [`he does not walk`, `he does walk`], - - [`he has not walked`, `he has walked`], - [`he will not have walked`, `he will have walked`], - [`he is not walking`, `he is walking`], - // //logical negations - ['john never walks', 'john always walks'], - ['john never walks quickly', 'john always walks quickly'] - // ['everybody walks quickly', 'nobody walks quickly'], - ].forEach(function(a) { - var str = nlp(a[0]).sentences().toPositive().out('text'); - str_test(str, a[0], a[1], t); - }); - t.end(); - }); -}); diff --git a/test/unit/subset/sentence/tokenize.test.js b/test/unit/subset/sentence/tokenize.test.js deleted file mode 100644 index f6c105e12..000000000 --- a/test/unit/subset/sentence/tokenize.test.js +++ /dev/null @@ -1,76 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('sentence tokenize:', function(t) { - [ - ['Tony is nice. He lives in Japan.', 2], - ['I like that Color', 1], - [ - 'Hi there Dr. Joe, the price is 4.59 for N.A.S.A. Ph.Ds. I hope that\'s fine, etc. and you can attend Feb. 8th. Bye', - 3 - ], - ['Soviet bonds to be sold in the U.S. market. Everyone wins.', 2], - ['Hi there! Everyone wins!', 2], - ['Hi there!!! Everyone wins.', 2], - ['Hi there\u203C Everyone wins\u203C', 2], - ['Hi there\u203C Everyone wins.', 2], - ['he bought Yahoo! the company.', 1], - ['he is ill', 1], - ['he is ill.', 1], - ['he is ill\u2047', 1], - ['she is fine. he is ill.', 2], - ['she is fine. he is ill', 2], - ['lkajsdflkjeicclksdfjefifh', 1], - ['i think it is good ie. fantastic.', 1], - ['i think it is good i.e. fantastic.', 1], - ['You did what\u2048', 1], - ['You did what\u2048 How could you\u2049', 2], - ['i think it is good or else.', 1], - ['i think it is good… or else.', 1], - ['i think it is good… ', 1], - ['i think it is good ... or else.', 1], - ['i think it is good ... ', 1], - ['What\'s my age again? What\'s my age again?', 2], - ['the problem, eg. the javascript', 1], - ['Dr. Tony is nice. He lives on Elm St. in Vancouver BC. Canada', 2], - ['I made $5.60 today in 1 hour of work. The E.M.T.\'s were on time, but only barely.', 2], - - ['In some notations, A or B is shown as A|B. In others A or B is shown as A||B.', 2], - ['hello. 1234. ëėö.', 3], - - // Linux EOL - ['Hi there.\nEveryone wins.', 2], - ['Hi there!\n\nEveryone wins.', 2], - ['Hi there\nEveryone wins', 2], - ['Hi there.\n Everyone wins', 2], - ['Hi there!!\nEveryone wins\n\n', 2], - - // Mac EOL - ['Hi there.\rEveryone wins.', 2], - ['Hi there!\r\rEveryone wins.', 2], - ['Hi there\rEveryone wins', 2], - ['Hi there.\r Everyone wins', 2], - ['Hi there!!\rEveryone wins\r\r', 2], - - // Windows EOL - ['Hi there.\r\nEveryone wins.', 2], - ['Hi there!\r\n\r\nEveryone wins.', 2], - ['Hi there\r\nEveryone wins', 2], - ['Hi there.\r\n Everyone wins', 2], - ['Hi there!!\r\nEveryone wins\r\n\r\n', 2] - ].forEach(function(a) { - var num = nlp(a[0]).list.length; - var msg = '"' + a[0] + '" -> ' + num; - t.equal(num, a[1], msg); - }); - t.end(); -}); - -test('fancy tokenize:', function(t) { - var doc = nlp('boris becker ?? he is nice.'); - t.equal(doc.sentences().length, 2, 'sentence-split'); - - // doc = nlp('Is Trump the president of U.S. ? i guess so') - // t.equal(doc.sentences().length, 2, 'sentence-split-2') - t.end(); -}); diff --git a/test/unit/subset/sentence/whitespace.test.js b/test/unit/subset/sentence/whitespace.test.js deleted file mode 100644 index 495f33590..000000000 --- a/test/unit/subset/sentence/whitespace.test.js +++ /dev/null @@ -1,75 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('=Whitespace=', function(T) { - T.test('preserve whitespace:', function(t) { - [ - 'John Smith', - 'John Smith', - 'John Smith ', - 'John Smith ', - ' John', - ' John Smith ', - //no joins - 'he is nice', - 'he is nice', - 'he is nice', - 'he is nice ', - ' he is nice ', - //contractions - `he isn't nice`, - `he isn't nice`, - `he isn't nice`, - `he isn't nice `, - ` he isn't nice `, - //multiples - 'it is ipso facto', - 'it is ipso facto ', - 'it is ipso facto ', - 'it is ipso facto ', - '2nd of march, 2015' - ].forEach(function(a) { - var str = nlp(a).out('text'); - str_test(str, a, a, t); - }); - t.end(); - }); - - T.test('inter-sentence whitespace:', function(t) { - [ - 'John Smith is nice.', - ' John Smith is nice.', - ' John Smith is nice. ', - 'John Smith is nice. He lives in Spain.', - 'John Smith is nice. He lives in Spain.', - 'John Smith is nice. He lives in Spain. ', - ' John Smith is nice. He lives in Spain. ', - 'Dr. Smith is nice. He lives in Spain. ', - ' Dr. Smith is nice. He lives in Spain. ', - 'Dr. Smith is nice? He lives in Spain. ', - ' Dr. Smith is nice? He lives in Spain? ', - ' Dr. Smith is nice? He lives in UCLA? He does? ', - ' Dr. Smith is nice? He lives in Spain? He does?? ' - ].forEach(function(a) { - var str = nlp(a).out('text'); - str_test(str, a, a, t); - }); - t.end(); - }); - - T.test('contraction whitespace:', function(t) { - [ - ['John\'s nice.', 'John is nice.'], - ['John Smith\'s nice.', 'John Smith is nice.'], - ['John isn\'t nice.', 'John is not nice.'], - ['John didn\'t go.', 'John did not go.'], - ['I wanna go.', 'I want to go.'], - ['they\'ve gone.', 'they have gone.'] - ].forEach(function(a) { - var str = nlp(a[0]).contractions().expand().all().out('text'); - str_test(str, a[0], a[1], t); - }); - t.end(); - }); -}); diff --git a/test/unit/subset/subset.test.js b/test/unit/subset/subset.test.js deleted file mode 100644 index 98277c866..000000000 --- a/test/unit/subset/subset.test.js +++ /dev/null @@ -1,62 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -var mustBe = function(arr) { - return arr.map(function(t) { - return t.normal; - }); -}; - -test('clauses', function(t) { - var m = nlp('he is nice - which is cool... but whatever'); - var have = mustBe(m.clauses().data()); - var want = ['he is nice', 'which is cool', 'but whatever']; - var msg = have.join(' -- '); - t.deepEqual(have, want, msg); - - m = nlp('he is nice. If so, then good'); - have = mustBe(m.clauses().data()); - want = ['he is nice', 'if so', 'then good']; - msg = have.join(' -- '); - t.deepEqual(have, want, msg); - - t.end(); -}); - -test('adjectives', function(t) { - var m = nlp('he is nice, cool and very fun'); - var have = mustBe(m.adjectives().data()); - var want = ['nice', 'cool', 'fun']; - var msg = have.join(' -- '); - t.deepEqual(have, want, msg); - - t.end(); -}); - -test('quotations', function(t) { - var have = nlp('My "String" "with many" adjacent "nested" \'quotes\'').quotations().out('array'); - var want = ['string', 'with many', 'nested', 'quotes']; - t.deepEqual(have, want, 'consecutive quoations'); - t.end(); -}); - -test('parentheses', function(t) { - var have = nlp('Use a pointed stick (a pencil) or congealed petroleum (an eraser) or a similar tool').parentheses().out('array'); - var want = ['a pencil', 'an eraser']; - t.deepEqual(have, want, 'two parentheses'); - - have = nlp('born in Canada (Toronto), Drake (Aubrey Graham) became a hit (a success)').parentheses().out('array'); - want = ['toronto', 'aubrey graham', 'a success']; - t.deepEqual(have, want, 'different-sized parentheses'); - t.end(); -}); - -test('contractions-subset', function(t) { - var m = nlp('he\'s nice. She could\'ve seen.'); - var have = mustBe(m.contractions().data()); - var want = ['he\'s', 'could\'ve']; - var msg = have.join(' -- '); - t.deepEqual(have, want, msg); - - t.end(); -}); diff --git a/test/unit/subset/terms/bestTag.js b/test/unit/subset/terms/bestTag.js deleted file mode 100644 index 29c7e76ec..000000000 --- a/test/unit/subset/terms/bestTag.js +++ /dev/null @@ -1,33 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('bestTag', function(t) { - var str = 'john smith was really working'; - var m = nlp(str); - var have = m.terms().data().map(function(o) { - return o.bestTag; - }); - var want = ['MaleName', 'LastName', 'Copula', 'Adverb', 'Gerund']; - var msg = str + ' - [' + have.join(', ') + ']'; - t.deepEqual(have, want, msg); - - str = 'he sang on June 5th 1991'; - m = nlp(str); - have = m.terms().data().map(function(o) { - return o.bestTag; - }); - want = ['Pronoun', 'PastTense', 'Preposition', 'Month', 'Ordinal', 'Year']; - msg = str + ' - [' + have.join(', ') + ']'; - t.deepEqual(have, want, msg); - - str = 'fastest shooter in Canada'; - m = nlp(str); - have = m.terms().data().map(function(o) { - return o.bestTag; - }); - want = ['Superlative', 'Noun', 'Preposition', 'Country']; - msg = str + ' - [' + have.join(', ') + ']'; - t.deepEqual(have, want, msg); - - t.end(); -}); diff --git a/test/unit/subset/topics/things.test.js b/test/unit/subset/topics/things.test.js deleted file mode 100644 index 98b00ce11..000000000 --- a/test/unit/subset/topics/things.test.js +++ /dev/null @@ -1,9 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('topics concat:', function(t) { - var things = nlp('spencer and danny are in Paris France, and germany for Google Inc and IBM').topics().out('array'); - var want = ['spencer', 'danny', 'paris france', 'germany', 'google inc', 'ibm']; - t.equal(things.join(', '), want.join(', '), 'found right things'); - t.end(); -}); diff --git a/test/unit/subset/topics/topics.test.js b/test/unit/subset/topics/topics.test.js deleted file mode 100644 index 2a65aad0d..000000000 --- a/test/unit/subset/topics/topics.test.js +++ /dev/null @@ -1,37 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('topics:', function(t) { - [ - ['James and Tony Hawk both live in Toronto. Tony Hawk is cool.', 'tony hawk'], - ['I live Toronto. I think Toronto is cool.', 'toronto'], - ['The EACD united in 1972. EACD must follow regulations.', 'eacd'], - // ['The Elkjsdflkjsdf sells hamburgers. I think the Elkjsdflkjsdf eats turky.', 'elkjsdflkjsdf'], - ['Toronto\'s citizens love toronto!', 'toronto'], - ].forEach(function(a) { - var arr = nlp(a[0]) - .topics() - .out('freq'); - str_test(arr[0].normal, a[0], a[1], t); - }); - t.end(); -}); - -test('topics-false-positives:', function(t) { - var arr = [ - 'somone ate her lunch', - 'everybody is dancing all night', - 'a man and a woman ate her son\'s breakfast', - 'my brother walks to school', - `She's coming by`, - `if she doesn't like something about us she can keep us off`, - ` She's it! She could be a soap opera.`, - `she's a little dare-devil!`, - ]; - arr.forEach(function(str, i) { - var doc = nlp(str).topics(); - t.equal(doc.length, 0, 'topics #' + i + ' -> ' + doc.out()); - }); - t.end(); -}); diff --git a/test/unit/subset/value/bigNumber.test.js b/test/unit/subset/value/bigNumber.test.js deleted file mode 100644 index 7aeca1d83..000000000 --- a/test/unit/subset/value/bigNumber.test.js +++ /dev/null @@ -1,73 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -var cardinal = function(str) { - return nlp(str).values().numbers()[0]; -}; - -test('a very large cardinal', function(t) { - t.equal(cardinal('nine trillion two hundred'), 9000000000200); - t.equal(cardinal('nine quadrillion two thousand and six'), 9000000000002006); - t.equal(cardinal('ninety quintillion two thousand and six'), 90000000000000002006); - t.equal(cardinal('ninety nine quintillion two thousand and six'), 99000000000000002006); - t.equal(cardinal('nine sextillion'), 9000000000000000000000); - // t.equal(cardinal('nine septillion'), 9000000000000000000000000); - // t.equal(cardinal('ninety nine septillion two thousand and six'), 99000000000000000002006); - // t.equal(cardinal('one hundred and twenty-three septillion, four hundred and fifty-six sextillion, seven hundred and eighty-nine quintillion, one hundred and twenty-three quadrillion, four hundred and fifty-six trillion, seven hundred and eighty-nine billion, one hundred and twenty-three million, four hundred and fifty-six thousand and seven hundred and eighty-nine'), 123456789123456789123456789); - // t.equal(cardinal('seven hundred and eighty-nine quintillion, one hundred and twenty-three quadrillion, four hundred and fifty-six trillion, seven hundred and eighty-nine billion, one hundred and twenty-three million, four hundred and fifty-six thousand and seven hundred and eighty-nine'), 789123456789123456789); - t.end(); -}); - -test('number ordinal', function(t) { - t.equal(nlp('two hundred sextillion').values().data()[0].niceOrdinal, '200,000,000,000,000,000,000,000th'); - t.equal(nlp('thirty seven quadrillion and two hundred').values().data()[0].niceOrdinal, '37,000,000,000,000,200th'); - t.equal(nlp('thirty seven quadrillion, two thousand').values().data()[0].niceOrdinal, '37,000,000,000,002,000th'); - t.equal(nlp('ninety nine quadrillion, two hundred thousand').values().data()[0].niceOrdinal, '99,000,000,000,200,000th'); - //javascript math can't do this. - // t.equal(nlp('thirty sextillion and two').values().data()[0].niceOrdinal, '30,000,000,000,000,000,000,002nd'); - // t.equal(nlp('ninety nine quadrillion, two hundred and fifty thousand').values().data()[0].niceOrdinal, '99,000,000,000,250,000th'); - t.end(); -}); - -test('text ordinal', function(t) { - t.equal(nlp('thirty quadrillion and two hundred').values().data()[0].textOrdinal, 'thirty quadrillion two hundredth'); - t.equal(nlp('nine trillion seven hundred fifty').values().data()[0].textOrdinal, 'nine trillion seven hundred and fiftieth'); - t.equal(nlp('a quintillion').values().data()[0].textOrdinal, 'one quintillionth'); - t.equal(nlp('seventy-two quintillion').values().data()[0].textOrdinal, 'seventy two quintillionth'); - t.end(); -}); - -test('from number', function(t) { - t.equal(nlp('9000000000200').values().toText().out(), 'nine trillion two hundred'); - t.equal(nlp('70000000000200').values().toText().out(), 'seventy trillion two hundred'); - t.equal(nlp('9000000000002006').values().toText().out(), 'nine quadrillion two thousand and six'); - t.equal(nlp('900,000,000').values().toText().out(), 'nine hundred million'); - t.equal(nlp('9,000,000,030').values().toText().out(), 'nine billion and thirty'); - t.equal(nlp('10,000,000,000').values().toText().out(), 'ten billion'); - // t.equal(nlp('900,000,000,037').values().toText().out(), 'nine hundred billion and thirty seven'); - //javascript can't do this - // t.equal(nlp('90000000000000002006').values().toText().out(), 'ninety quintillion two thousand and six'); - // t.equal(nlp('99000000000000002006').values().toText().out(), 'ninety nine quintillion two thousand and six'); - // t.equal(nlp('9000000000000000000000').values().toText().out(), 'nine sextillion'); - t.end(); -}); - -// test('cardinal numbers', function(t) { -// t.equal(cardinal('sixty-one trillion, six hundred and eighty-nine billion, four hundred and seventy-three million, four hundred and fifty-three thousand and five hundred and ninety'), 61689473453590); -// t.end(); -// }); - -// test('cardinal numbers in american form (with ands)', function(t) { -// t.equal(cardinal('six hundred eighty-nine billion, four hundred seventy-three million, four hundred fifty-three thousand, five hundred ninety'), 689473453590); -// t.end(); -// }); - -// test('ordinal numbers', function(t) { -// t.equal(cardinal('six hundred and eighty-nine billion, four hundred and seventy-three million, four hundred and fifty-three thousand and five hundred and ninetieth'), 689473453590); -// t.end(); -// }); - -// test('cardinal numbers in american form (with ands)', function(t) { -// t.equal(cardinal('six hundred eighty-nine billion, four hundred seventy-three million, four hundred fifty-three thousand, five hundred ninetieth'), 689473453590); -// t.end(); -// }); diff --git a/test/unit/subset/value/comparison.test.js b/test/unit/subset/value/comparison.test.js deleted file mode 100644 index 270a908e3..000000000 --- a/test/unit/subset/value/comparison.test.js +++ /dev/null @@ -1,86 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('isEqual:', function(t) { - var str = nlp('he is 7 years old').values().isEqual(7).out('normal'); - t.equal(str, '7 years old', 'isEqual 7'); - - str = nlp('he is seven years old').values().isEqual(7).out('normal'); - t.equal(str, 'seven years old', 'isEqual seven'); - - str = nlp("it's his 7th birthday").values().isEqual(7).out('normal'); - t.equal(str, '7th birthday', 'isEqual 7th'); - - str = nlp("it's his seventh birthday").values().isEqual(7).out('normal'); - t.equal(str, 'seventh birthday', 'isEqual seventh'); - - str = nlp('i have 7 potatoes and 12 tomatoes').values().isEqual(7).out('normal'); - t.equal(str, '7 potatoes', 'only 7'); - - str = nlp('i have 17 potatoes and fourteen tomatoes').values().isEqual('seventeen').out('normal'); - t.equal(str, '17 potatoes', 'only 17'); - - str = nlp('i have 15 books and eight hundred tomatoes').values().isEqual('fifteenth').out('normal'); - t.equal(str, '15 books', 'only 15'); - - str = nlp('i have 152 potatoes and eight hundred and two tomatoes').values().isEqual('152nd').out('normal'); - t.equal(str, '152 potatoes', 'only 152'); - - str = nlp('i have 9 potatoes and 77 tomatoes').values().isEqual(7).out('normal'); - t.equal(str, '', 'no equal-to'); - t.end(); -}); - -test('greaterThan:', function(t) { - var str = nlp('he is 8 years old').values().greaterThan(7).out('normal'); - t.equal(str, '8 years old', '8 greaterThan 7'); - - str = nlp('he is forty years old').values().greaterThan(7).out('normal'); - t.equal(str, 'forty years old', 'fourty greaterThan 7'); - - str = nlp('fifteen donuts').values().greaterThan(7).out('normal'); - t.equal(str, 'fifteen donuts', 'fifteen greaterThan 7'); - - str = nlp('my fifteenth donut').values().greaterThan(7).out('normal'); - t.equal(str, 'fifteenth donut', 'fifteenth greaterThan 7'); - - str = nlp('i have 9 potatoes and 77 tomatoes').values().greaterThan(700).out('normal'); - t.equal(str, '', 'no greaterThan'); - - t.end(); -}); - -test('lessThan:', function(t) { - var str = nlp('he is 8 years old').values().lessThan(700).out('normal'); - t.equal(str, '8 years old', '8 lessThan 700'); - - str = nlp('he is forty years old').values().lessThan('forty-one').out('normal'); - t.equal(str, 'forty years old', 'fourty lessThan forty-one'); - - str = nlp('my fifteenth book').values().lessThan(70).out('normal'); - t.equal(str, 'fifteenth book', 'fifteenth lessThan 70'); - - str = nlp('i have 9 potatoes and 77 tomatoes').values().lessThan(9).out('normal'); - t.equal(str, '', 'no lessThan'); - - t.end(); -}); - -test('negative comparisons:', function(t) { - var str = nlp('i am 8 years old').values().greaterThan(-2).out('normal'); - t.equal(str, '8 years old', '8 greaterThan -2'); - - str = nlp('i am eighty years old').values().greaterThan('-200').out('normal'); - t.equal(str, 'eighty years old', 'eighty greaterThan -200'); - - str = nlp('it is minus seven degrees out').values().lessThan('seven').out('normal'); - t.equal(str, 'minus seven degrees', 'minus seven lessThan seven'); - - str = nlp('i am minus two years old').values().isEqual('-2').out('normal'); - t.equal(str, 'minus two years old', 'minus two isEqual -2'); - - str = nlp('i am -2 years old').values().isEqual(-2).out('normal'); - t.equal(str, '-2 years old', '-2 isEqual -2'); - - t.end(); -}); diff --git a/test/unit/subset/value/money.test.js b/test/unit/subset/value/money.test.js deleted file mode 100644 index 566392087..000000000 --- a/test/unit/subset/value/money.test.js +++ /dev/null @@ -1,53 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('money-basic:', function(t) { - var r = nlp('it is $70.23'); - var m = r.match('#Money'); - t.equal(m.out('normal'), '$70.23', 'match-$70.23'); - - r = nlp('it is $703'); - m = r.match('#Money+'); - t.equal(m.out('normal'), '$703', 'match-$703'); - - r = nlp('it is five euros'); - m = r.match('#Money+'); - t.equal(m.out('normal'), 'five euros', 'match-five-euros'); - - r = nlp('i said five times, you should pay 12 dollars'); - m = r.match('#Money+'); - t.equal(m.out('normal'), '12 dollars', 'match-12 dollars'); - - r = nlp('you should pay sixty five dollars and four cents USD'); - m = r.match('#Money+'); - t.equal(m.out('normal'), 'sixty five dollars and four cents usd', 'match-long-usd'); - - t.end(); -}); - -test('money-has:', function(t) { - var tests = [ - ['$7', true], - ['$7.0', true], - ['$7.00', true], - ['$7.003', false], - - ['$7082.03', true], - ['$2,082.03', true], - ['€7.00', true], - ['¥70', true], - ['£0.20', true], - ['@0.20', false], - - ['8 cents', true], - ['60 pence', true], - ['sixty pence', true], - ['sixty USD', true] - ]; - tests.forEach(function(a) { - var r = nlp(a[0]); - var m = r.match('#Money'); - t.equal(m.found, a[1], "money-has: '" + a[0] + "'"); - }); - t.end(); -}); diff --git a/test/unit/subset/value/percent.test.js b/test/unit/subset/value/percent.test.js deleted file mode 100644 index bc63f04a0..000000000 --- a/test/unit/subset/value/percent.test.js +++ /dev/null @@ -1,58 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('percent-basic:', function(t) { - var m = nlp('it is 33%').match('#Percent'); - t.equal(m.out('normal'), '33%', 'match-33%'); - - //parse number - var arr = nlp('it is 50% of our budget').values().data(); - t.equal(arr[0].number, 50, 'match-50'); - - arr = nlp('it is 9,000% of our budget').values().data(); - t.equal(arr[0].number, 9000, 'match-9000'); - - //percent-decimal - arr = nlp('it is 0.5% of our budget').values().data(); - t.equal(arr[0].number, 0.5, 'match-0.5'); - - t.end(); -}); - -test('percent-conversion:', function(t) { - var str = '3% of the budget'; - var r = nlp(str).values().toNumber().all(); - t.equal(r.out(), str, '3% to number'); - - str = "it's 39% of the budget"; - r = nlp(str).values().toNumber().all(); - t.equal(r.out(), str, '39% to number'); - - str = '39% of the budget'; - r = nlp(str).values().toText().all(); - t.equal(r.out(), 'thirty nine percent of the budget', 'to text'); - - str = 'around 100% of the budget'; - r = nlp(str).values().toText().all(); - t.equal(r.out(), 'around one hundred percent of the budget', 'to text'); - - t.end(); -}); - -test('percent-tag:', function(t) { - var tests = [ - ['7%', true], - ['7.0%', true], - ['2.22%', true], - ['.2%', true], - ['0.2%', true], - ['2,999%', true], - ['2asdf99%', false], - ['99%3', false] - ]; - tests.forEach(function(a) { - var r = nlp(a[0]); - t.equal(r.has('#Percent'), a[1], "Percent-has: '" + a[0] + "'"); - }); - t.end(); -}); diff --git a/test/unit/subset/value/toCardinal.test.js b/test/unit/subset/value/toCardinal.test.js deleted file mode 100644 index a65685c66..000000000 --- a/test/unit/subset/value/toCardinal.test.js +++ /dev/null @@ -1,123 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -//tests 'borrowed' from Travis Savo's lib 💝 https://github.com/TSavo/english2number-js -var cardinal = function(str) { - return nlp(str).values().numbers()[0]; -}; - -test('should give right answers for numbers', function(t) { - t.equal(cardinal('0'), 0); - t.equal(cardinal('1'), 1); - t.equal(cardinal('2'), 2); - t.equal(cardinal('3'), 3); - t.equal(cardinal('4'), 4); - t.equal(cardinal('5'), 5); - t.equal(cardinal('6'), 6); - t.equal(cardinal('7'), 7); - t.equal(cardinal('8'), 8); - t.equal(cardinal('9'), 9); - t.equal(cardinal('10'), 10); - t.equal(cardinal('20'), 20); - t.equal(cardinal('30'), 30); - t.equal(cardinal('50'), 50); - t.equal(cardinal('90'), 90); - t.equal(cardinal('100'), 100); - t.end(); -}); -test('should give right answers for numbered ordinals', function(t) { - t.equal(cardinal('0th'), 0); - t.equal(cardinal('1st'), 1); - t.equal(cardinal('2nd'), 2); - t.equal(cardinal('3rd'), 3); - t.equal(cardinal('4th'), 4); - t.equal(cardinal('5th'), 5); - t.equal(cardinal('6th'), 6); - t.equal(cardinal('7th'), 7); - t.equal(cardinal('8th'), 8); - t.equal(cardinal('9th'), 9); - t.equal(cardinal('10th'), 10); - t.equal(cardinal('20th'), 20); - t.equal(cardinal('30th'), 30); - t.equal(cardinal('50th'), 50); - t.equal(cardinal('77th'), 77); - t.equal(cardinal('90th'), 90); - t.equal(cardinal('100th'), 100); - t.end(); -}); -test('should give right answers for english names of numbers', function(t) { - t.equal(cardinal('zero'), 0); - t.equal(cardinal('one'), 1); - t.equal(cardinal('two'), 2); - t.equal(cardinal('three'), 3); - t.equal(cardinal('four'), 4); - t.equal(cardinal('five'), 5); - t.equal(cardinal('six'), 6); - t.equal(cardinal('seven'), 7); - t.equal(cardinal('eight'), 8); - t.equal(cardinal('nine'), 9); - t.equal(cardinal('ten'), 10); - t.equal(cardinal('eleven'), 11); - t.equal(cardinal('twelve'), 12); - t.equal(cardinal('thirteen'), 13); - t.equal(cardinal('fourteen'), 14); - t.equal(cardinal('fifteen'), 15); - t.equal(cardinal('sixteen'), 16); - t.equal(cardinal('seventeen'), 17); - t.equal(cardinal('eighteen'), 18); - t.equal(cardinal('nineteen'), 19); - t.equal(cardinal('twenty'), 20); - t.equal(cardinal('twenty-five'), 25); - t.equal(cardinal('twenty five'), 25); - t.equal(cardinal('forty-four'), 44); - t.equal(cardinal('forty four'), 44); - t.equal(cardinal('fourty four'), 44); //typo - t.equal(cardinal('seventy'), 70); - t.equal(cardinal('seventy-seven'), 77); - t.equal(cardinal('eighty eight'), 88); - t.equal(cardinal('ninety nine'), 99); - t.equal(cardinal('one-hundred'), 100); - t.equal(cardinal('one hundred'), 100); - t.end(); -}); -test('should give right answers for english names of ordinal positions', function(t) { - t.equal(cardinal('zeroth'), 0); - t.equal(cardinal('first'), 1); - t.equal(cardinal('second'), 2); - t.equal(cardinal('third'), 3); - t.equal(cardinal('fourth'), 4); - t.equal(cardinal('fifth'), 5); - t.equal(cardinal('sixth'), 6); - t.equal(cardinal('seventh'), 7); - t.equal(cardinal('eighth'), 8); - t.equal(cardinal('ninth'), 9); - t.equal(cardinal('tenth'), 10); - t.equal(cardinal('eleventh'), 11); - t.equal(cardinal('twelfth'), 12); - t.equal(cardinal('thirteenth'), 13); - t.equal(cardinal('fourteenth'), 14); - t.equal(cardinal('fifteenth'), 15); - t.equal(cardinal('sixteenth'), 16); - t.equal(cardinal('seventeenth'), 17); - t.equal(cardinal('eighteenth'), 18); - t.equal(cardinal('nineteenth'), 19); - t.equal(cardinal('twentieth'), 20); - t.equal(cardinal('twenty first'), 21); - t.equal(cardinal('twenty second'), 22); - t.equal(cardinal('twenty third'), 23); - t.equal(cardinal('twenty fourth'), 24); - t.equal(cardinal('twenty-fifth'), 25); - t.equal(cardinal('forty-fourth'), 44); - t.equal(cardinal('seventieth'), 70); - t.equal(cardinal('seventy-seventh'), 77); - t.equal(cardinal('ninetieth'), 90); - t.equal(cardinal('ninety ninth'), 99); - t.equal(cardinal('one-hundredth'), 100); - t.end(); -}); - -test('should deal with negative numbers', function(t) { - t.equal(cardinal('negative thirty eight thousand two hundred sixty three'), -38263); - t.equal(cardinal('negative thirty eight thousand two hundred sixty three'), -38263); - t.equal(cardinal('negative zero'), -0); - t.end(); -}); diff --git a/test/unit/subset/value/toNumber.test.js b/test/unit/subset/value/toNumber.test.js deleted file mode 100644 index f2cad7239..000000000 --- a/test/unit/subset/value/toNumber.test.js +++ /dev/null @@ -1,146 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('to_number:', function(t) { - [ - ['twenty two thousand five hundred', 22500], - ['two thousand five hundred and sixty', 2560], - ['a hundred and two', 102], - ['a hundred', 100], - ['seven', 7], - ['seven grand', 7000], - ['104', 104], - ['13 thousand', 13000], - ['17,983', 17983], - ['nine hundred', 900], - ['twenty one hundred', 2100], - ['twenty one', 21], - ['seventy two', 72], - ['two hundred two', 202], - ['one thousand one', 1001], - ['minus five hundred', -500], - ['minus fifteen', -15], - ['five hundred million', 500000000], - // ['$12.03', 12.03], - // ['$12', 12], - ['5 hundred', 500], - ['5.2 thousand', 5200], - ['million', 1000000], - ['hundred one', 101], - ['minus fifty', -50], - ['twenty thousand', 20000], - ['four point six', 4.6], - ['nine hundred point five', 900.5], - ['sixteen hundred sixteen point eight', 1616.8], - ['four point seven nine', 4.79], - ['four point sixteen', 4.16], - ['twenty first', '21st'], - ['fifty ninth', '59th'], - ['nine hundred fiftieth', '950th'], - ['nine hundred and second', '902nd'], - ['five thousand nine hundred fiftieth', '5950th'], - ['six hundred and fifty nine', 659], - ['six hundred and fifty nine thousand', 659000], - [950, 950], - [999999950, 999999950], - [8080999999950, 8080999999950], - ['fifteen million and two', 15000002], - ['six hundred and eighteen', 618], - ['two hundred thousand', 200000], - ['six million ninety', 6000090], - ['twenty-two hundred', 2200], - - ['two million five hundred thousand', 2500000], - ['one billion five hundred thousand', 1000500000], - ['one billion five hundred thousand and eight', 1000500008], - ['a million fifty thousand and eight', 1050008], - ['a million twenty five thousand and fifty-two', 1025052], - ['minus two million twenty five thousand and eighty', -2025080], - - ['7 hundred and 8 thousand', 708000], - ['2 hundred and sixty 9 thousand seven hundred', 269700], - ['2 hundred and six million 7 hundred thousand seven hundred', 206700700], - - ['minus 70', -70], - ['minus eight', -8], - ['minus 8 hundred', -800], - ['twenty-seven hundred', 2700], - ['minus eight thousand two hundred', -8200], - ['twenty-five', 25], - ['half a million', 500000], - ['five hundred eighteen', 518], - ['eighty eight point nine nine', 88.99], - ['minus eighty eight point nine nine', -88.99], - // ['1/2', 1 / 2], - // ['-1/5', -1 / 5], - // ['-1 1/10', -1 - 1 / 10], - // ['1 1/20', 1 + 1 / 20], - // ['1/2 million', 500000], - // ['1 1/2 million', 1500000], - ['negative five', -5], - ['negative hundred', -100], - // ['12:32', ''], - // ['123-1231', ''], - ['seven eleven', '7 11'], - ['ten-four', '10 4'], - ['one seven', '1 7'], - ['one ten', '1 10'], - ['one twelve', '1 12'], - ['one thirty', '1 30'], - ['nine fifty', '9 50'], - ['five six', '5 6'], - ['nine seventy', '9 70'], - ['nine two hundred', '9 200'], - ['ten one', '10 1'], - ['twelve one', '12 1'], - ['seventy five two', '75 2'], - // ['two hundred three hundred', '200 300'], //tricky - ['sixty fifteen hundred', '60 1500'], - ['one twenty', '1 20'], - ['twenty five twenty', '25 20'] - // ['',''], - // [null,''], - ].forEach(function(a) { - var num = nlp(a[0]).values().toNumber().out('text'); - var want = String(a[1]) || a[0]; - var msg = '\'' + a[0] + '\' - - have: \'' + num + '\' want:\'' + a[1] + '\''; - t.equal(num, String(want), msg); - }); - t.end(); -}); - -test('all-to-number:', function(t) { - var num = nlp('1st').values().numbers()[0]; - t.equal(num, 1, '1st'); - num = nlp('1').values().numbers()[0]; - t.equal(num, 1, '1'); - num = nlp('first').values().numbers()[0]; - t.equal(num, 1, 'first'); - num = nlp('one').values().numbers()[0]; - t.equal(num, 1, 'one'); - //long-numbers - num = nlp('55575').values().numbers()[0]; - t.equal(num, 55575, '55575'); - num = nlp('55,575').values().numbers()[0]; - t.equal(num, 55575, '55,575'); - num = nlp('55,575.279').values().numbers()[0]; - t.equal(num, 55575.279, '55,575.279'); - num = nlp('$55,575').values().numbers()[0]; - t.equal(num, 55575, '$55,575'); - //decimals - num = nlp('2.5').values().numbers()[0]; - t.equal(num, 2.5, '2.5'); - num = nlp('2.5th').values().numbers()[0]; - t.equal(num, 2.5, '2.5th'); - //two-terms - num = nlp('fifty seven').values().numbers()[0]; - t.equal(num, 57, 'fifty seven'); - num = nlp('fifty 7').values().numbers()[0]; - t.equal(num, 57, 'fifty 7'); - num = nlp('2 hundred').values().numbers()[0]; - t.equal(num, 200, '2 hundred'); - num = nlp('2 hundredth').values().numbers()[0]; - t.equal(num, 200, '2 hundredth'); - - t.end(); -}); diff --git a/test/unit/subset/value/toOrdinal.test.js b/test/unit/subset/value/toOrdinal.test.js deleted file mode 100644 index fea8265c8..000000000 --- a/test/unit/subset/value/toOrdinal.test.js +++ /dev/null @@ -1,52 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('to-numOrdinal:', function(t) { - var arr = [ - 'one', - '1', - '1.0', //not sure.. - '1st', - 'first' - ]; - arr.forEach(txt => { - var o = nlp(txt).values().data()[0] || {}; - t.equal(o.ordinal, '1st', txt + ' -> 1st'); - }); - arr = ['500', '500.0', '500th', 'five hundred', 'five hundredth']; - arr.forEach(txt => { - var o = nlp(txt).values().data()[0] || {}; - t.equal(o.ordinal, '500th', txt + ' -> 500th'); - }); - arr = ['2012', '2012.0', '2,012', '2012th', 'two thousand and twelve', 'two thousand and twelfth']; - arr.forEach(txt => { - var o = nlp(txt).values().data()[0] || {}; - t.equal(o.ordinal, '2012th', txt + ' -> 2012th'); - }); - t.end(); -}); - -test('to-textOrdinal:', function(t) { - var arr = [ - 'one', - '1', - '1.0', //not sure.. - '1st', - 'first' - ]; - arr.forEach(txt => { - var o = nlp(txt).values().data()[0] || {}; - t.equal(o.textOrdinal, 'first', txt + ' -> first'); - }); - arr = ['500', '500.0', '500th', 'five hundred', 'five hundredth']; - arr.forEach(txt => { - var o = nlp(txt).values().data()[0] || {}; - t.equal(o.textOrdinal, 'five hundredth', txt + ' -> five hundredth'); - }); - arr = ['2012', '2012.0', '2,012', '2012th', 'two thousand and twelve', 'two thousand and twelfth']; - arr.forEach(txt => { - var o = nlp(txt).values().data()[0] || {}; - t.equal(o.textOrdinal, 'two thousand and twelfth', txt + ' -> two thousand and twelfth'); - }); - t.end(); -}); diff --git a/test/unit/subset/value/toText.test.js b/test/unit/subset/value/toText.test.js deleted file mode 100644 index f0f1e6cec..000000000 --- a/test/unit/subset/value/toText.test.js +++ /dev/null @@ -1,70 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('to_text:', function(t) { - [ - // [-5, 'negative five'], - [5, 'five'], - [15, 'fifteen'], - [10, 'ten'], - [20, 'twenty'], - [75, 'seventy five'], - [97, 'ninety seven'], - [111, 'one hundred and eleven'], - [175, 'one hundred and seventy five'], - [900, 'nine hundred'], - [1175, 'one thousand one hundred and seventy five'], - [2000, 'two thousand'], - [2100, 'two thousand one hundred'], - [2102, 'two thousand one hundred and two'], - [70000, 'seventy thousand'], - [72000, 'seventy two thousand'], - [900000, 'nine hundred thousand'], - [900001, 'nine hundred thousand and one'], - [900200, 'nine hundred thousand two hundred'], - [900205, 'nine hundred thousand two hundred and five'], - [7900205, 'seven million nine hundred thousand two hundred and five'], - [90000000, 'ninety million'], - [900000000, 'nine hundred million'], - [900000080, 'nine hundred million and eighty'] - ].forEach(function(a) { - var str = nlp(a[0]).values().toText().out('text'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('all-to-text:', function(t) { - var arr = [ - 'one', - '1', - '1.0', //not sure.. - '1st', - 'first' - ]; - arr.forEach(txt => { - var str = nlp(txt).values().data()[0].text; - t.equal(str, 'one', txt + ' -> one'); - }); - arr = ['500', '500.0', '500th', 'five hundred', 'five hundredth']; - arr.forEach(txt => { - var str = nlp(txt).values().data()[0].text; - t.equal(str, 'five hundred', txt + ' -> five hundred'); - }); - arr = ['2012', '2012.0', '2,012', '2012th', 'two thousand and twelve', 'two thousand and twelfth']; - arr.forEach(txt => { - var str = nlp(txt).values().data()[0].text; - t.equal(str, 'two thousand and twelve', txt + ' -> two thousand and twelve'); - }); - t.end(); -}); - -test('big number:', function(t) { - var str = nlp('twenty-three quadrillion').values().toText().out(); - t.equal(str, 'twenty three quadrillion', 'quadrillion'); - - // str = nlp('nine quintillion two hundred').values().toText().out(); - // t.equal(str, 'nine quintillion two hundred', 'quantillion'); - t.end(); -}); diff --git a/test/unit/subset/value/value.test.js b/test/unit/subset/value/value.test.js deleted file mode 100644 index f13668d3c..000000000 --- a/test/unit/subset/value/value.test.js +++ /dev/null @@ -1,204 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); -var str_test = require('../../lib/fns').str_test; - -test('value-lumper-splitter:', function(t) { - var r = nlp('202 199'); - t.equal(r.values().length, 2, 'two-numbers'); - - r = nlp('two hundred and fifty times six'); - t.equal(r.values().length, 2, 'two-numbers2'); - - r = nlp('one two'); - t.equal(r.values().length, 2, 'two-numbers3'); - - r = nlp('fifth ninth'); - t.equal(r.values().length, 2, 'two-numbers4'); - t.end(); -}); - -test('value-basic:', function(t) { - var r = nlp('third month of 2019'); - r.values().toNumber(); - t.equal(r.out(), '3rd month of 2019', 'toNumber'); - - r.values().toText(); - t.equal(r.out(), 'third month of two thousand and nineteen', 'toText'); - - r = nlp('third month of two thousand and nineteen'); - r.values().toCardinal(); - t.equal(r.out(), 'three month of two thousand and nineteen', 'toCardinal'); - - r = nlp('three month of two thousand nineteen'); - r.values().toOrdinal(); - t.equal(r.out(), 'third month of two thousand and nineteenth', 'toOrdinal'); - - r.values().toNumber().all(); - t.equal(r.out(), '3rd month of 2019th', 'toNumber2'); - - t.end(); -}); - -test('value-to_ordinal:', function(t) { - [[11, '11th'], [5, '5th'], [22, '22nd']].forEach(function(a) { - var str = nlp(a[0]).values().toOrdinal().out('normal'); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('value-number:', function(t) { - [ - ['five hundred feet', 500], - ['fifty square feet', 50], - ['90 hertz', 90], - // ['5 six-ounce containers', 5], - ['twelve 2-gram containers', 12], - ['thirty-seven forever-21 stores', 37] - ].forEach(function(a) { - var str = nlp(a[0]).values().toNumber().term(0).first().out('normal'); - a[1] = String(a[1]); - str_test(str, a[0], a[1], t); - }); - t.end(); -}); - -test('add/subtract:', function(t) { - var r = nlp('beginning of 2019').values().add(2).all(); - t.equal(r.out(), 'beginning of 2021', 'add-2-cardinal'); - - r = nlp('beginning of the 2019th').values().add(2).all(); - t.equal(r.out(), 'beginning of the 2021st', 'add-2-ordinal'); - - r = nlp('beginning of the 2019th').values().add(-2).all(); - t.equal(r.out(), 'beginning of the 2017th', 'add-minus-2-ordinal'); - - r = nlp('beginning of 2019').values().subtract(2).all(); - t.equal(r.out(), 'beginning of 2017', 'subtract-2-cardinal'); - - r = nlp('beginning of the 2019th').values().subtract(2).all(); - t.equal(r.out(), 'beginning of the 2017th', 'subtract-2-ordinal'); - - r = nlp('seventeen years old').values().add(2).all(); - t.equal(r.out(), 'nineteen years old', 'text-add-2-ordinal'); - r = nlp('seventeenth birthday').values().add(2).all(); - t.equal(r.out(), 'nineteenth birthday', 'text-add-2-ordinal'); - - r = nlp('seventeen years old').values().subtract(2).all(); - t.equal(r.out(), 'fifteen years old', 'text-subtract-2-cardinal'); - r = nlp('seventeenth birthday').values().subtract(2).all(); - t.equal(r.out(), 'fifteenth birthday', 'text-subtract-2-cardinal'); - - r = nlp('seven apples and 1,231 peaches').values().add(50).all(); - t.equal(r.out(), 'fifty seven apples and 1,281 peaches', 'two-add-50s'); - t.end(); -}); - -test('increment:', function(t) { - var r = nlp('seven apples and 231 peaches'); - r.values().increment(); - t.equal(r.out(), 'eight apples and 232 peaches', 'increment-cardinal'); - r.values().decrement(); - t.equal(r.out(), 'seven apples and 231 peaches', 'decrement-cardinal'); - - r = nlp('seventh place and 12th place'); - r.values().increment().increment(); - t.equal(r.out(), 'ninth place and 14th place', 'increment-ordinal'); - r.values().decrement().decrement(); - t.equal(r.out(), 'seventh place and 12th place', 'decrement-ordinal'); - t.end(); -}); - -test('nounit:', function(t) { - var r = nlp('seven apples and 231 peaches'); - var arr = r.values().out('array'); - t.deepEqual(arr, ['seven apples', '231 peaches']); - - arr = r.values().noUnits().out('array'); - t.deepEqual(arr, ['seven', '231']); - t.end(); -}); - -test('value-unit:', function(t) { - [ - ['five hundred feet', 'feet'], - ['fifty hertz', 'hertz'], - ['100 dollars', 'dollars'], - // ['$100', 'dollar'], - // ['¥2.5', 'yen'], - // ['€3,000,100', 'euro'], - // ['EUR 9.99', 'eur'], - // ['5 g', 'g'], - // ['2 in', 'in'], - // ['5 g sugar', 'g'], - ['3 grams', 'grams'], - ['2 inches', 'inches'], - ['10 grams of sugar', 'grams'], - ['fifty inches of snow', 'inches'], - ['7 years', 'years'], - ['7.5 days', 'days'], - - ['7th year', 'year'], - ['7th years', ''], - ['1 day', 'day'], - ['one book', 'book'], - ['first book', 'book'], - ['7 day', ''], - ].forEach(function(a) { - var r = nlp(a[0]).values().units(); - str_test(r.out('normal'), a[0], a[1], t); - }); - t.end(); -}); - -test('number splits', function(t) { - var arr = [ - '12, 34, 56', - '12 34 56', - '12, 34, 56', - '1 2 4' - ]; - arr.forEach((str) => { - var tokens = nlp(str).values().out('array'); - t.equal(tokens.length, 3, str); - }); - t.end(); -}); - -// test('value-measurement:', function(t) { -// [ -// ['five hundred feet', 'Distance'], -// ['100 kilometers', 'Distance'], -// ['fifty hertz', 'Frequency'], -// ['59 thousand $', 'Money'], -// ['100 mb', 'Data'], -// ['50 руб', 'Money'], -// ['EUR 9.99', 'Money'], -// ['100 dollars', 'Money'], -// ['256 bitcoins', 'Money'], -// ].forEach(function (a) { -// var str = nlp.value(a[0]).measurement; -// str_test(str, a[0], a[1], t); -// }); -// t.end(); -// }); -// -// test('value-of_what:', function(t) { -// [ -// ['nine kg', 'kg'], -// ['5 kg of copper', 'copper'], -// ['many of these stories', 'many of these stories'], -// ['room full of beautiful creatures', 'full of beautiful creatures'], -// ['boxes of bags of food', 'boxes of bags of food'], -// ['5 boxes of water', 'boxes of water'], -// ['6 of kids', 'kids'], -// ['10 kids', 'kids'], -// ['just nothing', 'just nothing'], -// ['EUR 77', 'eur'], -// ['kg', 'kg'] -// ].forEach(function (a) { -// var str = nlp.value(a[0]).of_what; -// str_test(str, a[0], a[1], t); -// }); -// t.end(); -// }); diff --git a/test/unit/subset/verb/conjugate.test.js b/test/unit/subset/verb/conjugate.test.js deleted file mode 100644 index 0b2041775..000000000 --- a/test/unit/subset/verb/conjugate.test.js +++ /dev/null @@ -1,252 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -var arr = [ - { - Infinitive: 'convolute', - PresentTense: 'convolutes', - Gerund: 'convoluting', - PastTense: 'convoluted' - }, - { - PresentTense: 'presents', - Gerund: 'presenting', - PastTense: 'presented', - Infinitive: 'present' - }, - { - PresentTense: 'angulates', - Gerund: 'angulating', - PastTense: 'angulated', - Infinitive: 'angulate' - }, - { - PresentTense: 'conjures', - Gerund: 'conjuring', - PastTense: 'conjured', - Infinitive: 'conjure' - }, - { - PresentTense: 'denounces', - Gerund: 'denouncing', - PastTense: 'denounced', - Infinitive: 'denounce' - }, - { - PresentTense: 'watches', - Gerund: 'watching', - PastTense: 'watched', - Infinitive: 'watch' - }, - { - PresentTense: 'tingles', - Gerund: 'tingling', - PastTense: 'tingled', - Infinitive: 'tingle' - }, - { - PresentTense: 'mortises', - Gerund: 'mortising', - PastTense: 'mortised', - Infinitive: 'mortise' - }, - { - PresentTense: 'disguises', - Gerund: 'disguising', - PastTense: 'disguised', - Infinitive: 'disguise' - }, - { - Infinitive: 'effect', - Gerund: 'effecting', - PastTense: 'effected', - PresentTense: 'effects' - }, - { - Infinitive: 'want', - Gerund: 'wanting', - PastTense: 'wanted', - PresentTense: 'wants' - }, - { - Infinitive: 'power', - Gerund: 'powering', - PastTense: 'powered', - PresentTense: 'powers' - }, - { - Infinitive: 'overcompensate', - PresentTense: 'overcompensates', - PastTense: 'overcompensated', - Gerund: 'overcompensating' - }, - { - Infinitive: 'ice', - PresentTense: 'ices', - PastTense: 'iced', - Gerund: 'icing' - }, - { - Infinitive: 'buy', - PresentTense: 'buys', - PastTense: 'bought', - Gerund: 'buying' - }, - { - Infinitive: 'flower', - PresentTense: 'flowers', - PastTense: 'flowered', - Gerund: 'flowering' - }, - { - Infinitive: 'rage', - PresentTense: 'rages', - PastTense: 'raged', - Gerund: 'raging' - }, - { - Infinitive: 'drive', - PresentTense: 'drives', - PastTense: 'drove', - Gerund: 'driving' - }, - { - Infinitive: 'foul', - PresentTense: 'fouls', - PastTense: 'fouled', - Gerund: 'fouling' - }, - { - Infinitive: 'overthrow', - PresentTense: 'overthrows', - Gerund: 'overthrowing', - PastTense: 'overthrew' - }, - { - Infinitive: 'aim', - PresentTense: 'aims', - PastTense: 'aimed', - Gerund: 'aiming' - }, - { - PresentTense: 'unifies', - Gerund: 'unifying', - PastTense: 'unified', - Infinitive: 'unify' - }, - { - PresentTense: 'addresses', - Gerund: 'addressing', - PastTense: 'addressed', - Infinitive: 'address' - }, - { - Infinitive: 'bumble', - PresentTense: 'bumbles', - PastTense: 'bumbled', - Gerund: 'bumbling' - }, - { - Infinitive: 'snipe', - PresentTense: 'snipes', - PastTense: 'sniped', - Gerund: 'sniping' - }, - { - PresentTense: 'relishes', - Gerund: 'relishing', - PastTense: 'relished', - Infinitive: 'relish' - }, - { - Infinitive: 'lengthen', - Gerund: 'lengthening', - PastTense: 'lengthened', - PresentTense: 'lengthens' - }, - { - Infinitive: 'farm', - PresentTense: 'farms', - PastTense: 'farmed', - Gerund: 'farming' - }, - { - Infinitive: 'develop', - PresentTense: 'develops', - PastTense: 'developed', - Gerund: 'developing' - }, - { - Infinitive: 'study', - PresentTense: 'studies', - PastTense: 'studied', - Gerund: 'studying' - }, - { - Infinitive: 'criticise', - PresentTense: 'criticises', - PastTense: 'criticised', - Gerund: 'criticising' - }, - { - Infinitive: 'speak', - PresentTense: 'speaks', - PastTense: 'spoke', - Gerund: 'speaking' - }, - { - Infinitive: 'fuzz', - PresentTense: 'fuzzes', - PastTense: 'fuzzed', - Gerund: 'fuzzing' - }, - { - Infinitive: 'invest', - PresentTense: 'invests', - PastTense: 'invested', - Gerund: 'investing' - }, - { - Infinitive: 'age', - PresentTense: 'ages', - PastTense: 'aged', - Gerund: 'ageing' - }, - { - Infinitive: 'shed', - PresentTense: 'sheds', - PastTense: 'shed', - Gerund: 'shedding' - }, - { - Infinitive: 'ace', - PresentTense: 'aces', - PastTense: 'aced', - Gerund: 'acing' - }, - { - Infinitive: 'egg', - PresentTense: 'eggs', - PastTense: 'egged', - Gerund: 'egging' - } -]; -test('conjugation:', function(t) { - var test_conjugation = function(inf, o, form, original) { - var msg = 'from ' + original + ' to ' + form + ': [' + o[original] + '] -> [' + inf[form] + ']'; - t.equal(inf[form], o[form], msg); - }; - - arr.forEach(function(o) { - var forms = ['Infinitive', 'PastTense', 'PresentTense', 'Gerund']; - for (var i = 0; i < forms.length; i++) { - var from = forms[i]; - var inf = nlp(o[from]).tag('Verb').verbs().conjugate()[0]; - test_conjugation(inf, o, 'Infinitive', from); - test_conjugation(inf, o, 'PastTense', from); - test_conjugation(inf, o, 'PresentTense', from); - test_conjugation(inf, o, 'Gerund', from); - } - }); - t.end(); -}); diff --git a/test/unit/subset/verb/contractions.test.js b/test/unit/subset/verb/contractions.test.js deleted file mode 100644 index fc0c3ba57..000000000 --- a/test/unit/subset/verb/contractions.test.js +++ /dev/null @@ -1,19 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('conjugate-contractions:', function(t) { - [ - [`i'm good`, 'i was good'], - [`they're good`, 'they were good'], - //TODO: missing auxillary - // [`we've said`, 'we said'], //or 'we have said' - // [`they'd said`, 'they said'], //or 'they have said' - // (ambiguous) - // [`he's good`, 'he was good'], - ].forEach(function(a) { - var doc = nlp(a[0]); - doc.verbs().toPastTense(); - t.equal(doc.out(), a[1], a[1]); - }); - t.end(); -}); diff --git a/test/unit/subset/verb/modal.test.js b/test/unit/subset/verb/modal.test.js deleted file mode 100644 index 401d9adf9..000000000 --- a/test/unit/subset/verb/modal.test.js +++ /dev/null @@ -1,33 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -//ignore some modals during conjugation, i guess -test('ignore-would-behaviour', function(t) { - var str = nlp('he would walk').sentences().toPastTense().out(); - t.equal(str, 'he walked', 'would-past'); - - str = nlp('he would walk').sentences().toFutureTense().out(); - t.equal(str, 'he will walk', 'would-future'); - - str = nlp('he would walk').sentences().toPresentTense().out(); - t.equal(str, 'he walks', 'would-present'); - - str = nlp('he would walk').sentences().toContinuous().out(); - t.equal(str, 'he is walking', 'would-continuous'); - - t.end(); -}); - - -test('ignore-would-behaviour', function(t) { - var doc = nlp(`best look after`).verbs(); - var out = doc.conjugation(); - t.equal(doc.length, 1, 'one-verb'); - t.ok(out, 'no-error'); - t.end(); -}); - - -//can/could -//might -//should diff --git a/test/unit/subset/verb/parts.test.js b/test/unit/subset/verb/parts.test.js deleted file mode 100644 index e8b499f1d..000000000 --- a/test/unit/subset/verb/parts.test.js +++ /dev/null @@ -1,91 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('verb-parts:', function(t) { - var tests = [ - ['john is walking', '', 'is', ''], - ['john was walking', '', 'was', ''], - ['john will be walking', '', 'will be', ''], - ['john has been walking', '', 'has been', ''], - ['john had been walking', '', 'had been', ''], - ['john would have had been walking', '', 'would have had been', ''], - //negatives - ['john is not walking', 'not', 'is', ''], - ['john was not walking', 'not', 'was', ''], - ['john will not be walking', 'not', 'will be', ''], - ['john will be not walking', 'not', 'will be', ''], - ['john has not been walking', 'not', 'has been', ''], - ['john has been not walking', 'not', 'has been', ''], - ['john had not been walking', 'not', 'had been', ''], - ['john had been not walking', 'not', 'had been', ''], - ['john would be walking', '', 'would be', ''], - ['john would not be walking', 'not', 'would be', ''], - ['john would be not walking', 'not', 'would be', ''], - ['john would not have had been walking', 'not', 'would have had been', ''], - ['john would have not had been walking', 'not', 'would have had been', ''], - ['john would have had not been walking', 'not', 'would have had been', ''], - ['john would have had been not walking', 'not', 'would have had been', ''], - //adverbs + negatives combinations - ['john is really walking', '', 'is', 'really'], - ['john really is walking', '', 'is', 'really'], - ['john is walking really', '', 'is', 'really'], - ['john is not really walking', 'not', 'is', 'really'], - ['john is really not walking', 'not', 'is', 'really'], - ['john really is not walking', 'not', 'is', 'really'], - ['john is not walking really', 'not', 'is', 'really'], - ['john has really been not walking', 'not', 'has been', 'really'], - ['john has been really not walking', 'not', 'has been', 'really'], - ['john has been not really walking', 'not', 'has been', 'really'], - ['john has been not walking really', 'not', 'has been', 'really'], - ['john would really not have had been walking', 'not', 'would have had been', 'really'], - ['john would not really have had been walking', 'not', 'would have had been', 'really'], - ['john would not have really had been walking', 'not', 'would have had been', 'really'], - ['john would not have had really been walking', 'not', 'would have had been', 'really'], - ['john would not have had been really walking', 'not', 'would have had been', 'really'], - ['john would not have had been walking really', 'not', 'would have had been', 'really'] - ]; - tests.forEach(function(a) { - var arr = nlp(a[0]).verbs().data(); - t.equal(arr.length, 1, '#verbs - ' + arr.length); - t.equal(arr[0].parts.negative, a[1], "neg-test - '" + a[0] + "'"); - t.equal(arr[0].parts.auxiliary, a[2], "aux-test - '" + a[0] + "'"); - t.equal(arr[0].parts.verb, 'walking', "verb-test - '" + a[0] + "'"); - t.equal(arr[0].parts.adverbs, a[3], "adverb-test - '" + a[0] + "'"); - }); - t.end(); -}); - -//dont take it too-far -test('verb-greedy:', function(t) { - var arr = nlp('he would be, had he survived').verbs().data(); - t.equal(arr.length, 3, 'split-on-clause'); - - arr = nlp('we walked, talked, and sang').verbs().data(); - t.equal(arr.length, 3, 'split-on-list'); - - arr = nlp('we walked, talked, and quickly sang').verbs().data(); - t.equal(arr.length, 3, 'split-on-list2'); - - arr = nlp('we suddenly walked, talked, and abruptly sang').verbs().data(); - t.equal(arr.length, 3, 'split-on-list3'); - - arr = nlp('we really').verbs().data(); - t.equal(arr.length, 0, 'adverb-isnt-a-verb'); - - arr = nlp('we really really').verbs().data(); - t.equal(arr.length, 0, 'two-adverbs-isnt-a-verb'); - - arr = nlp('not good').verbs().data(); - t.equal(arr.length, 0, 'not-isnt-a-verb'); - - var str = nlp('we must not').verbs().out('normal'); - t.equal(str, 'must not', 'verb-not'); - - str = nlp('we must really').verbs().out('normal'); - t.equal(str, 'must really', 'verb-adverb'); - - str = nlp('we must really not').verbs().out('normal'); - t.equal(str, 'must really not', 'verb-adverb-not'); - - t.end(); -}); diff --git a/test/unit/subset/verb/phrasal.test.js b/test/unit/subset/verb/phrasal.test.js deleted file mode 100644 index 57e83edad..000000000 --- a/test/unit/subset/verb/phrasal.test.js +++ /dev/null @@ -1,22 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('phrasal-verbs:', function(t) { - [ - [`he is really good`, ['he', 'is', 'really', 'good']], - [`he is upset about it`, ['he', 'is', 'upset', 'about', 'it']], - [`he will mess about with it`, ['he', 'will', 'mess about', 'with', 'it']], - - [`come forward`, ['come forward']], - [`come together`, ['come together']], - [`come apart`, ['come apart']], - - [`frighten back`, ['frighten', 'back']], - [`frighten away`, ['frighten away']] - ].forEach(function(a) { - var terms = nlp(a[0]).out('array'); - var msg = terms.join(' ') + ' -- ' + a[1].join(' '); - t.equal(terms.join(' '), a[1].join(' '), msg); - }); - t.end(); -}); diff --git a/test/unit/subset/verb/plural.test.js b/test/unit/subset/verb/plural.test.js deleted file mode 100644 index ac819cad7..000000000 --- a/test/unit/subset/verb/plural.test.js +++ /dev/null @@ -1,25 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('plural-verbs:', function(t) { - var r = nlp('i look at'); - var len = r.verbs().isPlural().length; - t.equal(len, 0, 'i singular'); - - r = nlp('we look at it. They report on it'); - len = r.verbs().isPlural().length; - t.equal(len, 2, 'they plural'); - - r = nlp('lkjsdf are cool'); - var str = r.verbs().isPlural().out('normal'); - t.equal(str, 'are', 'are plural'); - - r = nlp('lkjsdf does eat bugs'); - str = r.verbs().isPlural().out('normal'); - t.equal(str, 'does eat', 'does plural'); - - r = nlp('lkjsdf is cool'); - str = r.verbs().isPlural().out('normal'); - t.equal(str, '', 'is singular'); - t.end(); -}); diff --git a/test/unit/subset/verb/toAdjective.test.js b/test/unit/subset/verb/toAdjective.test.js deleted file mode 100644 index 8d292df3c..000000000 --- a/test/unit/subset/verb/toAdjective.test.js +++ /dev/null @@ -1,16 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('verb-to-adjective:', function(t) { - [ - ['walk', 'walkable'], - ['sing', 'singable'], - ['win', 'winnable'], - ['convert', 'convertible'], - ['see', 'visible'] - ].forEach(function(a) { - var str = nlp(a[0]).verbs().asAdjective()[0]; - t.equal(str, a[1], str + ' -> ' + a[1]); - }); - t.end(); -}); diff --git a/test/unit/subset/verb/toGerund.test.js b/test/unit/subset/verb/toGerund.test.js deleted file mode 100644 index 972e6d075..000000000 --- a/test/unit/subset/verb/toGerund.test.js +++ /dev/null @@ -1,19 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('verb-to-gerund:', function(t) { - [ - ['walk', 'is walking'], - ['sing', 'is singing'], - ['win', 'is winning'], - ['will convert', 'is converting'], - ['see', 'is seeing'], - ['is', 'is being'], - ['was', 'is being'], - ['am', 'is being'] - ].forEach(function(a) { - var str = nlp(a[0]).verbs().toGerund().out('normal'); - t.equal(str, a[1], str + ' -> ' + a[1]); - }); - t.end(); -}); diff --git a/test/unit/subset/verb/toNegative.test.js b/test/unit/subset/verb/toNegative.test.js deleted file mode 100644 index b18b963e7..000000000 --- a/test/unit/subset/verb/toNegative.test.js +++ /dev/null @@ -1,46 +0,0 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); - -test('verb-to-negative:', function(t) { - [ - [`he is nice`, 'is not'], - [`she was nice`, 'was not'], - - [`she has walked`, 'has not walked'], - [`she had walked`, 'had not walked'], - [`we have had problems`, 'have not had'], - [`we would walk`, 'would not walk'], - [`we would have walked`, 'would not have walked'], - - //conjugations - [`she walked`, 'did not walk'], - [`it all came apart`, 'all did not come apart'], - - //phrasals - [`he would come forward`, 'would not come forward'], - [`we come together`, 'do not come together'], - [`he was frightened`, 'was not'], - [`i didn't want to`, 'didn\'t want'], - - //===singular - // pastTense - - ['john played', 'did not play'], - // presentTense - - ['john plays', 'does not play'], - // futureTense - - ['john will play', 'will not play'], - - ///===plural - // pastTense - - ['we played', 'did not play'], - // presentTense - - ['we play', 'do not play'], - // futureTense - - ['we will play', 'will not play'] - ].forEach(function(a) { - var vb = nlp(a[0]).verbs().toNegative(); - var str = vb.out('normal'); - t.equal(str, a[1], '\'' + str + '\' - - want: ' + a[1]); - }); - t.end(); -}); diff --git a/test/unit/tagger/emoji.test.js b/test/unit/tagger/emoji.test.js deleted file mode 100644 index b37c514f0..000000000 --- a/test/unit/tagger/emoji.test.js +++ /dev/null @@ -1,46 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('keyword emojis', function(t) { - [ - ['he is so nice :heart:', ':heart:'], - [':cool: :wine_glass: yeah party', ':cool: :wine_glass:'], - ['to be or not to be: this is a question :cookie:', ':cookie:'] - ].forEach(function(a) { - var have = nlp(a[0]).match('#Emoji').out('normal'); - var msg = "have: '" + have + "' want: '" + a[1] + "'"; - t.equal(have, a[1], msg); - }); - t.end(); -}); - -test('unicode emojis', function(t) { - [ - ['nice job 💯 ❤️', '💯 ❤️'], - ['💚 good job 🎇', '💚 🎇'], - ['visit Brunei', ''], - ['visit Brunei 🇧🇳', '🇧🇳'], - ['visit Brunei 🇧🇳🇧🇳🇧🇳', '🇧🇳🇧🇳🇧🇳'] - ].forEach(function(a) { - var have = nlp(a[0]).match('#Emoji').out('normal'); - var msg = "have: '" + have + "' want: '" + a[1] + "'"; - t.equal(have, a[1], msg); - }); - t.end(); -}); - -test('emoticon emojis', function(t) { - [ - ['nice job :)', ':)'], - [';) good work', ';)'], - [';( oh no :(', ';( :('], - ['to be: that is th3 question', ''], - [' { - var terms = nlp(o.text).terms() - o.pos = o.pos.split(', ') - t.equal(terms.length, o.pos.length, 'tokenize#' + index) - - var equal = true - var msg = '' - for (var i = 0; i < o.pos.length; i++) { - var want = softMapping[o.pos[i]] - var term = terms.list[i].terms[0] - if (!term.tags[want]) { - equal = false - msg += " - '" + term.normal + "' " + want - break - } - } - t.ok(equal, msg + ' - "' + o.text + '"') - }) - t.end() -}) diff --git a/test/unit/tagger/people.test.js b/test/unit/tagger/people.test.js deleted file mode 100644 index 0faf6d442..000000000 --- a/test/unit/tagger/people.test.js +++ /dev/null @@ -1,34 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('people:', function(t) { - var doc = nlp('Mary is in the boat. Nancy is in the boat. Fred is in the boat. Jack is too.'); - var arr = doc.people().out('array'); - t.deepEqual(arr, ['mary', 'nancy', 'fred', 'jack'], 'people-easy'); - - doc = nlp('jean jacket. jean Slkje'); - arr = doc.people().out('array'); - t.deepEqual(arr, ['jean slkje'], 'people-context'); - - doc = nlp('The Bill was passed by James MacCarthur'); - arr = doc.people().out('array'); - t.deepEqual(arr, ['james maccarthur'], 'the-bill'); - - doc = nlp('Rod MacDonald bought a Rod'); - arr = doc.people().out('array'); - t.deepEqual(arr, ['rod macdonald',], 'the-rod-1'); - - doc = nlp('Rod L. MacDonald bought a lightening rod'); - arr = doc.people().out('array'); - t.deepEqual(arr, ['rod l macdonald',], 'the-rod-2'); - - doc = nlp('Matt \'the doctor\' Smith lasted three seasons.'); - arr = doc.people().out('array'); - t.deepEqual(arr, ['matt the doctor smith',], 'nickname-1'); - - doc = nlp('Randal Kieth Orton and Dwayne \'the rock\' Johnson had a really funny fight.'); - arr = doc.people().out('array'); - t.deepEqual(arr, ['randal kieth orton','dwayne the rock johnson',], 'nickname-2'); - - t.end(); -}); diff --git a/test/unit/tagger/single-word.test.js b/test/unit/tagger/single-word.test.js deleted file mode 100644 index 4c9af53d2..000000000 --- a/test/unit/tagger/single-word.test.js +++ /dev/null @@ -1,74 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('specific_noun :', function(t) { - [ - // ['five hundred feet', 'Value'], - // ['50 square feet', 'Value'], - // ['90 hertz', 'Value'], - // ['two books', 'Value'], - ['two hundred', 'Value'], - ['4 hundred and ten', 'Value'], - ['4 and a half million', 'Value'], - ['499 thousand', 'Value'], - ['499', 'Value'], - ['4,899', 'Value'], - - ['John Smith', 'Person'], - ['dr. John Smith', 'Person'], - ['John Smith jr.', 'Person'], - ['John Jacob Smith', 'Person'], - ['Jani K. Smith', 'Person'], - - ['asdfefs', 'Noun'], - ['octopus', 'Noun'], - ['tree', 'Noun'], - // ['i', 'Noun'], - - ['FBI', 'Organization'], - ['F.B.I.', 'Organization'], - ['Fun ltd.', 'Organization'], - ['Fun co', 'Organization'], - ['Smith & Rogers', 'Organization'], - ['Google', 'Organization'], - - ['tuesday', 'Date'], - ['february', 'Date'], - ['february fifth', 'Date'], - ['tuesday march 5th', 'Date'], - ['tuesday march 5th, 2015', 'Date'] - ].forEach(function(a) { - var r = nlp(a[0]); - - if (a[1] === 'Person') { - t.equal(r.people().out(), a[0], a[0] + ' - is_person'); - } else { - t.equal(r.people().out(), '', a[0] + ' - not-a-person'); - } - - if (a[1] === 'Place') { - t.equal(r.places().out(), a[0], a[0] + ' - is_place'); - } else { - t.equal(r.places().out(), '', a[0] + ' - not-a-place'); - } - - if (a[1] === 'Value') { - t.equal(r.values().noDates().out(), a[0], a[0] + ' - is_value'); - } else { - t.equal(r.values().noDates().out(), '', a[0] + ' - not-a-value'); - } - - if (a[1] === 'Date') { - t.equal(r.dates().out(), a[0], a[0] + ' - is_date'); - } else { - t.equal(r.dates().out(), '', a[0] + ' - not-a-date'); - } - - if (a[1] === 'Organization') { - t.equal(r.organizations().out(), a[0], a[0] + ' - is_organization'); - } else { - t.equal(r.organizations().out(), '', a[0] + ' - not-a-org'); - } - }); - t.end(); -}); diff --git a/test/unit/tagger/swears.test.js b/test/unit/tagger/swears.test.js deleted file mode 100644 index 0eb72992f..000000000 --- a/test/unit/tagger/swears.test.js +++ /dev/null @@ -1,28 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -//nsfw! - -test('swears:', function(t) { - var m = nlp('shit, i am tired').match('^#Expression'); - t.ok(m.found, 'swear-1'); - - m = nlp('the shit keeps piling up').match('the #Noun'); - t.ok(m.found, 'swear-2'); - - m = nlp('damn them all').match('^#Verb'); - t.ok(m.found, 'swear-3'); - - m = nlp('fuck the government').match('^#Verb'); - t.ok(m.found, 'swear-4'); - - // m = nlp('when hell freezes over').match('^when #Noun'); - // t.ok(m.found, 'swear-5'); - - // m = nlp('he fucked up').match('he #Verb #Particle'); - // t.ok(m.found, 'swear-6'); - - m = nlp('it is fucked up').match('is #Adjective #Adjective'); - t.ok(m.found, 'swear-7'); - - t.end(); -}); diff --git a/test/unit/tagger/tagCustom.test.js b/test/unit/tagger/tagCustom.test.js deleted file mode 100644 index 82fdcb5b8..000000000 --- a/test/unit/tagger/tagCustom.test.js +++ /dev/null @@ -1,10 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('tag-multiples:', function(t) { - var r = nlp('twas brillig in the doofgafoof.'); - r.match('brillig').tag(['Foo', 'Barr']); - t.ok(r.match('#Foo').found, 'tagged-foo'); - t.ok(r.match('#barr').found, 'tagged-barr'); - t.end(); -}); diff --git a/test/unit/tagger/tagWord.test.js b/test/unit/tagger/tagWord.test.js deleted file mode 100644 index 59dbbabdd..000000000 --- a/test/unit/tagger/tagWord.test.js +++ /dev/null @@ -1,71 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -//test a word from each file in ./data/** -test('pos from-lexicon', function(t) { - var arr = [ - ['toronto', 'City'], - ['mexico', 'Country'], - ['Jamaica', 'Country'], - ['legendary', 'Adjective'], - ['above', 'Adjective'], - ['moderate', 'Adjective'], - ['extreme', 'Adjective'], - ['august', 'Month'], - ['saturday', 'WeekDay'], - ['minute', 'Duration'], - ['valentines day', 'Holiday'], - ['ash wednesday', 'Holiday'], - ['really', 'Adverb'], - ['each', 'Determiner'], - ['voila', 'Expression'], - ['new england', 'Place'], - ['hers', 'Possessive'], - ['onto', 'Preposition'], - ['blvd', 'Place'], - ['belgian', 'Demonym'], - ['cactus', 'Singular'], - ['cacti', 'Plural'], - ['economy', 'Noun'], - ['engineer', 'Noun'], - ['clothing', 'Noun'], - ['duran duran', 'Organization'], - ['american express', 'Organization'], - ['brotherhood', 'Noun'], - ['oakland athletics', 'SportsTeam'], - ['jamie', 'Person'], - ['claire', 'FemaleName'], - ['arthur', 'MaleName'], - ['¥', 'Currency'], - ['pence', 'Currency'], - ['seven', 'Value'], - ['seventeen', 'Value'], - ['twenty', 'Value'], - ['thousand', 'Value'], - ['eighteenth', 'Value'], - ['tbsp', 'Unit'], - ['wrote', 'PastTense'], - ['write', 'Verb'], - ['survive', 'Verb'], - ['attempt', 'Verb'], - ['mc\'adams', 'LastName'], - ['Müller', 'LastName'], - ['muller', 'LastName'], - ['425-1231', 'PhoneNumber'], - ['823-425-1231', 'PhoneNumber'], - ['823 425-1231', 'PhoneNumber'], - ['(823) 425-1231', 'PhoneNumber'], - ['invest', 'Verb'], - ['investing', 'Verb'], - [`wallys'`, 'Possessive'], - [`JDI University'`, 'Organization'], - ['ocean', 'Noun'], - ['shiver', 'Verb'] - ]; - arr.forEach(function(a) { - var term = nlp(a[0]).list[0].terms[0]; - var msg = '\'' + term.normal + '\' has - ' + a[1] + ' (' + Object.keys(term.tags).join(',') + ')'; - t.equal(term.tags[a[1]], true, msg); - }); - t.end(); -}); diff --git a/test/unit/tagger/tagger.test.js b/test/unit/tagger/tagger.test.js deleted file mode 100644 index 156bbdbc7..000000000 --- a/test/unit/tagger/tagger.test.js +++ /dev/null @@ -1,117 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); -var pos_test = require('../lib/fns').pos_test; - -test('=Tagger=', function(T) { - T.test('pos-basic-tag:', function(t) { - [ - ['John is pretty', ['Person', 'Copula', 'Adjective']], - ['John was lofty', ['Person', 'Copula', 'Adjective']], - ['John Smith was lofty', ['FirstName', 'LastName', 'Copula', 'Adjective']], - ['asdfes was lofty', ['Noun', 'Copula', 'Adjective']], - ['asdfes lksejfj was lofty', ['Noun', 'Noun', 'Copula', 'Adjective']], - ['Spencer Kelly is in Canada', ['Person', 'Person', 'Copula', 'Preposition', 'Place']], - ['He is in Canada', ['Pronoun', 'Copula', 'Preposition', 'Place']], - ['5 red roses', ['Value', 'Adjective', 'Noun']], - // ['3 trains', ['Value', 'Noun']], - ['3 trainers', ['Value', 'Noun']], - ['5 buses', ['Value', 'Noun']], - ['101010101010101010101010101010101010101010', ['NumericValue']], - - ['walk the walk', ['Verb', 'Determiner', 'Noun']], - ['Peter the man', ['Person', 'Determiner', 'Noun']], - // ['book the flight', ['Verb', 'Determiner', 'Noun']], - - //slang, contractions - // ['u r nice', ['Pronoun', 'Copula', 'Adjective']], - ['canadian bacon', ['Demonym', 'Noun']], - ['canadian dollar', ['Currency', 'Currency']], - - //possessive rules - ['john lkjsdf\'s', ['Person', 'Possessive']], - ['john lkjsdf\'s house', ['Person', 'Possessive', 'Noun']], - ['john Lkjsdf\'s house', ['Person', 'Possessive', 'Noun']], - ['john Lkjsdf\'s House', ['Person', 'Possessive', 'Noun']], - ['mark\'s question mark', ['Possessive', 'Noun', 'Noun']], - - //question-words - ['who is good?', ['QuestionWord', 'Copula', 'Adjective']], - ['which is good?', ['QuestionWord', 'Copula', 'Adjective']], - // ['bacon which is good', ['Noun', 'Pronoun', 'Copula', 'Adjective']], - // ['bacon which really is good', ['Noun', 'Pronoun', 'Adverb', 'Copula', 'Adjective']], - // ['Douglas who really is good', ['Person', 'Pronoun', 'Adverb', 'Copula', 'Adjective']], - - //web text things - ['lkj@fun.com', ['Email']], - ['j@f.ti', ['Email']], - ['j@ti', ['Noun']], - ['@ti', ['AtMention']], - ['#funtimes', ['HashTag']], - ['http://fun.com/cool?fun=yes', ['Url']], - ['#cool fun.com @cooman', ['HashTag', 'Url', 'AtMention']], - - //determiner-corrections - ['this rocks dude', ['Determiner', 'Verb', 'Noun']], - ['that rocks dude', ['Determiner', 'Verb', 'Noun']], - ['the rocks dude', ['Determiner', 'Plural', 'Noun']], - ['these rocks dude', ['Determiner', 'Plural', 'Noun']], - ['those rocks dude', ['Determiner', 'Plural', 'Noun']], - ['the test string', ['Determiner', 'Noun', 'Noun']], - - //people - ['John swim', ['Person', 'Verb']], - ['John, John', ['Person', 'Person']], - ['John, you', ['FirstName', 'Pronoun']], - ['John you', ['MaleName', 'Pronoun']], - ['you John you', ['Pronoun', 'Person', 'Pronoun']], - // ['10 + 9', ['Value', 'Symbol', 'Value']], - // ['2 * 90 = 180', ['Value', 'Symbol', 'Value', 'Symbol', 'Value']], - // ['one - seventy-six', ['Value', 'Symbol', 'Value']], - ['The stream runs', ['Determiner', 'Noun', 'Verb']], - ['The stream really runs', ['Determiner', 'Noun', 'Adverb', 'Verb']], - ['The nice stream really runs', ['Determiner', 'Adjective', 'Noun', 'Adverb', 'Verb']], - - ['he is walking', ['Pronoun', 'Copula', 'Gerund']], - ['walking is fun', ['Activity', 'Copula', 'Adjective']], - ['walking\'s great', ['Activity', 'Copula', 'Adjective']], - ['jack cheered', ['Person', 'PastTense']], - ['jack guarded', ['Person', 'PastTense']], - ['jack is guarded', ['Person', 'Copula', 'Adjective']], - ['jack seems guarded', ['Person', 'Verb', 'Adjective']], - //more - ['there are reasons', ['Noun', 'Copula', 'Plural']], - ['there were many walks', ['Noun', 'Copula', 'Adjective', 'Plural']], - ['there were the walks', ['Noun', 'Copula', 'Determiner', 'Noun']], - - ['it was fixed', ['Noun', 'Copula', 'PastTense']], - ['it will be boxed', ['Noun', 'Verb', 'Verb', 'PastTense']], - //ambiguous adverbs - ['it was pretty', ['Noun', 'Copula', 'Adjective']], - ['it was pretty cool', ['Noun', 'Copula', 'Adverb', 'Adjective']], - // ['it was really pretty cool', ['Noun', 'Copula', 'Adverb', 'Adverb', 'Adjective']], - ['it was just', ['Noun', 'Copula', 'Adjective']], - ['it was just gorgeous', ['Noun', 'Copula', 'Adverb', 'Adjective']], - - ['N.V.,', ['Noun']], - ['16.125', ['Cardinal']], - ['$19', ['Money']], - ['butterfly', ['Singular']], - ['he blamed the girl', ['Pronoun', 'PastTense', 'Determiner', 'Singular']], - ['his fine', ['Possessive', 'Noun']], - ['contracted AIDS', ['PastTense', 'Acronym']], - ['city/town', ['Noun', 'Noun']], - ['boyfriend to Jane', ['Noun', 'Conjunction', 'Person']], - // ['boyfriend of Jane', ['Noun', 'Conjunction', 'Person']], - ['his fines', ['Possessive', 'Noun']], - ['100+ rumours', ['Value', 'Plural']], - ['John & John,', ['Noun', 'Noun', 'Noun']], - - //abbreviations - ['col. Patrick said march and feb. etc.', ['Abbreviation', 'Person', 'PastTense', 'Month', 'Conjunction', 'Abbreviation', 'Abbreviation']] - ].forEach(function(a) { - var terms = nlp(a[0]).terms(); //.data(); - pos_test(terms, a[1], t); - }); - t.end(); - }); -}); diff --git a/test/unit/tagger/topics.test.js b/test/unit/tagger/topics.test.js deleted file mode 100644 index 1a5baefac..000000000 --- a/test/unit/tagger/topics.test.js +++ /dev/null @@ -1,26 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('proper-nouns', function(t) { - var arr = [ - ['I met John Smith in Toronto.', ['john smith', 'toronto']], - ['Toronto and Vancouver Canada.', ['toronto', 'vancouver canada']], - ['we ate shellfish at 23 Main st.', []], - ['google is suing motorola inc.', ['google', 'motorola inc']], - ['the doctor and his brother see the mayor of france', ['france']], - ]; - arr.forEach((a) => { - var out = nlp(a[0]).match('#ProperNoun+').out('array'); - t.deepEqual(out, a[1], a[0]); - }); - t.end(); -}); - -//after we change pos, untag propernoun -test('remove-proper-nouns', function(t) { - var doc = nlp('do what Theresa May'); - t.equal(doc.match('may').has('#ProperNoun'), true, 'propernoun-init'); - doc.match('may').tag('Verb'); - t.equal(doc.match('may').has('#ProperNoun'), false, 'propernoun-missing'); - t.end(); -}); diff --git a/test/unit/tagger/untag.test.js b/test/unit/tagger/untag.test.js deleted file mode 100644 index 3a3586eae..000000000 --- a/test/unit/tagger/untag.test.js +++ /dev/null @@ -1,68 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('tag inference:', function(t) { - var m = nlp('aasdf2').unTag('Noun').unTag('NounPhrase'); - var term = m.list[0].terms[0]; - t.equal(Object.keys(term.tags).length, 0, 'aasdf2 has no tags'); - //give it a specific tag- - m.tag('SportsTeam'); - term = m.list[0].terms[0]; - t.equal(term.tags.Noun, true, 'aasdf2 now has Noun'); - t.equal(term.tags.Organization, true, 'aasdf2 now has Organization(inferred)'); - //give it a redundant tag- - m.tag('Organization'); - term = m.list[0].terms[0]; - t.equal(term.tags.Noun, true, 'aasdf2 still has Noun'); - t.equal(term.tags.Organization, true, 'aasdf2 still has Organization'); - t.end(); -}); - -test('untag inference:', function(t) { - var m = nlp('aasdf'); - m.tag('FemaleName'); - var term = m.list[0].terms[0]; - t.equal(term.tags.FemaleName, true, 'aasdf first has FemaleName'); - t.equal(term.tags.Person, true, 'aasdf first has person'); - t.equal(term.tags.Noun, true, 'aasdf first has noun'); - //remove the assumption.. - term.unTag('Noun'); - t.equal(term.tags.Noun, undefined, 'aasdf now has no noun'); - t.equal(term.tags.Person, undefined, 'aasdf now has no person(inferred)'); - t.equal(term.tags.FemaleName, undefined, 'aasdf now has no FemaleName(inferred)'); - t.end(); -}); - -test('tag idempodence:', function(t) { - var m = nlp('walk').tag('Verb'); - var term = m.list[0].terms[0]; - t.equal(term.tags.Verb, true, 'walk has Verb'); - t.equal(term.tags.Value, undefined, 'walk has no Value'); - //untag irrelevant stuff - term.unTag('Value'); - term.unTag('Determiner'); - term.unTag('Country'); - term.unTag('Place'); - t.equal(term.tags.Verb, true, 'walk has Verb after'); - t.equal(term.tags.Value, undefined, 'walk has no Value after'); - t.end(); -}); - -test('tags are self-removing', function(t) { - var terms = ['Person', 'Place', 'PastTense', 'FemaleName', 'Infinitive', 'HashTag', 'Month']; - terms.forEach(function(tag) { - var m = nlp('aasdf').tag(tag).unTag(tag); - var t0 = m.list[0].terms[0]; - t.equal(t0.tags[tag], undefined, 'tag removes self ' + tag); - }); - t.end(); -}); - -test('untag wildcard', function(t) { - var r = nlp('we live in Toronto Canada and it is cold'); - r.match('#Place+').unTag('*'); - t.equal(r.match('#Place').found, false, 'place-tag-is-gone'); - var term = r.list[0].terms[3]; - t.equal(Object.keys(term.tags).length, 0, 'toronto-has-no-tags-now'); - t.end(); -}); diff --git a/test/unit/tagger/web.test.js b/test/unit/tagger/web.test.js deleted file mode 100644 index e78910afa..000000000 --- a/test/unit/tagger/web.test.js +++ /dev/null @@ -1,68 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('=Web Terminology=', function(T) { - T.test('is-email:', function(t) { - [ - [`s@s.com`, true], - [`sasdf@sasdf.com`, true], - [`sasdf@sasdf.ti`, true], - [`sasdf@sasdf.t`], - [`sasdf@sasdft`], - [`sasdfsasdft.com`], - [`@sasdft.com`], - [`_@_.com`, true], - [`_@_._`], - [`sas df@sasdf.com`], - [`sasdf@sa sdf.com`] - ].forEach(function(a) { - var term = nlp(a[0]).list[0].terms[0]; - var msg = a[0] + ' is email: ' + a[1]; - t.equal(term.tags['Email'], a[1], msg); - }); - t.end(); - }); - - T.test('is-hashtag:', function(t) { - [ - [`#lkjsdf`, true], - [`#ll`, true], - [`#22ll`, true], - [`#_22ll`, true], - // [`#l`,], - [`# l`], - [`l#l`] - ].forEach(function(a) { - var term = nlp(a[0]).list[0].terms[0]; - var msg = a[0] + ' is hashtag: ' + a[1]; - t.equal(term.tags['HashTag'], a[1], msg); - }); - t.end(); - }); - - T.test('is-url:', function(t) { - [ - [`http://cool.com/fun`, true], - [`https://cool.com`, true], - [`https://cool.com/`, true], - [`https://www.cool.com/`, true], - [`http://subdomain.cool.com/`, true], - [`www.fun.com/`, true], - [`www.fun.com`, true], - [`www.fun.com/foobar/fun`, true], - [`www.subdomain.cool.com/`, true], - [`wwwsubdomain.cool.com/`, true], - [`woo.br`, true], - [`woohoo.biz`, true], - [`woop.org/news`, true], - [`http://woop.org/news?foo=bar`, true], - [`http:subdomain.cool.com/`], - [`coolcom`] - ].forEach(function(a) { - var term = nlp(a[0]).list[0].terms[0]; - var msg = a[0] + ' is url: ' + a[1]; - t.equal(term.tags['Url'], a[1], msg); - }); - t.end(); - }); -}); diff --git a/test/unit/term/hyphens.test.js b/test/unit/term/hyphens.test.js deleted file mode 100644 index 4c541ca34..000000000 --- a/test/unit/term/hyphens.test.js +++ /dev/null @@ -1,52 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('hyphen-tokenize', function(t) { - var r = nlp('super-cool work'); - t.equal(r.terms().length, 3, 'super, cool'); - t.equal(r.out('text'), 'super-cool work', 'preserve hyphen'); - t.equal(r.out('normal'), 'super cool work', 'normalize-out hyphen'); - - r = nlp('http://about.com/my-summer-vacation'); - t.equal(r.terms().length, 1, 'url hyphen'); - r = nlp('http://about.com/my-summer'); - t.equal(r.terms().length, 1, 'url hyphen2'); - - r = nlp('421-0059'); - t.equal(r.terms().length, 1, 'phoneNuumber hyphen'); - - r = nlp('sept-2'); - t.equal(r.terms().length, 2, 'date hyphen'); - - r = nlp('-2 degrees'); - t.equal(r.terms().length, 2, 'minus hyphen'); - - r = nlp('re-enactment'); - t.equal(r.out('normal'), 'reenactment', 're-hyphen'); - r = nlp('un-do'); - t.equal(r.out('normal'), 'undo', 'un-hyphen'); - - t.end(); -}); - -test('hyphenate', function(t) { - var str = 'it is cool. he is nice'; - var m = nlp(str); - m.hyphenate(); - t.equal(m.terms().length, 6, 'seperate terms'); - t.equal(m.out('text'), 'it-is-cool. he-is-nice', 'hyphenate'); - m.dehyphenate(); - t.equal(m.out('text'), str, 'dehyphenate'); - - str = 'i payed seven-hundred for the sandwich'; - m = nlp(str); - m.values().dehyphenate(); - t.equal(m.out('text'), 'i payed seven hundred for the sandwich', 'dehyphenate-values'); - - str = 'he is the king of rock. she is the queen of cool.'; - m = nlp(str); - m.match('(king|queen) of (#Noun|#Adjective)').hyphenate(); - t.equal(m.out('text'), 'he is the king-of-rock. she is the queen-of-cool.', 'hyphenate-match'); - - t.end(); -}); diff --git a/test/unit/term/term_negate.test.js b/test/unit/term/term_negate.test.js deleted file mode 100644 index 64fb9e16a..000000000 --- a/test/unit/term/term_negate.test.js +++ /dev/null @@ -1,30 +0,0 @@ -var test = require('tape'); -var nlp = require('../lib/nlp'); - -test('verb negate:', function(t) { - [ - ['is', 'is not'], - ['will', 'will not'], - ['will be', 'will not be'], - ['was', 'was not'], - - ['walks', 'does not walk'], - ['walked', 'did not walk'], - // ['walking', 'not walking'], - // ['walk', 'do not walk'], - ['will walk', 'will not walk'], - ['will have walked', 'will not have walked'], - - // ['corrupted', 'did not corrupt'], - ['jumped', 'did not jump'], - ['stunk up', 'did not stink up'], - - [`would study`, `would not study`], - [`could study`, `could not study`], - [`should study`, `should not study`] - ].forEach(function(a) { - var str = nlp(a[0]).verbs().toNegative().out('normal'); - t.equal(str, a[1], a[1] + ' --- ' + str); - }); - t.end(); -}); diff --git a/tests/_backlog/backlog.ignore.js b/tests/_backlog/backlog.ignore.js new file mode 100644 index 000000000..cd74e4ac5 --- /dev/null +++ b/tests/_backlog/backlog.ignore.js @@ -0,0 +1,95 @@ +const test = require('tape') +const nlp = require('../_lib') + +// test('match-from-object :', function(t) { +// const m = nlp('spencer is really cool').match({ +// spencer: true, +// }) +// t.equal(m.out('normal'), 'spencer', 'just-spencer') +// t.equal(m.length, 1, 'one-result') +// t.end() +// }) + +/* +test('replace-capture-group', function(t) { + const m = nlp('John eats glue').replace('john [#Verb]', 'sniffs') + t.equal(m.out('text'), 'John sniffs glue', 'capture-2-simple') + // + // m = nlp('John eats glue. john is fun.').replace('[john]', '$1 smith'); + // t.equal(m.out('text'), 'John smith eats glue. john smith is fun.', 'capture-group-multiple'); + // + // m = nlp('John Smith eats glue').replace('[#Person+]', 'dr. $1'); + // t.equal(m.out('text'), 'dr. John Smith eats glue', 'capture-two'); + // + // m = nlp('ralf eats the glue').replace('ralf [#Verb]', 'he $1'); + // t.equal(m.out('text'), 'he eats the glue', 'simple subset'); + // + // m = nlp('John eats the glue').replace('the [#Noun]', 'the cyber-$1'); + // t.equal(m.out('text'), 'John eats the cyber-glue', 'capture-group as subset'); + // + t.end() +}) +*/ + +//test object-form +// test('not-from-object :', function(t) { +// const m = nlp('spencer is not really cool.') +// const r = m.not({ +// not: true, +// really: true, +// }) +// t.equal(m.out('normal'), 'spencer is not really cool.', 'double-obj-remains') +// t.equal(r.out('normal'), 'spencer is cool.', 'spencer-double-obj') + +// m = nlp('everyone is cool. I said hi to everyone.').not({ +// everyone: true, +// totally: true, +// }) +// t.equal(m.out('normal'), 'is cool. i said hi to', 'not-everyone') + +// m = nlp('spencer is really, secretly, very cool.') +// const adv = m.match('#Adverb').not({ +// really: true, +// }) +// t.equal(adv.out('normal'), 'secretly very', 'not-subset') +// t.equal(adv.length, 2, 'one-result-obj') + +// const adv2 = m.match('#Adverb').not('secretly') +// t.equal(adv2.out('normal'), 'really very', 'not-subset2') +// t.equal(adv2.length, 2, 'two-results-obj') + +// t.end() +// }) + +// test('normalize quotes ', function(t) { +// const str = `،one’ «two» ‘three’ “four” 'five' "six."` +// const doc = nlp(str) +// t.equal(doc.text(), str, 'text out-3') +// t.equal(doc.text(), 'one two three four five six.', 'normal out-3') +// t.end() +// }) + +// test('false-positives', function(t) { +// const txt = `Probably the renovation right away from the amount of work, which has been done to the property. +// I have one two, three, four five six properties, which came on the market in the month. +// I think that the number one quite comfortable looking at the two properties, which I'm working on now.` +// const questions = nlp(txt) +// .sentences() +// .isQuestion() +// .out('array') +// t.equal(questions.length, 0, 'no questions here') +// t.end() +// }) + +// let r = nlp('Homer, have you been eating that sandwich again?') +// .terms() +// .slice(0, 3) +// t.equal(r.out('text'), 'Homer, have you', 'result.slice') + +// str = 'men go' +// m = nlp(str) +// .sentences() +// .toPastTense() +// .nouns() +// .toSingular() +// t.equal(m.out('normal'), 'a man went', str) diff --git a/tests/_backlog/clone.ignore.js b/tests/_backlog/clone.ignore.js new file mode 100644 index 000000000..6f7ea54cb --- /dev/null +++ b/tests/_backlog/clone.ignore.js @@ -0,0 +1,34 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('nlp.clone() -change original', function(t) { + let nlp2 = nlp.clone() + t.ok(nlp('bat').has('#Noun'), 'nlp1-init') + t.ok(nlp2('bat').has('#Noun'), 'nlp2-init') + + //change nlp1 + nlp.extend((Doc, world) => { + world.addWords({ + bat: 'Man', + }) + }) + t.ok(nlp('bat').has('#Man'), 'nlp1-changed') + t.ok(nlp2('bat').has('#Man') === false, 'nlp2-unchanged') + + //change nlp2 + nlp2.extend((Doc, world) => { + world.addWords({ + bat: 'ManTwo', + }) + }) + t.ok(nlp('bat').has('#ManTwo') === false, 'nlp1-changed') + t.ok(nlp2('bat').has('#ManTwo') === true, 'nlp2-unchanged') + + //try nlp3 + let nlp3 = nlp.clone() + t.ok(nlp3('bat').has('#Noun'), 'nlp3-normal-default') + t.ok(nlp3('bat').has('#Man') === false, 'nlp3-normal') + t.ok(nlp3('bat').has('#ManTwo') === false, 'nlp3-normal-again') + + t.end() +}) diff --git a/tests/_backlog/pronoun.ignore.js b/tests/_backlog/pronoun.ignore.js new file mode 100644 index 000000000..3ae62801c --- /dev/null +++ b/tests/_backlog/pronoun.ignore.js @@ -0,0 +1,92 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('pronoun:', function(t) { + ;[ + ['John', 'he'], + ['John Smith', 'he'], + ['Jane', 'she'], + // ['turtle', 'it'], + // ['turtles', 'they'], + // ['Toronto', 'it'], + // ['studying', 'it'], + // ['horses', 'they'], + // ['road bikes', 'they'], + // ['NHL goaltenders', 'they'], + ['Tony Danza', 'he'], + ['Tanya Danza', 'she'], + ['Mrs. Tanya Danza', 'she'], + // ['John G. Fishermore Institute', 'it'], + // ['John Fisher & sons', 'it'], + ].forEach(function(a) { + const str = nlp(a[0]) + .people() + .pronoun()[0] + const msg = a[0] + ' -> ' + str + t.equal(str, a[1], msg) + }) + t.end() +}) + +// #Determiner, #Possessive - "his book", "her book", "their book", +// #Adjective, #Possessive - "the book is his", "the book is hers", "the book is theirs", +// #Pronoun, #Object - "the book belongs to him", "the book belongs to her", "the book belongs to them", and for completeness, +// #Pronoun, #Subject - "he owns the book", "she owns the book", "they own the book". + +test('to her:', function(t) { + let doc = nlp('her book belongs to her') //Det ... Pronoun + // her book... + let m = doc + .match('^her') + .match('#Determiner') + .match('#Possessive') + t.ok(m.found, 'her book - det/poss') + + // ...to her + m = doc + .match('her$') + .match('#Pronoun') + .match('#Possessive') + t.ok(m.found, 'to her - det/poss') + t.end() +}) + +test('to him:', function(t) { + let doc = nlp('his book belongs to him') //Det ... Pronoun + // his book... + let m = doc + .match('^hi') + .match('#Determiner') + .match('#Possessive') + t.ok(m.found, 'him book - det/poss') + + // ...to him + m = doc + .match('him$') + .match('#Pronoun') + .match('#Possessive') + t.ok(m.found, 'to him - det/poss') + t.end() +}) + +test('is his forms:', function(t) { + let doc = nlp('his book is his') //Det ... Adjective + //...is his + let m = doc + .match('his$') + .match('#Adjective') + .match('#Possessive') + t.ok(m.found, 'is his - adj/poss') + t.end() +}) + +test('is his forms:', function(t) { + let doc = nlp('her book is hers') //Det ... Adjective + //...is hers + let m = doc + .match('hers$') + .match('#Adjective') + .match('#Possessive') + t.ok(m.found, 'is hers - adj/poss') + t.end() +}) diff --git a/tests/_backlog/toAdjective.ignore.js b/tests/_backlog/toAdjective.ignore.js new file mode 100644 index 000000000..73a6e0a34 --- /dev/null +++ b/tests/_backlog/toAdjective.ignore.js @@ -0,0 +1,19 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('verb-to-adjective:', function(t) { + let arr = [ + ['walk', 'walkable'], + ['sing', 'singable'], + ['win', 'winnable'], + ['convert', 'convertible'], + ['see', 'visible'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .verbs() + .asAdjective()[0] + t.equal(str, a[1], str + ' -> ' + a[1]) + }) + t.end() +}) diff --git a/tests/_lib.js b/tests/_lib.js new file mode 100644 index 000000000..f260b728f --- /dev/null +++ b/tests/_lib.js @@ -0,0 +1,11 @@ +if (typeof process !== undefined && typeof module !== undefined) { + let nlp + if (process.env.TESTENV === 'prod') { + console.warn('== production build test 🚀 ==') + nlp = require('../') + } else { + nlp = require('../src') + } + + module.exports = nlp +} diff --git a/tests/_pennSample.js b/tests/_pennSample.js new file mode 100644 index 000000000..65f7ced8e --- /dev/null +++ b/tests/_pennSample.js @@ -0,0 +1,325 @@ +//(very) small subset of the Penn-treebank that should always pass +module.exports = [ + { + text: + 'Dr. Talcott led a team of researchers from the National Cancer Institute and the medical schools of Harvard University and Boston University.', + tags: 'NNP, NNP, VBD, DT, NN, IN, NNS, IN, DT, NNP, NNP, NNP, CC, DT, JJ, NNS, IN, NNP, NNP, CC, NNP, NNP', + }, + { + text: 'The monthly sales have been setting records every month since March.', + tags: 'DT, JJ, NNS, VBP, VBN, VBG, NNS, DT, NN, IN, NNP', + }, + { + text: ' Cray Computer will be a concept stock, he said.', + tags: 'NNP, NNP, MD, VB, DT, NN, NN, PRP, VBD', + }, + { + text: 'Esso said the Whiting field started production Tuesday.', + tags: 'NNP, VBD, DT, NNP, NN, VBD, NN, NNP', + }, + { + text: 'Pick a country, any country.', + tags: 'VB, DT, NN, DT, NN', + }, + { + text: 'They fell into oblivion after the 1929 crash.', + tags: 'PRP, VBD, IN, NN, IN, DT, CD, NN', + }, + { + text: 'Political and currency gyrations can whipsaw the funds.', + tags: 'JJ, CC, NN, NNS, MD, VB, DT, NNS', + }, + { + text: 'They cite a lack of imbalances that provide early warning signals of a downturn.', + tags: 'PRP, VBP, DT, NN, IN, NNS, WDT, VBP, JJ, NN, NNS, IN, DT, NN', + }, + { + text: 'Characters drink Salty Dogs, whistle Johnny B. Goode and watch Bugs Bunny reruns.', + tags: 'NNS, VBP, NNP, NNP, VBP, NNP, NNP, NNP, CC, VBP, NNP, NNP, NNS', + }, + { + text: 'They read Mickey Spillane and talk about Groucho and Harpo.', + tags: 'PRP, VBP, NNP, NNP, CC, VBP, IN, NNP, CC, NNP', + }, + { + text: ' Consider Jim Courter.', + tags: 'VB, NNP, NNP', + }, + { + text: 'But it resists yielding political ground.', + tags: 'CC, PRP, VBZ, VBG, JJ, NN', + }, + { + text: ' In Asia, as in Europe, a new order is taking shape, Mr. Baker said.', + tags: 'IN, NNP, IN, IN, NNP, DT, JJ, NN, VBZ, VBG, NN, NNP, NNP, VBD', + }, + { + text: 'And South Carolina says it is getting results.', + tags: 'CC, NNP, NNP, VBZ, PRP, VBZ, VBG, NNS', + }, + { + text: " It was full of violence and gangs and kids cutting class, says Linda Ward, the school's principal.", + tags: 'PRP, VBD, JJ, IN, NN, CC, NNS, CC, NNS, VBG, NN, VBZ, NNP, NNP, DT, NN, NN', + }, + { + text: 'I believe in the system.', + tags: 'PRP, VBP, IN, DT, NN', + }, + { + text: 'Mrs. Yeargin declined.', + tags: 'NNP, NNP, VBD', + }, + { + text: 'Yeargin won widespread local support.', + tags: 'NNP, VBD, JJ, JJ, NN', + }, + { + text: 'But Learning Materials matched on 66.5 of 69 subskills.', + tags: 'CC, NNP, NNPS, VBD, IN, CD, IN, CD, NNS', + }, + { + text: 'The two banks merged in 1985.', + tags: 'DT, CD, NNS, VBD, IN, CD', + }, + { + text: "He said the company's core business remains strong.", + tags: 'PRP, VBD, DT, NN, NN, NN, VBZ, JJ', + }, + { + text: 'Estimated volume was a moderate 3.5 million ounces.', + tags: 'VBN, NN, VBD, DT, JJ, CD, CD, NNS', + }, + { + text: 'Mr. Gillespie at Viacom says the ratings are rising.', + tags: 'NNP, NNP, IN, NNP, VBZ, DT, NNS, VBP, VBG', + }, + { + text: 'Ad Notes....', + tags: 'NNP, NNPS', + }, + { + text: 'The business had been handled by VanSant Dugdale, Baltimore.', + tags: 'DT, NN, VBD, VBN, VBN, IN, NNP, NNP, NNP', + }, + { + text: ' The economy is clearly slowing, says Robert Black, president of the Richmond Federal Reserve Bank.', + tags: 'DT, NN, VBZ, RB, VBG, VBZ, NNP, NNP, NN, IN, DT, NNP, NNP, NNP, NNP', + }, + { + text: 'They will mature Dec. 21.', + tags: 'PRP, MD, VB, NNP, CD', + }, + { + text: 'Lancaster Colony Corp. said it acquired Reames Foods Inc. in a cash transaction.', + tags: 'NNP, NNP, NNP, VBD, PRP, VBD, NNP, NNP, NNP, IN, DT, NN, NN', + }, + { + text: 'NL is officially making the offer.', + tags: 'NNP, VBZ, RB, VBG, DT, NN', + }, + { + text: "The Japanese fret openly about the U.S. public's rancor.", + tags: 'DT, NNP, NN, RB, IN, DT, NNP, NN, NN', + }, + { + text: 'They operate ships and banks.', + tags: 'PRP, VBP, NNS, CC, NNS', + }, + { + text: + 'Adds Takeshi Kondo, senior vice president of C. Itoh America Inc.: We have a great interest in making investments, particularly in new ventures.', + tags: 'VBZ, NNP, NNP, JJ, NN, NN, IN, NNP, NNP, NNP, NNP, PRP, VBP, DT, JJ, NN, IN, VBG, NNS, RB, IN, JJ, NNS', + }, + { + text: 'But many banks are turning away from strict price competition.', + tags: 'CC, JJ, NNS, VBP, VBG, RB, IN, JJ, NN, NN', + }, + { + text: 'One big reason: thin margins.', + tags: 'CD, JJ, NN, JJ, NNS', + }, + { + text: 'Buy a new Chevrolet.', + tags: 'VB, DT, JJ, NNP', + }, + { + text: 'Buy a diamond necklace.', + tags: 'VB, DT, NN, NN', + }, + { + text: 'They are keeping a close watch on the yield on the S&P 500.', + tags: 'PRP, VBP, VBG, DT, JJ, NN, IN, DT, NN, IN, DT, NNP, CD', + }, + { + text: 'In fact, the market has always tanked.', + tags: 'IN, NN, DT, NN, VBZ, RB, VBN', + }, + { + text: 'Always.', + tags: 'RB', + }, + { + text: 'China pulled out of the program in July.', + tags: 'NNP, VBD, VB, IN, DT, NN, IN, NNP', + }, + { + text: 'But regulators are wary.', + tags: 'CC, NNS, VBP, JJ', + }, + { + text: 'He also is a consensus manager, insiders say.', + tags: 'PRP, RB, VBZ, DT, NN, NN, NNS, VBP', + }, + { + text: 'Compromises are possible.', + tags: 'NNS, VBP, JJ', + }, + { + text: 'The company acknowledges some problems.', + tags: 'DT, NN, VBZ, DT, NNS', + }, + { + text: + 'A number of cities including Minneapolis, Philadelphia and Houston have vacant grain elevators, Eggers says.', + tags: 'DT, NN, IN, NNS, VBG, NNP, NNP, CC, NNP, VBP, JJ, NN, NNS, NNP, VBZ', + }, + { + text: + 'They suffered from malnutrition, chest diseases, cardiovascular disorders, skin problems, infectious diseases and the aftereffects of assaults and rape.', + tags: 'PRP, VBD, IN, NN, NN, NNS, JJ, NNS, NN, NNS, JJ, NNS, CC, DT, NNS, IN, NNS, CC, NN', + }, + { + text: 'That was the law.', + tags: 'DT, VBD, DT, NN', + }, + { + text: 'It was censorship.', + tags: 'PRP, VBD, NN', + }, + { + text: 'It was outrageous.', + tags: 'PRP, VBD, JJ', + }, + { + text: 'But the court disagreed.', + tags: 'CC, DT, NN, VBD', + }, + { + text: 'The man was Charles Z. Wick.', + tags: 'DT, NN, VBD, NNP, NNP, NNP', + }, + { + text: ' Bob has handled the extraordinary growth of the company quite brilliantly, said Mr. Newhouse.', + tags: 'NNP, VBZ, VBN, DT, JJ, NN, IN, DT, NN, RB, RB, VBD, NNP, NNP', + }, + { + text: + 'This species of congressional action is predicated on an interpretation of the appropriations clause that is erroneous and unconstitutional.', + tags: 'DT, NN, IN, JJ, NN, VBZ, VBN, IN, DT, NN, IN, DT, NNS, NN, WDT, VBZ, JJ, CC, JJ', + }, + { + text: 'President Reagan learned that lesson.', + tags: 'NNP, NNP, VBD, DT, NN', + }, + { + text: 'Mr. Sidak served as an attorney in the Reagan administration.', + tags: 'NNP, NNP, VBD, IN, DT, NN, IN, DT, NNP, NN', + }, + { + text: 'The death of the Herald, a newsstand paper in a freeway town, was perhaps inevitable.', + tags: 'DT, NN, IN, DT, NNP, DT, NN, NN, IN, DT, NN, NN, VBD, RB, JJ', + }, + { + text: ' The Herald was a survivor from a bygone age, said J. Kendrick Noble, a media analyst with PaineWebber Inc.', + tags: 'DT, NNP, VBD, DT, NN, IN, DT, JJ, NN, VBD, NNP, NNP, NNP, DT, NNS, NN, IN, NNP, NNP', + }, + { + text: 'The reaction in the newsroom was emotional.', + tags: 'DT, NN, IN, DT, NN, VBD, JJ', + }, + { + text: + 'The program traders, on the other hand, portray old-fashioned stock pickers as the Neanderthals of the industry.', + tags: 'DT, NN, NNS, IN, DT, JJ, NN, VBP, JJ, JJ, NN, NNS, IN, DT, NNS, IN, DT, NN', + }, + { + text: 'Reducing volatility.', + tags: 'VBG, NN', + }, + { + text: 'Ballot watchers say attention already is focused on the 1990 elections.', + tags: 'NN, NNS, VBP, NN, RB, VBZ, VBN, IN, DT, CD, NNS', + }, + { + text: 'Colleges, she says, are eyeing registration through 900 service.', + tags: 'NNS, PRP, VBZ, VBP, VBG, NN, IN, CD, NN', + }, + { + text: 'FAMILY PETS are improving recovery rates of patients at Columbia Hospital, Milwaukee.', + tags: 'NN, NNS, VBP, VBG, NN, NNS, IN, NNS, IN, NNP, NNP, NNP', + }, + { + text: 'The appointment takes effect Nov. 13.', + tags: 'DT, NN, VBZ, NN, NNP, CD', + }, + { + text: 'Heiwado Co.', + tags: 'NNP, NNP', + }, + { + text: 'Guaranteed by Svenska Handelsbanken.', + tags: 'VBN, IN, NNP, NNP', + }, + { + text: 'Mitsubishi Pencil Co.', + tags: 'NNP, NNP, NNP', + }, + { + text: 'Koizumi Sangyo Corp.', + tags: 'NNP, NNP, NNP', + }, + { + text: 'A stadium craze is sweeping the country.', + tags: 'DT, NN, NN, VBZ, VBG, DT, NN', + }, + { + text: 'Stock prices closed higher in Stockholm, Amsterdam and Frankfurt and lower in Zurich.', + tags: 'NN, NNS, VBD, JJR, IN, NNP, NNP, CC, NNP, CC, JJR, IN, NNP', + }, + { + text: 'A faster version, the SuperDot, was launched in 1984.', + tags: 'DT, JJR, NN, DT, NNP, VBD, VBN, IN, CD', + }, + { + text: 'Valley Federal is currently being examined by regulators.', + tags: 'NNP, NNP, VBZ, RB, VBG, VBN, IN, NNS', + }, + { + text: 'Columbia has only about 10 million common shares in public hands.', + tags: 'NNP, VBZ, RB, IN, CD, CD, JJ, NNS, IN, JJ, NNS', + }, + { + text: 'But the concept is workable.', + tags: 'CC, DT, NN, VBZ, JJ', + }, + { + text: "Mr. Spiegel's next career move is a subject of speculation on Wall Street.", + tags: 'NNP, NNP, JJ, NN, NN, VBZ, DT, NN, IN, NN, IN, NNP, NNP', + }, + { + text: 'Wedtech management used the merit system.', + tags: 'NNP, NN, VBD, DT, NN, NN', + }, + { + text: 'Numerous other scandals, among them the ones at HUD, have the same characteristics as Wedtech.', + tags: 'JJ, JJ, NNS, IN, PRP, DT, NNS, IN, NNP, VBP, DT, JJ, NNS, IN, NNP', + }, + { + text: 'Railroad companies and some ports are reaping a sudden windfall of business.', + tags: 'NN, NNS, CC, DT, NNS, VBP, VBG, DT, JJ, NN, IN, NN', + }, + { + text: ' The recent rally in precious metals was a result of uncertainty and volatility in equities, he said.', + tags: 'DT, JJ, NN, IN, JJ, NNS, VBD, DT, NN, IN, NN, CC, NN, IN, NNS, PRP, VBD', + }, +] diff --git a/tests/abbreviation.test.js b/tests/abbreviation.test.js new file mode 100644 index 000000000..e02f53451 --- /dev/null +++ b/tests/abbreviation.test.js @@ -0,0 +1,16 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('abbreviations', function(t) { + let doc = nlp(`mr. and Mrs. Kelly live on Shoreditch st.`) + doc.abbreviations().stripPeriods() + t.equal(doc.text(), 'mr and Mrs Kelly live on Shoreditch st.', 'no-periods') + + doc + .abbreviations() + .addPeriods() + .addPeriods() + t.equal(doc.text(), 'mr. and Mrs. Kelly live on Shoreditch st.', 'one-period') + + t.end() +}) diff --git a/tests/acronym.test.js b/tests/acronym.test.js new file mode 100644 index 000000000..93632cf28 --- /dev/null +++ b/tests/acronym.test.js @@ -0,0 +1,16 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('acronyms', function(t) { + let doc = nlp(`mr. and Mrs. Smith are in the FBI and the c.i.a.`) + doc.acronyms().stripPeriods() + t.equal(doc.text(), 'mr. and Mrs. Smith are in the FBI and the cia.', 'no-periods') + + doc + .acronyms() + .addPeriods() + .addPeriods() + t.equal(doc.text(), 'mr. and Mrs. Smith are in the F.B.I and the c.i.a.', 'one-period') + + t.end() +}) diff --git a/tests/append.test.js b/tests/append.test.js new file mode 100644 index 000000000..23d65c972 --- /dev/null +++ b/tests/append.test.js @@ -0,0 +1,74 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('append parent', function(t) { + let doc = nlp(`one two three`) + doc.append('four five') + t.equal(doc.text(), 'one two three four five', 'appended in parent') + t.end() +}) + +test('append one child', function(t) { + let doc = nlp(`one two three`) + let m = doc.match('three') + m.append('four five') + t.equal(doc.text(), 'one two three four five', 'appended in parent') + t.end() +}) + +test('append multi', function(t) { + let doc = nlp('one two. three four') + doc.append('oooo') + t.equal(doc.text(), 'one two oooo. three four oooo') + t.end() +}) + +test('append two children', function(t) { + let doc = nlp(`one two three`) + let m = doc.match('two three') + let m2 = m.match('three') + m2.append('four five') + t.equal(m.text('normal'), 'two three four five', 'append in child 1') + t.equal(m2.text('normal'), 'three four five', 'append in child 2') + t.equal(doc.text(), 'one two three four five', 'appended in parent') + t.end() +}) + +test('append in middle', function(t) { + let doc = nlp(`one two three six`) + let m = doc.match('three').append('four five') + t.equal(m.text('normal'), 'three four five', 'append in child 1') + t.equal(doc.text(), 'one two three four five six', 'inserted in parent') + t.end() +}) + +test('append in middle many children', function(t) { + let doc = nlp(`one two three six`) + let mx = doc + .match('one two three') + .match('three') + .match('.') + .match('three') + mx.append('four five') + t.equal(mx.text('normal'), 'three four five', 'append in child n') + t.equal(doc.text(), 'one two three four five six', 'inserted in parent') + t.end() +}) + +test('append check false-positives', function(t) { + let doc = nlp(`one two three five`) + let one = doc.match('one') + let twoThree = doc.match('two three') + let noFour = doc.match('four') + let five = doc.match('five') + doc.match('three').append('four') + t.equal(one.text('normal'), 'one', 'not in one') + t.equal(twoThree.text('normal'), 'two three', 'not in twoThree') + t.equal(noFour.text('normal'), '', 'still no four') + t.equal(five.text('normal'), 'five', 'not in five') + t.equal(doc.text(), 'one two three four five', 'inserted in parent') + t.equal(doc.match('four').text('normal'), 'four', 'now has four') + t.equal(doc.match('four five').text('normal'), 'four five', 'now has four-five') + t.equal(doc.match('. four').text('normal'), 'three four', 'now has three four') + t.end() +}) diff --git a/tests/bestTag.test.js b/tests/bestTag.test.js new file mode 100644 index 000000000..0f19d7ba7 --- /dev/null +++ b/tests/bestTag.test.js @@ -0,0 +1,36 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('bestTag', function(t) { + let str = 'john smith was really working' + let m = nlp(str) + let have = m + .terms() + .json({ terms: { bestTag: true } }) + .map(p => p.terms[0].bestTag) + let want = ['MaleName', 'LastName', 'Copula', 'Adverb', 'Gerund'] + let msg = str + ' - [' + have.join(', ') + ']' + t.deepEqual(have, want, msg) + + str = 'he sang in June' + m = nlp(str) + have = m + .terms() + .json({ terms: { bestTag: true } }) + .map(p => p.terms[0].bestTag) + want = ['Pronoun', 'PastTense', 'Preposition', 'Month'] + msg = str + ' - [' + have.join(', ') + ']' + t.deepEqual(have, want, msg) + + str = 'fastest shooter in Canada' + m = nlp(str) + have = m + .terms() + .json({ terms: { bestTag: true } }) + .map(p => p.terms[0].bestTag) + want = ['Superlative', 'Singular', 'Preposition', 'Country'] + msg = str + ' - [' + have.join(', ') + ']' + t.deepEqual(have, want, msg) + + t.end() +}) diff --git a/tests/canBe.test.js b/tests/canBe.test.js new file mode 100644 index 000000000..ceb96e673 --- /dev/null +++ b/tests/canBe.test.js @@ -0,0 +1,18 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('canBe', function(t) { + let doc = nlp(`spencer was going crazy. He walks quickly.`) + + let canBeNoun = doc.canBe('Noun') + t.equal(canBeNoun.length, 2, 'two results') + t.equal(canBeNoun.terms(0).text('normal'), 'spencer', 'first result') + t.equal(canBeNoun.terms(1).text(), 'He', 'first result') + + let canBeVerb = nlp('spencer kelly').canBe('Verb') + t.equal(canBeVerb.length, 0, 'no results') + + let canBeMisc = nlp('spencer kelly').canBe('asdf') + t.equal(canBeMisc.length, 1, 'all results are one') + t.end() +}) diff --git a/tests/case.test.js b/tests/case.test.js new file mode 100644 index 000000000..a1d16ee11 --- /dev/null +++ b/tests/case.test.js @@ -0,0 +1,52 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('sanity-check case:', function(t) { + let str = 'John xoo, John fredman' + let r = nlp(str) + str = r.toUpperCase().out('text') + t.equal(str, 'JOHN XOO, JOHN FREDMAN', 'uppercase') + + str = r.toLowerCase().out('text') + t.equal(str, 'john xoo, john fredman', 'lowercase') + + str = r.toCamelCase().out('text') + t.equal(str, 'johnXooJohnFredman', 'camelcase') //removes comma + t.end() +}) + +test('camel case:', function(t) { + let doc = nlp('and check this out! a walk-in microwave.') + doc.hyphenated().toCamelCase() + t.equal(doc.text(), 'and check this out! a walkIn microwave.', 'hyphenated-camelcase') + t.end() +}) + +test('tricky case:', function(t) { + let str = 'i am spencer kelly here with Amy Adams.' + let r = nlp(str) + r.match('#Person').toUpperCase() + str = r.out('text') + t.equal(str, 'i am SPENCER KELLY here with AMY ADAMS.', 'tricky-uppercase') + + str = 'the Spencer Kelly Festival of Silly Walks' + r = nlp(str) + r.match('@titleCase+').toCamelCase() + t.equal(r.out('text'), 'the SpencerKellyFestival of SillyWalks', 'tricky-camelcase') + + t.end() +}) + +test('unicode case:', function(t) { + let doc = nlp(`ümasdfs`) + doc.toTitleCase() + t.equal(doc.text(), 'Ümasdfs', 'unicode-titlecase') + + doc = nlp(`Ümasdfs`) + doc.toUpperCase() + t.equal(doc.text(), 'ÜMASDFS', 'unicode-uppercase') + doc.toLowerCase() + t.equal(doc.text(), 'ümasdfs', 'unicode-lowercase') + + t.end() +}) diff --git a/tests/celebrity-names.test.js b/tests/celebrity-names.test.js new file mode 100644 index 000000000..5ccf94610 --- /dev/null +++ b/tests/celebrity-names.test.js @@ -0,0 +1,159 @@ +const test = require('tape') +const nlp = require('./_lib') + +//list of famous names taken from https://gate.ac.uk/gate/plugins/ANNIE/resources/gazetteer/ +const tests = { + 'john stewart': 'Male', + 'martha stewart': 'Female', + // 'Gaugin': 'Male', + // 'Gauguin': 'Male', + 'George Bush': 'Male', + 'Hillary Clinton': 'Female', + 'Hillary Rodham Clinton': 'Female', + // 'John the Baptist': 'Male', + 'Margaret Thatcher': 'Female', + Messiaen: 'Male', + Mozart: 'Male', + Nixon: 'Male', + 'Pope John Paul II': 'Male', + 'Richard Nixon': 'Male', + 'Ronald Reagan': 'Male', + 'Saddam Hussain': 'Male', + 'Saint - Saens': 'Male', + // 'Shostakovich': 'Male', + // 'Strauss': 'Male', + // 'Thatcher': 'Female', + // 'The Queen': 'Female', + // 'the Queen': 'Female', + 'Van Gogh': 'Male', + 'Virgin Mary': 'Female', + Vivaldi: 'Male', + 'van Gogh': 'Male', + 'Carl Marx': 'Male', + Lenin: 'Male', + Stalin: 'Male', + 'George W.Bush': 'Male', + 'Mitt Romney': 'Male', + 'Barack Obama': 'Male', + Obama: 'Male', + 'Lady Gaga': 'Female', + 'Kanye West': 'Male', + 'Abu Hamza': 'Male', + 'Abu Hamza Al - Masri': 'Male', + 'Osama bin Laden': 'Male', + 'Osama Bin Laden': 'Male', + Mubarek: 'Male', + 'Muhammad Ali': 'Male', + 'Jennifer Aniston': 'Female', + 'Tyra Banks': 'Female', + 'Mario Batali': 'Male', + 'David Beckham': 'Male', + 'Halle Berry': 'Female', + 'Tom Brady': 'Male', + 'Matthew Broderick': 'Male', + 'Nathan Lane': 'Male', + 'Mel Brooks': 'Male', + 'Dan Brown': 'Male', + 'Jerry Bruckheimer': 'Male', + 'Kobe Bryant': 'Male', + 'Gisele Bundchen': 'Female', + 'Jim Carrey': 'Male', + 'Dave Chappelle': 'Male', + 'Sean Combs': 'Male', + 'Katie Couric': 'Female', + 'Simon Cowell': 'Male', + 'Tom Cruise': 'Male', + 'Johnny Depp': 'Male', + 'Cameron Diaz': 'Female', + 'Leonardo DiCaprio': 'Male', + 'Celine Dion': 'Female', + 'Jodie Foster': 'Female', + 'John Grisham': 'Male', + 'Tom Hanks': 'Male', + 'Paris Hilton': 'Female', + 'Eric Idle': 'Male', + 'Mike Nichols': 'Male', + 'Peter Jackson': 'Male', + 'LeBron James': 'Male', + 'Derek Jeter': 'Male', + 'Scarlett Johansson': 'Female', + 'Elton John': 'Male', + 'Angelina Jolie': 'Female', + 'Michael Jordan': 'Male', + 'Nicole Kidman': 'Female', + 'Heidi Klum': 'Female', + 'Emeril Lagasse': 'Male', + 'Jay Leno': 'Male', + 'David Letterman': 'Male', + 'Adriana Lima': 'Female', + 'Rush Limbaugh': 'Male', + 'George Lopez': 'Male', + 'Jennifer Lopez': 'Female', + 'George Lucas': 'Male', + 'Paul McCartney': 'Male', + 'Dr. Phil McGraw': 'Male', + 'Phil Mickelson': 'Male', + 'Kate Moss': 'Female', + 'Neil Diamond': 'Male', + "Bill O'Reilly": 'Male', + "Shaquille O'Neal": 'Male', + 'Carson Palmer': 'Male', + 'James Patterson': 'Male', + 'Ty Pennington': 'Male', + 'Regis Philbin': 'Male', + 'Brad Pitt': 'Male', + 'Wolfgang Puck': 'Male', + 'Rachael Ray': 'Female', + 'Nicole Richie': 'Female', + 'Alex Rodriguez': 'Male', + 'Ray Romano': 'Male', + Ronaldo: 'Male', + 'Valentino Rossi': 'Male', + 'J.K. Rowling': 'Female', + 'Adam Sandler': 'Male', + 'Diane Sawyer': 'Female', + 'Michael Schumacher': 'Male', + 'Ryan Seacrest': 'Male', + 'Jerry Seinfeld': 'Male', + 'Maria Sharapova': 'Female', + 'Jessica Simpson': 'Female', + 'Will Smith': 'Male', + 'Annika Sorenstam': 'Female', + 'Steven Spielberg': 'Male', + 'Bruce Springsteen': 'Male', + 'Howard Stern': 'Male', + 'Rod Stewart': 'Male', + 'Kiefer Sutherland': 'Male', + 'Donald Trump': 'Male', + 'Rick Warren': 'Male', + 'Denzel Washington': 'Male', + 'Sardinia F Jones': 'Female', + 'Andrew Lloyd Webber': 'Male', + 'Michelle Wie': 'Female', + 'Serena Williams': 'Female', + 'Venus Williams': 'Female', + 'Oprah Winfrey': 'Female', + 'Reese Witherspoon': 'Female', + 'Dick Wolf': 'Male', + 'Tiger Woods': 'Male', + 'Renee Zellweger': 'Female', + 'Whitney Houston': 'Female', + 'Adolf Hitler': 'Male', + 'Shania Twain': 'Female', + 'Hulk Hogan': 'Male', + 'Michelle Obama': 'Female', + 'Ashton Kutcher': 'Male', + 'Cardinal Wolsey': 'Male', + 'Slobodan Milosevic': 'Male', +} + +test('celebrity names:', function(t) { + Object.keys(tests).forEach(function(k) { + const str = nlp(k) + .people() + .text() + const msg = "'" + k + "' is a person - - have: '" + str + "'" + t.equal(str, k, msg) + }) + t.end() +}) diff --git a/tests/clause.test.js b/tests/clause.test.js new file mode 100644 index 000000000..9a941724c --- /dev/null +++ b/tests/clause.test.js @@ -0,0 +1,48 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('clauses-parentheses:', function(t) { + let m = nlp("i said, 'did you have to do that' and then left, like nothing happened (which it didn't).").clauses() + t.equal(m.length, 5, 'found 5 clauses') + t.equal(m.eq(0).text(), 'i said', 'clause 1') + t.equal(m.eq(1).text(), `did you have to do that`, 'clause 2') + t.equal(m.eq(2).text(), `and then left`, 'clause 3') + t.equal(m.eq(3).text(), `like nothing happened`, 'clause 4') + t.equal(m.eq(4).text(), `which it didn't`, 'clause 5') + t.end() +}) + +test('clauses-commas:', function(t) { + let doc = nlp(`in Toronto, Canada`).clauses() + t.equal(doc.length, 1, 'place-comma') + + // doc = nlp(`July 4, 1776`).clauses() + // t.equal(doc.length, 1, 'date-comma') + + doc = nlp(`“You have a spider on your nose!” my friend yelled.`).clauses() + t.equal(doc.length, 2, 'found 2 clauses-1') + t.end() +}) + +test('clauses-condition:', function(t) { + let m = nlp('if you must, go to the basement').clauses() + t.equal(m.length, 2, 'found 2 clauses2') + t.equal(m.eq(0).text(), 'if you must', 'clause 1') + t.equal(m.eq(1).text(), `go to the basement`, 'clause 2') + t.end() +}) + +test('clauses-conjunction:', function(t) { + let m = nlp(`it is cool but it is not`).clauses() + t.equal(m.length, 2, 'found 2 clauses3') + t.equal(m.eq(0).text(), 'it is cool', 'clause 1') + t.equal(m.eq(1).text(), `but it is not`, 'clause 2') + t.end() +}) + +test('clauses-list:', function(t) { + let m = nlp('he is nice, cool and fun.').clauses() + t.equal(m.length, 1, 'found 1 clause') + t.equal(m.eq(0).text(), 'he is nice, cool and fun.', 'clause 1') + t.end() +}) diff --git a/tests/constructor.test.js b/tests/constructor.test.js new file mode 100644 index 000000000..d74ac7c9a --- /dev/null +++ b/tests/constructor.test.js @@ -0,0 +1,48 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('extra exports:', function(t) { + t.ok(nlp.version, 'version number exported') + + t.doesNotThrow(function() { + nlp.verbose(true) + nlp.verbose(false) + }, 'can set verbosity') + + t.end() +}) + +test('tokenize() runs without pos-tagging', function(t) { + const str = 'Miss Hoover, I glued my head to my shoulder.' + const r = nlp.tokenize(str) + t.equal(r.out('text'), str, 'tokenize output is same') + + t.equal(r.list.length, 1, 'sentence-parser-working') + + const found = r.match('#Noun').found + t.equal(found, false, 'no sneaky-tagging') + + t.end() +}) + +//make sure it can handle garbage inputs +test('garbage:', function(t) { + const garbage = ['', ' ', null, '\n\n', []] //{} + garbage.forEach(function(g, i) { + let num = nlp(g).list.length + let msg = typeof g + ' text input #' + i + t.equal(num, 0, msg) + }) + let str = nlp(2).out() + t.equal(str, '2', 'integer-casted') + str = nlp(2.2).out() + t.equal(str, '2.2', 'float-casted') + + //garbage in lexicon too + str = nlp('hello', null).out() + t.equal(str, 'hello', 'null-lexicon') + + str = nlp('hello', 2).out() + t.equal(str, 'hello', 'int-lexicon') + t.end() +}) diff --git a/tests/contractions/contract.test.js b/tests/contractions/contract.test.js new file mode 100644 index 000000000..b7e84eb5e --- /dev/null +++ b/tests/contractions/contract.test.js @@ -0,0 +1,64 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('contract basic', function(t) { + let r = nlp(`he is cool.`) + r.contract() + t.equal(r.out('text'), `he's cool.`, 'expanded-contract') + + r = nlp(`he's cool.`) + r.contract() + t.equal(r.out('text'), `he's cool.`, 'contracted-contract') + + r = nlp(`please do not eat the marshmellow`) + r.contract() + t.equal(r.out('text'), `please don't eat the marshmellow`, 'expanded-contract') + + r = nlp(`please don't eat the marshmellow`) + r.contract() + t.equal(r.out('text'), `please don't eat the marshmellow`, 'contracted-contract') + + r = nlp(`i have stood`) + r.contract() + t.equal(r.out('text'), `i've stood`, 'expanded-contract') + + r = nlp(`i've stood`) + r.contract() + t.equal(r.out('text'), `i've stood`, 'contracted-contract') + + r = nlp('i am good') + r.contract() + t.equal(r.out('text'), `i'm good`, 'contract-1') + r.contractions().expand() + t.equal(r.out('text'), `i am good`, 'expand-2') + r.contract() + t.equal(r.out('text'), `i'm good`, 'contract-2') + + r.contractions() + .contract() + .contract() + .contract() + t.equal(r.out('text'), `i'm good`, 'contract-n') + + t.end() +}) + +test('avoid contraction messes', function(t) { + let doc = nlp('Tony, is').contract() + t.equal(doc.text('reduced'), 'tony is', 'avoid-contraction 1') + + doc = nlp('(Tony) is').contract() + t.equal(doc.text('reduced'), 'tony is', 'avoid-contraction 2') + + doc = nlp(`'Tony' is`).contract() + t.equal(doc.text('reduced'), 'tony is', 'avoid-contraction 3') + + doc = nlp('Tony-is').contract() + t.equal(doc.text('reduced'), 'tony is', 'avoid-contraction 4') + + doc = nlp(`Tony +is`).contract() + t.equal(doc.text('reduced'), 'tony is', 'avoid-contraction 5') + + t.end() +}) diff --git a/tests/contractions/contraction.test.js b/tests/contractions/contraction.test.js new file mode 100644 index 000000000..1c9d40a52 --- /dev/null +++ b/tests/contractions/contraction.test.js @@ -0,0 +1,28 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('match contractions/possessives', function(t) { + let doc = nlp(`i think it's spencer's`) + t.equal(doc.has('it'), true, 'has it') + t.equal(doc.has('spencer'), true, 'has spencer') + t.equal(doc.has(`spencer's`), true, "has spencer's") + t.equal(doc.has(`i'm`), false, 'not false-positive') + t.equal(doc.has(`it'll`), false, 'not false-positive-2') + t.end() +}) + +test('contraction whitespace', function(t) { + let doc = nlp(`i didn't know.`) + t.equal(doc.text(), `i didn't know.`, 'init-whitespace') + + doc.contractions().expand() + t.equal(doc.text(), `i did not know.`, 'expanded-whitespace') + + doc = nlp(`i didn't.`) + t.equal(doc.text(), `i didn't.`, 'init-period') + + doc.contractions().expand() + t.equal(doc.text(), `i did not.`, 'expanded-period') + + t.end() +}) diff --git a/tests/contractions/expand.test.js b/tests/contractions/expand.test.js new file mode 100644 index 000000000..6643d3a69 --- /dev/null +++ b/tests/contractions/expand.test.js @@ -0,0 +1,94 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('basic is contractions', function(t) { + let r = nlp(`he is cool.`) + r.contractions().expand() + t.equal(r.out('text'), `he is cool.`, 'expanded-expand') + + r = nlp(`he's cool.`) + r.contractions().expand() + t.equal(r.out('text'), `he is cool.`, 'contracted-expand') + + r = nlp(`that's really great.`) + r.contractions().expand() + t.equal(r.out('text'), `that is really great.`, 'contracted-expand') + + r = nlp(`she'll, eat icecream`) + r.contractions().expand() + t.equal(r.out('text'), `she will, eat icecream`, 'with-punctuation') + + r = nlp("we're not gonna take it, no we're not gonna take it") + r.contractions().expand() + t.equal(r.out('text'), `we are not going to take it, no we are not going to take it`, 'expand gonna twice') + + r = nlp("we're we're gonna gonna") + r.contractions().expand() + t.equal(r.out('text'), `we are we are going to going to`, 'expand consecutive') + t.end() +}) + +test('do-not contractions', function(t) { + let r = nlp(`please do not eat the marshmellow`) + r.contractions().expand() + t.equal(r.out('text'), `please do not eat the marshmellow`, 'expanded-expand') + + r = nlp(`please don't eat the marshmellow`) + r.contractions().expand() + t.equal(r.out('text'), `please do not eat the marshmellow`, 'contracted-expand') + + t.end() +}) + +test('have contractions', function(t) { + let r = nlp(`i have stood`) + r.contractions().expand() + t.equal(r.out('text'), `i have stood`, 'expanded-expand') + + r = nlp(`i've stood`) + r.contractions().expand() + t.equal(r.out('text'), `i have stood`, 'contracted-expand') + + t.end() +}) + +test('repeated contract-expand', function(t) { + let r = nlp(`i'm good`) + r.contractions().expand() + + r.contractions() + .expand() + .expand() + .expand() + t.equal(r.out('text'), `i am good`, 'expand-n') + t.end() +}) + +test('contracted', function(t) { + let r = nlp(`I'll go to Toronto. I will see.`) + let m = r.contractions() + let str = m.out('text') + t.equal(str, `I'll`, 'contracted') + + t.equal(m.length, 1, 'no-expanded') + t.end() +}) + +test('would-or-did', function(t) { + let r = nlp(`i'd contemplate`) + let str = r + .contractions() + .expand() + .all() + .out('text') + t.equal(str, `i would contemplate`, 'i-would') + + r = nlp(`i'd contemplated`) + str = r + .contractions() + .expand() + .all() + .out('text') + t.equal(str, `i had contemplated`, 'i-had') + t.end() +}) diff --git a/tests/emoji.test.js b/tests/emoji.test.js new file mode 100644 index 000000000..ddd667372 --- /dev/null +++ b/tests/emoji.test.js @@ -0,0 +1,72 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('keyword emojis', function(t) { + ;[ + ['he is so nice :heart:', ':heart:'], + [':cool: :wine_glass: yeah party', ':cool: :wine_glass:'], + ['to be or not to be: this is a question :cookie:', ':cookie:'], + ].forEach(function(a) { + const have = nlp(a[0]) + .match('#Emoji') + .text() + .trim() + const msg = "have: '" + have + "' want: '" + a[1] + "'" + t.equal(have, a[1], msg) + }) + t.end() +}) + +test('unicode emojis', function(t) { + ;[ + ['nice job 💯 ❤️', '💯 ❤️'], + ['💚 good job 🎇', '💚 🎇'], + ['visit Brunei', ''], + ['visit Brunei 🇧🇳', '🇧🇳'], + ['visit Brunei 🇧🇳🇧🇳🇧🇳', '🇧🇳🇧🇳🇧🇳'], + ].forEach(function(a) { + const have = nlp(a[0]) + .match('#Emoji') + .out('normal') + const msg = "have: '" + have + "' want: '" + a[1] + "'" + t.equal(have, a[1], msg) + }) + t.end() +}) + +test('emoticon emojis', function(t) { + ;[ + ['nice job :)', ':)'], + [';) good work', ';)'], + [';( oh no :(', ';( :('], + ['to be: that is th3 question', ''], + ['{ nlp.tokenize("you\'re sure you haven\'t just made thousands of mistakes?") }', + extend: "()=>{ nlp.extend((Doc, world)=>world.addWords({bort:'FirstName'})) }", + clone: "()=>{ let b=nlp.clone(); b.extend((Doc, world)=>{world.addWords({ 'a hoy hoy' : 'Greeting'})}) }", + load: "()=>{ let json=nlp('Tony Hawk').export();nlp.load(json).match('#Person') }", + verbose: "()=>{ nlp.verbose(false);nlp('I am the very model of a modern Major-General') }", + version: '()=>{ nlp.version}', + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('utils api', function(t) { + const fns = { + all: "()=>{ nlp('this is yelling').match('#Verb').toTitleCase().all().text() }", + found: "()=>{ nlp('oh say can you see?').match('see').found }", + parent: '()=>{ }', + parents: '()=>{ }', + tagger: '()=>{ }', + wordCount: '()=>{ }', + length: "()=>{ nlp('jackie kennedy and aristotle onassis').match('#Person+').length }", + clone: "()=>{ nlp('would somebody please think of the children').clone().toUpperCase().parent().text() }", + cache: "()=>{ let doc=nlp(\"I'm looking for Amanda Hugginkiss\").cache({root:true});doc.match('~look~') }", + uncache: '()=>{ let doc=nlp("urine-soaked hell-hole").uncache();doc.tag("Insult") }', + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('accessors api', function(t) { + const fns = { + first: '()=>{ }', + last: '()=>{ }', + slice: "()=>{ nlp('Homer, have you been eating that sandwich again?').terms().slice(0, 3).text() }", + eq: '()=>{ }', + firstTerm: '()=>{ }', + lastTerm: '()=>{ }', + termList: '()=>{ }', + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('match api', function(t) { + const fns = { + match: "()=>{ nlp('we understand, we are from the land of chocolate.').match('land of #Noun').text() }", + not: "()=>{ nlp('wait, there’s a new mexico?').match('#Place').not('new').text() }", + matchOne: '()=>{ }', + if: "()=>{ nlp('We’re here, we’re clear, we don’t want anymore bears.').clauses().if('anymore').text() }", + ifNo: "()=>{ nlp('We’re here, we’re clear, we don’t want anymore bears.').clauses().ifNo('anymore').text() }", + has: "()=>{ nlp('I am the very model of a modern Major-General').has('#Pronoun') }", + lookBehind: '()=>{ }', + lookAhead: '()=>{ }', + before: "()=>{ nlp('one two three four five').before('three').text() }", + after: "()=>{ nlp('one two three four five').after('three').text() }", + lookup: "()=>{ nlp('chocolate microscopes? double guitars?').lookup(['double guitars']).length }", + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('case api', function(t) { + const fns = { + toUpperCase: "()=>{ nlp('Dental plan. Lisa needs braces.').match('dental .').toUpperCase().text() }", + toLowerCase: "()=>{ nlp('Careful! They’re RUFFLED!!').toLowerCase().text() }", + toTitleCase: "()=>{ nlp('jupiter, pluto and mars').match('#Noun').toTitleCase().all().text() }", + toCamelCase: "()=>{ nlp('natural language processing').toCamelCase().text() }", + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('whitespace api', function(t) { + const fns = { + pre: '()=>{ nlp("we\'re here. we\'re clear. we don\'t want anymore bears.").pre(" ") }', + post: "()=>{ nlp(\"we're here. we're clear. we don't want anymore bears.\").post('!') }", + trim: "()=>{ nlp(' Lenny and Carl ').match('#Person').trim().text() }", + hyphenate: "()=>{ nlp('natural language processing').hyphenate().text() }", + dehyphenate: "()=>{ nlp('natural-language processing').dehyphenate().text() }", + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('tag api', function(t) { + const fns = { + tag: + "()=>{ nlp('Michael Apple ate a delicious apple.').match('#FirstName apple').tag('Person').all().match('#Person+').text() }", + tagSafe: '()=>{ }', + unTag: + "()=>{ nlp('they made a catch & scored a run').match('(run|catch)').unTag('#Verb').all().match('#Verb').out('array') }", + canBe: "()=>{ nlp('it’s fusilli jerry!').canBe('Person').text() }", + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('loops api', function(t) { + const fns = { + map: "()=>{ nlp('yahoo serious festival').terms().map((m)=> m.toUpperCase()).text() }", + forEach: "()=>{ nlp('Oh, no! Bette Midler!').match('#Person+').forEach((m,i)=> m.text()) }", + filter: "()=>{ nlp('Hey, anymore arboretum’s around here?').terms().filter(m => m.has('#Plural') ).length }", + find: + "()=>{ nlp('Always do the opposite of what bart says') .terms() .find(t => t.out('normal').match(/b[ao]rt/)) .text() }", + some: "()=>{ nlp('Don’t make me run, I’m full of chocolate!').terms().some(m => m.out('normal')==='run' )}", + random: "()=>{ nlp('one two three four').terms().random(2).out('array') }", + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('insert api', function(t) { + const fns = { + replaceWith: "()=>{ nlp('it was the worst of times').match('worst').replaceWith('blurst', true).all().text() }", + replace: "()=>{ nlp('trust me folks, big league.').replace('big league','bigly').all().text() }", + delete: "()=>{ nlp('you don’t win friends with salad').delete('do not').text() }", + append: "()=>{ nlp('i know so many words').insertAfter('bigly').all().text() }", + prepend: "()=>{ nlp('stupid flanders').match('flanders').insertBefore('sexy').all().text() }", + concat: "()=>{ nlp('My name is Otto').concat('and i love to get blotto').all().length }", + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('transform api', function(t) { + const fns = { + sort: "()=>{ nlp('Larry, Curly, Moe').terms().sort('alphabetical').out('array') }", + reverse: '()=>{ }', + normalize: + "()=>{ nlp(' so... you like DONUTS? have all the donuts in the WORLD!!!').normalize().all().get(0).text() }", + unique: '()=>{ }', + split: "()=>{ nlp('Monorail...Once again! Monorail... Monorail!').splitOn('monorail').eq(0).text() }", + splitAfter: "()=>{ nlp('Monorail...Once again! Monorail... Monorail!').splitAfter('monorail').eq(0).text() }", + splitBefore: "()=>{ nlp('Monorail...Once again! Monorail... Monorail!').splitBefore('monorail').eq(0).text()}", + segment: '()=>{ }', + join: '()=>{ }', + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('out api', function(t) { + const fns = { + text: "()=>{ nlp('you might say there’s a little Uter in all of us').match('#Adjective uter').out('array') }", + debug: '()=>{ }', + out: '()=>{ }', + json: + "()=>{ nlp('The stage was set for the Alan Parsons Project! Which I believe was some sort of hovercraft.').data() }", + + export: '()=>{ }', + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('selectors api', function(t) { + const fns = { + terms: "()=>{ nlp('we should all be more like little Ruttiger').terms().json() }", + clauses: + "()=>{ nlp('All right, Colossus, you’re free to go, but stay away from Death Mountain').clauses().data() }", + hyphenated: '()=>{ }', + phoneNumbers: "()=>{ nlp('Moe Sizlak. That’s right. I’m a surgeon. (800) 555-0000.').phoneNumbers().json() }", + hashTags: "()=>{ nlp('oh, but where is the #anykey').hashTags().json() }", + emails: '()=>{ }', + emoticons: '()=>{ }', + emoji: '()=>{ }', + atMentions: '()=>{ }', + urls: "()=>{ nlp('thank you http://simpsons.wikia.com').urls().json()}", + adverbs: '()=>{ }', + pronouns: '()=>{ }', + conjunctions: '()=>{ }', + prepositions: '()=>{ }', + abbreviations: '()=>{ }', + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) + +test('subsets api', function(t) { + const fns = { + contractions: '()=>{ }', + parentheses: "()=>{ nlp('Use a pointed stick (a pencil) or a similar tool').parentheses().data() }", + possessives: "()=>{ nlp('moe’s tavern').possessives().text() }", + quotations: '()=>{ nlp(\'the he said "crazy like a fox!".\').quotations().data().length }', + acronyms: '()=>{ }', + lists: '()=>{ }', + nouns: '()=>{ }', + verbs: `()=>{ nlp('Moe Sizlak. That’s right. I’m a surgeon.').verbs() }`, + } + Object.keys(fns).forEach(k => { + t.doesNotThrow(eval(fns[k]), k) + }) + t.end() +}) diff --git a/tests/hyphens.test.js b/tests/hyphens.test.js new file mode 100644 index 000000000..870d539f7 --- /dev/null +++ b/tests/hyphens.test.js @@ -0,0 +1,62 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('hyphen-tokenize', function(t) { + let r = nlp('super-cool work') + t.equal(r.terms().length, 3, 'super, cool') + t.equal(r.out('text'), 'super-cool work', 'preserve hyphen') + t.equal(r.out('normal'), 'super cool work', 'normalize-out hyphen') + + r = nlp('http://about.com/my-summer-vacation') + t.equal(r.terms().length, 1, 'url hyphen') + r = nlp('http://about.com/my-summer') + t.equal(r.terms().length, 1, 'url hyphen2') + + r = nlp('421-0059') + t.equal(r.terms().length, 1, 'phoneNuumber hyphen') + + r = nlp('sept-2') + t.equal(r.terms().length, 2, 'date hyphen') + + r = nlp('-2 degrees') + t.equal(r.terms().length, 2, 'minus hyphen') + + r = nlp('re-enactment') + t.equal(r.out('normal'), 'reenactment', 're-hyphen') + r = nlp('un-do') + t.equal(r.out('normal'), 'undo', 'un-hyphen') + + t.end() +}) + +test('hyphenate', function(t) { + let str = 'it is cool. he is nice' + let m = nlp(str) + m.hyphenate() + t.equal(m.terms().length, 6, 'seperate terms') + t.equal(m.out('text'), 'it-is-cool. he-is-nice', 'hyphenate') + m.dehyphenate() + t.equal(m.out('text'), str, 'dehyphenate') + + str = 'i payed seven-hundred for the sandwich' + m = nlp(str) + m.match('#Value').dehyphenate() + t.equal(m.out('text'), 'i payed seven hundred for the sandwich', 'dehyphenate-values') + + str = 'he is the king of rock. she is the queen of cool.' + m = nlp(str) + m.match('(king|queen) of (#Noun|#Adjective)').hyphenate() + t.equal(m.out('text'), 'he is the king-of-rock. she is the queen-of-cool.', 'hyphenate-match') + + t.end() +}) + +test('hasHyphen', function(t) { + let doc = nlp(`super-cool and hunky-dory. Connected with-a-dash.`) + let arr = doc.match('@hasHyphen+ .').out('array') + t.equal(arr.length, 3, 'three found') + t.equal(arr[0], 'super-cool', 'first found') + t.equal(arr[1], 'hunky-dory.', 'second found') + // t.equal(arr[2], 'with-a-dash', 'third found') //FIXME:hyphens + t.end() +}) diff --git a/tests/lists.test.js b/tests/lists.test.js new file mode 100644 index 000000000..b37f0a161 --- /dev/null +++ b/tests/lists.test.js @@ -0,0 +1,52 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('list-types', function(t) { + let doc = nlp('he is nice, cool, and really fun.').lists() + t.equal(doc.length, 1, 'found adj list') + t.equal(doc.things().length, 3, 'three adjs') + + doc = nlp('his sweat, blood, and tears').lists() + t.equal(doc.length, 1, 'found noun list') + t.equal(doc.things().length, 3, 'three nouns') + + doc = nlp('we ran, biked, swam, and then ate').lists() + t.equal(doc.length, 1, 'found verb list') + t.equal(doc.things().length, 4, 'four verbs') + + doc = nlp('there is Spencer Kelly, Donald Glover, and Justin Trudeau').lists() + t.equal(doc.length, 1, 'found person list') + t.equal(doc.things().length, 3, 'three people') + + t.end() +}) + +// test('support-2-part-list', function(t) { +// const doc = nlp('spencer is cool, and great. He is nice and tired.') +// let m = doc.lists() +// t.equal(m.length, 2, 'has two lists') +// t.end() +// }) + +test('muti-word things', function(t) { + const doc = nlp('spencer is nice, quite warm, and tired.') + let m = doc.lists() + t.equal(m.length, 1, 'has one list') + t.equal(m.things().length, 3, 'has three things') + t.end() +}) + +test('add', function(t) { + const doc = nlp('spencer is nice, warm and tired.') + doc.lists().add('CRAAZY') + t.equal(doc.text(), 'spencer is nice, warm, CRAAZY and tired.', 'without no-oxford') + t.end() +}) + +test('hasOxfordComma', function(t) { + const doc = nlp('spencer is cool, fun, and great. He is nice, tired and not smart.') + let m = doc.lists().hasOxfordComma() + t.equal(m.length, 1, 'only one has oxford-comma') + t.equal(m.text(), 'cool, fun, and great', 'first-one has oxford-comma') + t.end() +}) diff --git a/tests/load.test.js b/tests/load.test.js new file mode 100644 index 000000000..d7cb440cc --- /dev/null +++ b/tests/load.test.js @@ -0,0 +1,53 @@ +const test = require('tape') +const nlp = require('./_lib') + +// do an elaborate comparison between json objects +const isEqual = function(a, b, t) { + let jsonA = a.json() + let jsonB = b.json() + t.equal(a.length, b.length, 'same length') + t.equal(a.text(), b.text(), 'same text') + jsonA.forEach((o, i) => { + t.equal(o.text, jsonB[i].text, o.text) + t.equal(o.terms.length, jsonB[i].terms.length, 'terms-length ' + i) + o.terms.forEach(term => { + term.tags.forEach(tag => { + let p = b.eq(i) + t.equal(p.has('#' + tag), true, p.text() + ' has ' + tag) + }) + }) + }) +} + +test('load-export basic', function(t) { + let a = nlp('it was cold. John K. Smith was verrrrry cold ! ') + let b = nlp.load(a.export()) + isEqual(a, b, t) + t.end() +}) + +test('load-export-empty', function(t) { + let a = nlp('') + let b = nlp.load(a.export()) + isEqual(a, b, t) + + t.end() +}) + +test('load-export-garbage', function(t) { + let a = nlp('[]. oh yeah. function the null prototype. - \n "two| (time()7 77') + let b = nlp.load(a.export()) + isEqual(a, b, t) + + t.end() +}) + +test('export-unknown tag', function(t) { + let a = nlp('cookie monster was a boomer. ok boomer', { boomer: 'Generation' }) + a.match('. monster').tag('Character') + a.match('ok boomer').tag('Diss') + let json = a.export() + let b = nlp.load(json) + isEqual(a, b, t) + t.end() +}) diff --git a/tests/lookahead.test.js b/tests/lookahead.test.js new file mode 100644 index 000000000..d9fbc4c1e --- /dev/null +++ b/tests/lookahead.test.js @@ -0,0 +1,71 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('look-ahead', function(t) { + let doc = nlp(`i walked to a store today. the store was very nice`) + let m = doc.match('store').lookAhead('#Adjective') + t.deepEqual(m.out('array'), ['nice'], 'found all upcoming adjectives') + + let m2 = doc.match('store').lookAhead('.') + t.deepEqual(m2.out('array'), ['today.', 'was', 'very', 'nice'], 'found all upcoming words') + + let m3 = doc.match('store').lookAhead('farmer') + t.equal(m3.found, false, 'lookahead empty') + + let m4 = doc.match('nice').lookAhead('.') + t.equal(m4.found, false, 'lookahead on edge empty') + + let m5 = nlp('it is raining') + .match('raining') + .lookAhead() + t.equal(m5.found, false, 'lookahead at end empty') + + let m6 = nlp('it is raining today and tomorrow') + .match('raining') + .lookAhead() + t.equal(m6.text(), 'today and tomorrow', 'lookahead blank finds all') + + t.end() +}) + +test('lookahead from parent is blank', function(t) { + let doc = nlp('it is raining') + t.equal(doc.lookAhead('.').found, false, 'no after 1') + + doc = nlp('oh wow, it is raining. it is snowing? it is very cold.') + t.equal(doc.lookAhead('.').found, false, 'no after 1') + t.end() +}) + +test('look-behind', function(t) { + let doc = nlp(`i walked to a store. the store was very nice`) + let m = doc.match('store').lookBehind('#Determiner') + t.deepEqual(m.out('array'), ['a', 'the'], 'found previous determiners') + + let m2 = doc.match('store').lookBehind('.') + t.deepEqual(m2.out('array'), ['i', 'walked', 'to', 'a', 'the'], 'found all previous words') + + let m3 = doc.match('store').lookBehind('farmer') + t.equal(m3.found, false, 'lookbehind not found') + + let m4 = doc.match('i').lookBehind('.') + t.equal(m4.found, false, 'lookbehind on edge empty') + + let m6 = nlp('it is raining today and tomorrow') + .match('raining') + .lookBehind() + t.equal(m6.text(), 'it is', 'lookbehind blank finds all') + + t.end() +}) + +test('look-behind-last', function(t) { + let doc = nlp(`a priest walked into a bar`) + let m = doc + .match('bar') + .lookBehind('a') + .last() + m.replace('the') + t.equal(doc.text(), `a priest walked into the bar`, 'lookbehind most-recent') + t.end() +}) diff --git a/tests/lookup.test.js b/tests/lookup.test.js new file mode 100644 index 000000000..c0f1bd5c4 --- /dev/null +++ b/tests/lookup.test.js @@ -0,0 +1,16 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('lookup tests', function(t) { + let doc = nlp("he isn't AT Spencer's house of pain. The haunted house of not pain. Third sentence spencer.") + let m = doc.lookup(['house of pain', 'house of']) + t.equal(m.length, 3, 'found redundant match') + + m = doc.lookup(["spencer's"]) + t.equal(m.length, 1, 'found possessive lookup') + + m = doc.lookup('spencer') + t.equal(m.length, 2, 'end of line lookup') + + t.end() +}) diff --git a/tests/loop-mutate.test.js b/tests/loop-mutate.test.js new file mode 100644 index 000000000..e86883791 --- /dev/null +++ b/tests/loop-mutate.test.js @@ -0,0 +1,36 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('foreach replace', function(t) { + let doc = nlp('guns and roses') + doc.match('guns').forEach(p => { + p.replaceWith('flowers') + }) + t.equal(doc.text(), 'flowers and roses', 'simple loop-replace') + + doc = nlp('guns and roses. roses and guns') + doc.match('guns').forEach(p => { + p.replaceWith('flowers') + }) + t.equal(doc.text(), 'flowers and roses. roses and flowers', 'two loop-replacements') + + doc = nlp('guns and roses') + doc.match('guns').forEach(p => { + p.replaceWith('flowers, kittens') + }) + t.equal(doc.text(), 'flowers, kittens and roses', 'loop-replace-grow') + + doc = nlp('guns, bombs, and roses') + doc.match('guns bombs').forEach(p => { + p.replaceWith('flowers') + }) + t.equal(doc.text(), 'flowers, and roses', 'loop-replace-shrink') + + doc = nlp('the end') + doc.match('end').forEach(p => { + p.replaceWith('more words') + }) + t.equal(doc.text(), 'the more words', 'loop-replace-expand-end') + + t.end() +}) diff --git a/tests/loops.test.js b/tests/loops.test.js new file mode 100644 index 000000000..8f7e694ab --- /dev/null +++ b/tests/loops.test.js @@ -0,0 +1,88 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('map-stuff', function(t) { + let doc = nlp('and').map(d => { + return d.replaceWith('or') + }) + t.equal(doc.text(), 'or', 'replace-with') + + doc = nlp('one two three. three four five.').map(d => { + return d.match('three') + }) + t.equal(doc.eq(0).text(), 'three', 'match-one') + t.equal(doc.eq(1).text(), 'three', 'match-two') + + t.end() +}) + +test('foreach-stuff', function(t) { + let doc = nlp('one two three. three four five.').forEach(p => { + p.toUpperCase() + }) + t.equal(doc.out('text'), 'ONE TWO THREE. THREE FOUR FIVE.', 'foreach-uppercase') + t.end() +}) + +test('filter-stuff', function(t) { + let doc = nlp('one two three. three four five.').filter(p => { + return p.has('four') + }) + t.equal(doc.out('normal'), 'three four five.', 'filter-has') + + doc = nlp('one two three. three four five.') + .terms() + .filter(p => { + return p.has('four') + }) + t.equal(doc.out('normal'), 'four', 'filter-four') + + doc = nlp('one two three. three four five.') + .terms() + .filter(p => { + return p.has('asdf') + }) + t.equal(doc.out('normal'), '', 'empty-filter') + t.end() +}) + +test('find-stuff', function(t) { + let doc = nlp('one two three. three four five.').find(m => m.has('four')) + t.equal(doc && doc.out('normal') === 'three four five.', true, 'found four') + + doc = nlp('one two three. three four five.').find(m => m.has('asdf')) + t.equal(doc, undefined, 'undefined find result') + t.end() +}) + +test('some-stuff', function(t) { + let bool = nlp('one two three. three four five.').some(m => m.has('three')) + t.equal(bool, true, 'found-three') + + bool = nlp('one two three. three four five.').some(m => m.has('asdf')) + t.equal(bool, false, 'not-found') + t.end() +}) + +test('map array return', function(t) { + let doc = nlp('Larry, Curly, and Moe') + let people = doc.match('#Noun') // (any one noun) + people.sort('alpha') + let arr = people.map(d => d.text('normal')) + t.deepEqual(arr, ['curly, ', 'larry, ', 'moe'], 'got array in response') + t.end() +}) + +// test('reduce-stuff', function(t) { +// let doc = nlp('one two three. three four five.') +// .terms() +// .reduce((p, d) => { +// if (!p.has('two')) { +// return d +// } +// return null +// }) +// doc.debug() +// // t.equal(doc.out('text'), 'ONE TWO THREE. THREE FOUR FIVE.', 'foreach-uppercase') +// t.end() +// }) diff --git a/tests/match/and-operand.test.js b/tests/match/and-operand.test.js new file mode 100644 index 000000000..7fa041e20 --- /dev/null +++ b/tests/match/and-operand.test.js @@ -0,0 +1,43 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('and-match', function(t) { + let doc = nlp('june and july cool') + let m = doc.match('(#Date && july)') + t.equal(m.out(), 'july', 'found july') + + m = doc.match('(#Date && !july)') + t.equal(m.out(), 'june', 'found not july') + + m = doc.match('(and && !foo && #Conjunction && .)') + t.equal(m.out(), 'and', 'three-match') + + t.end() +}) + +test('and-match-more', function(t) { + let doc = nlp('toronto and montreal. Sydney and Paris.') + let m = doc.match('(#Place && .)') + t.equal(m.length, 4, 'found all four') + + m = doc.match('(#Place && /e/)') + t.equal(m.out(), 'montreal. Sydney', 'found e words') + + m = doc.match('(#Place && !#Verb)') + t.equal(m.length, 4, 'and not') + + m = doc.match('(#Place && #Verb)') + t.equal(m.length, 0, 'no and') + + m = doc.match('(#Place && #Noun && * && .{1,3})') + t.equal(m.length, 4, 'four towns') + + t.end() +}) + +// test('and-match-multi', function(t) { +// let doc = nlp('toronto and montreal. Sydney and Paris.') +// let m = doc.match('(#Place and && toronto .)') +// t.equal(m.out(), 'toronto and', 'found one multi') +// t.end() +// }) diff --git a/tests/match/before-after.test.js b/tests/match/before-after.test.js new file mode 100644 index 000000000..866393c25 --- /dev/null +++ b/tests/match/before-after.test.js @@ -0,0 +1,65 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('before-basic', function(t) { + let doc = nlp('one two three four five. one three four') + let arr = doc.before('three four').out('array') + t.equal(arr.length, 2, 'two-matches') + t.equal(arr[0], 'one two', 'first-match') + t.equal(arr[1], 'one', 'second-match') + + doc = nlp('one two three four five. one three four. three four') + arr = doc.before('three').out('array') + t.equal(arr.length, 2, 'two-matches') + t.equal(arr[0], 'one two', 'first-match') + t.equal(arr[1], 'one', 'second-match') + t.end() +}) + +test('before-match:', function(t) { + let r = nlp('one two three four five').before('two') + t.equal(r.out('normal'), 'one', 'before-two') + + r = nlp('one two three four five').before('three . five') + t.equal(r.out('normal'), 'one two', 'before-several') + + r = nlp('one two three four five').before('one two') + t.equal(r.out('normal'), '', 'no-before-start') + + // r = nlp('one two three four').before('.'); //tricky + // t.equal(r.out('normal'), '', 'before-any'); + + r = nlp('one two three four. No, not here. He said two days a week.').before('two') + let arr = r.out('array') + t.equal(arr[0], 'one', 'before-twice-1') + t.equal(arr[1], 'He said', 'before-twice-2') + + r = nlp('it was all the way over to two. It was the number two.').before('it') + t.equal(r.found, false, 'no-empty-matches') + + t.end() +}) + +test('after-match:', function(t) { + let r = nlp('one two three four five').after('two') + t.equal(r.out('normal'), 'three four five', 'after-one') + + r = nlp('one two three four five').after('one . three') + t.equal(r.out('normal'), 'four five', 'after-several') + + r = nlp('one two three four five').after('four five') + t.equal(r.out('normal'), '', 'no-afters-end') + + r = nlp('one two three four').after('.') + t.equal(r.out('normal'), 'two three four', 'after-any') + + r = nlp('one two three four. No, not here. He said two days a week.').after('two') + let arr = r.out('array') + t.equal(arr[0], 'three four.', 'after-twice-1') + t.equal(arr[1], 'days a week.', 'after-twice-2') + + r = nlp('all the way over to two. It was the number two.').after('two') + t.equal(r.found, false, 'no-empty-matches') + + t.end() +}) diff --git a/tests/match/capture.test.js b/tests/match/capture.test.js new file mode 100644 index 000000000..3c6ce8c58 --- /dev/null +++ b/tests/match/capture.test.js @@ -0,0 +1,40 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('match-capture-group', function(t) { + let m = nlp('John eats glue').match('[john]') + t.equal(m.out('text'), 'John', 'capture-group-simple') + + m = nlp('John Smith eats glue').match('[#Person+]') + t.equal(m.out('text'), 'John Smith', 'capture-two') + + m = nlp('ralf eats the glue').match('ralf [#Verb] the') + t.equal(m.out('normal'), 'eats', 'simple subset') + + m = nlp('ralf eats the glue').match('[ralf] [#Verb] the') + t.equal(m.out('normal'), 'ralf eats', 'two-word capture') + + m = nlp('i saw ralf eat the glue Mrs. Hoover').match('ralf [#Verb the glue] mrs') + t.equal(m.out('normal'), 'eat the glue', 'three-word capture') + + m = nlp('ralf eats the glue').match('* [#Verb]') + t.equal(m.out('normal'), 'eats', 'capture after wildcard') + + // m = nlp('ralf eats the glue').match('ralf eats [*]') + // t.equal(m.out('normal'), 'the glue', 'wildcard capture at the end') + + // m = nlp('ralf eats the glue').match('ralf eats [*] glue') + // t.equal(m.out('normal'), 'the', 'wildcard capture in the middle') + + m = nlp('saw the Toronto International Documentary Film Festival yesterday').match('saw the? [#Noun+] yesterday') + t.equal(m.trim().out('text'), 'Toronto International Documentary Film Festival', 'greedy capture') + + t.end() +}) + +test('tricky capture', function(t) { + let doc = nlp.tokenize('during august') + let m = doc.match('^(on|during|in) [.]') + t.equal(m.text('normal'), 'august', 'found capture') + t.end() +}) diff --git a/tests/match/doc-match.test.js b/tests/match/doc-match.test.js new file mode 100644 index 000000000..99a4dcc9e --- /dev/null +++ b/tests/match/doc-match.test.js @@ -0,0 +1,37 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('doc-as-input', function(t) { + let doc = nlp('if so, he is the best, that i see. he is the greatest') + let m = doc.match('he is the .') + let found = doc.match(m) + t.equal(found.length, 2, 'found both phrases') + t.equal(found.eq(0).text('reduced'), 'he is the best', 'found first match') + t.equal(found.eq(1).text('reduced'), 'he is the greatest', 'found second match') + t.end() +}) + +test('doc-sibling-as-input', function(t) { + let doc = nlp('he is the best, that i see. he is the greatest') + let childA = doc.if('greatest') + let childB = doc.match('he is') + let found = childA.match(childB) + t.equal(found.length, 1, 'found self in sibling') + //try false-positive example + childA = doc.if('foobar') + childB = doc.match('he is') + found = childA.match(childB) + t.equal(found.length, 0, 'false-positive not found') + t.end() +}) + +test('split-doc-input', function(t) { + let doc = nlp('he is the best, that i see. he is the greatest') + let childA = doc.if('greatest') + let childB = doc.match('he is') + let found = childA.splitAfter(childB) + t.equal(found.length, 2, 'split from sibling') + t.equal(found.eq(0).text('reduced'), 'he is', 'found first match') + t.equal(found.eq(1).text('reduced'), 'the greatest', 'found second match') + t.end() +}) diff --git a/tests/match/encoding.test.js b/tests/match/encoding.test.js new file mode 100644 index 000000000..728dac883 --- /dev/null +++ b/tests/match/encoding.test.js @@ -0,0 +1,70 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('encoding-match:', function(t) { + const r = nlp('it is * nice') + const str = r + .match('is \\*') + .trim() + .out() + t.equal(str, 'is *', 'encode asterix') + + // r = nlp('it is + nice'); + // str = r.match('is \\+ nice').trim().out(); + // t.equal(str, 'is + nice', 'encode plus'); + + t.end() +}) + +test('reserved-word-in-src:', function(t) { + const r = nlp('buy eggs constructor yeah prototype') + t.equal(r.has(`backburner`), false, 'single') + t.equal(r.has(`#Foo`), false, 'tag') + t.equal(r.has(`(upcoming|backburner)`), false, 'anyOf') + t.equal(r.has(`lala+`), false, 'manyOf') + t.equal(r.has(`nword{2,4}`), false, 'someOf') + t.end() +}) + +test('reserved-word-in-match:', function(t) { + const r = nlp('fo foo fulala repeat') + t.equal(r.has(`constructor`), false, 'single') + t.equal(r.has(`#constructor`), false, 'tag') + t.equal(r.has(`(upcoming|constructor)`), false, 'anyOf') + t.equal(r.has(`constructor+`), false, 'manyOf') + t.equal(r.has(`constructor{2,4}`), false, 'someOf') + t.end() +}) + +test('test-infinite-loop', function(t) { + const weirdDoc = nlp('^ ? * . + $') + weirdDoc.match('is?') + weirdDoc.match('.?') + weirdDoc.match('*') + weirdDoc.match('.+') + weirdDoc.match('+') + weirdDoc.match('?') + weirdDoc.match('.') + weirdDoc.match('? * . +') + weirdDoc.not('?') + weirdDoc.not('*') + weirdDoc.not('^') + weirdDoc.not('$') + weirdDoc.not('+') + weirdDoc.not('? * . +') + t.ok(true, 'didnt regress') + + let str = 'And you are?. Marshal' + let have = nlp(str) + .all() + .out() + t.equal(have, str, 'regression #1') + + str = `- where is she.Oh. you guys don't know?` + have = nlp(str) + .all() + .out() + t.equal(have, str, 'regression #2') + + t.end() +}) diff --git a/tests/match/fancy-match.test.js b/tests/match/fancy-match.test.js new file mode 100644 index 000000000..a171319aa --- /dev/null +++ b/tests/match/fancy-match.test.js @@ -0,0 +1,47 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('matchOne', function(t) { + let doc = nlp('one two three four five. one three four') + let arr = doc.matchOne('three four').out('array') + t.equal(arr.length, 1, 'one-match') + t.equal(arr[0], 'three four', 'found-match') + t.end() +}) + +test('match-from-array :', function(t) { + let m = nlp('spencer is really cool').match(['spencer']) + t.equal(m.out('normal'), 'spencer', 'just-spencer') + t.equal(m.length, 1, 'one-result') + + m = nlp('spencer is really cool').match([]) + t.equal(m.out('normal'), '', 'empty match') + t.equal(m.length, 0, 'zero-results') + + m = nlp('spencer is really cool') + let r = m.match(['spencer', 'really']).toUpperCase() + t.equal(r.out('text'), 'SPENCER REALLY', 'match-spencer-really') + t.equal(r.length, 2, 'two-results') + + t.equal(m.out('text'), 'SPENCER is REALLY cool', 'match-spencer-really') + t.equal(m.length, 1, 'still-one-result') + t.end() +}) + +test('greedy-capture', function(t) { + let m = nlp('so ralf and really eats the glue').match('* [eats] the') + t.equal(m.out('normal'), 'eats', 'one-captures') + + m = nlp('so ralf really, really eats the glue').match('[#Adverb+] eats the') + t.equal(m.out('normal'), 'really, really', 'greedy-capture') + + m = nlp('so ralf and really eats the glue').match('* [eats the]') + t.equal(m.out('normal'), 'eats the', 'two-captures') + + m = nlp('so ralf really eats the glue').match('really [eats the] *') + t.equal(m.out('normal'), 'eats the', 'astrix after') + + m = nlp('so ralf really eats the glue').match('really * [eats the]') + t.equal(m.out('normal'), 'eats the', 'astrix is not necessary') + t.end() +}) diff --git a/tests/match/has.test.js b/tests/match/has.test.js new file mode 100644 index 000000000..ee0218d66 --- /dev/null +++ b/tests/match/has.test.js @@ -0,0 +1,44 @@ +const test = require('tape') +const nlp = require('../_lib') + +let arr = [ + ['five hundred feet', 'Value'], + ['50 square feet', 'Value'], + ['90 hertz', 'Value'], + ['two books', 'Value'], + ['two hundred', 'Value'], + ['4 hundred and ten', 'Value'], + ['4 and a half million', 'Value'], + ['499 thousand', 'Value'], + ['499', 'Value'], + ['4,899', 'Value'], + ['John Smith', 'Person'], + ['dr. John Smith', 'Person'], + ['John Smith jr.', 'Person'], + ['John Jacob Smith', 'Person'], + ['Jani K. Smith', 'Person'], + ['asdfefs', 'Noun'], + ['octopus', 'Noun'], + ['tree', 'Noun'], + ['i', 'Noun'], + + ['FBI', 'Organization'], + ['F.B.I.', 'Organization'], + ['Fun ltd.', 'Organization'], + ['Fun co', 'Organization'], + ['Smith & Rogers', 'Organization'], + ['Google', 'Organization'], + ['tuesday', 'Date'], + ['february', 'Date'], + ['february fifth', 'Date'], + ['tuesday march 5th', 'Date'], + ['tuesday march 5th, 2015', 'Date'], +] + +test('has-test', function(t) { + arr.forEach(function(a) { + let doc = nlp(a[0]) + t.equal(doc.has('#' + a[1]), true, a[0]) + }) + t.end() +}) diff --git a/tests/match/if.test.js b/tests/match/if.test.js new file mode 100644 index 000000000..d6648b08a --- /dev/null +++ b/tests/match/if.test.js @@ -0,0 +1,32 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('if-basic:', function(t) { + let r = nlp('spencer is here') + let m = r.if('asdf') + t.equal(m.out('text'), '', 'if-negative') + + m = r.if('spencer') + t.equal(m.out('text'), 'spencer is here', 'if-positive') + + r = nlp('spencer is here. john was here.') + m = r.if('is') + t.equal(m.out('normal'), 'spencer is here.', 'if-partial') + + t.end() +}) + +test('ifNo:', function(t) { + let r = nlp('spencer is here') + let m = r.ifNo('spencer') + t.equal(m.out('text'), '', 'ifNo-positive') + + m = r.ifNo('asdf') + t.equal(m.out('text'), 'spencer is here', 'ifNo-negative') + + r = nlp('spencer is here. john was here.') + m = r.ifNo('is') + t.equal(m.out('normal'), 'john was here.', 'if-no-partial') + + t.end() +}) diff --git a/tests/match/insert.test.js b/tests/match/insert.test.js new file mode 100644 index 000000000..a64627d46 --- /dev/null +++ b/tests/match/insert.test.js @@ -0,0 +1,44 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('insert-basic :', function(t) { + let m = nlp('the dog sat').insertBefore('and') + t.equal(m.out('text'), 'and the dog sat', 'and-dog') + + m = nlp('the dog sat').insertAfter('patiently') + t.equal(m.out('text'), 'the dog sat patiently', 'sat-patiently') + + m = nlp('the dog sat') + m.match('dog').insertBefore('nice') + t.equal(m.out('text'), 'the nice dog sat', 'nice-dog') + + m = nlp('a dog sat') + m.match('sat').insertAfter('quickly') + t.equal(m.out('text'), 'a dog sat quickly', 'sat-quickly') + + m = nlp('a dog sat') + m.match('a dog sat').insertAfter('quickly') + t.equal(m.out('text'), 'a dog sat quickly', 'multi-match-quickly') + + m = nlp('a dog sat') + m.match('asdf').insertAfter('no no no') + t.equal(m.out('text'), 'a dog sat', 'no no no no') + + t.end() +}) + +test('insert-subset-include :', function(t) { + let m = nlp('the dog is nice') + let sub = m.match('is') + sub.insertAfter('really') + t.equal(sub.out('normal'), 'is really', 'is-really') + t.equal(m.out('normal'), 'the dog is really nice', 'dog-is-really-nice') + + m = nlp('the dog climbed the fence') + sub = m.match('climbed') + sub.insertBefore('really') + t.equal(sub.out('normal'), 'really climbed', 'really-quickly') + t.equal(m.out('normal'), 'the dog really climbed the fence', 'dog-really-climbed') + + t.end() +}) diff --git a/tests/match/match-method.test.js b/tests/match/match-method.test.js new file mode 100644 index 000000000..0ba2ce969 --- /dev/null +++ b/tests/match/match-method.test.js @@ -0,0 +1,48 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('match-methods:', function(t) { + let arr = [ + ['@hasComma bravery', 'truth, bravery'], + ['spencer @hasPeriod', 'spencer did.'], + ['spencer @hasExclamation', 'spencer did!'], + ['spencer @hasQuestionMark', 'spencer did?'], + ['spencer @hasEllipses', 'spencer did...'], + ['no @hasSemicolon i said', 'no fair; i said'], + ['hurricane', 'tornado/hurricane'], + ['tornado', 'tornado/hurricane'], + ['@hasSlash', 'tornado/hurricane'], + ['a @hasSlash', 'rock you like a tornado/hurricane'], + ['he @hasContraction', "he isn't going"], + ['@isAcronym', 'FIFA'], + ['@isKnown', 'spencer'], + ] + arr.forEach(a => { + let doc = nlp(a[1]) + t.equal(doc.has(a[0]), true, a[0]) + }) + t.end() +}) + +test('match @functions', function(t) { + let doc = nlp(`jamie's much, much better.`) + + let m = doc.match('@hasComma') + t.equal(m.text(), 'much', 'hasComma') + + m = doc.match('(@hasPeriod|cool)') + t.equal(m.text(), 'better', 'hasPeriod') + + m = doc.match('(@hasSemicolon|better)') + t.equal(m.text(), 'better', 'false-positive') + + doc = nlp(`i am much, much better and faster`) + m = doc.match('!@hasComma') + t.equal(m.text(), 'i am much better and faster', 'negative function') + + doc = nlp(`i am much, much better and faster`) + m = doc.match('(foo|!@hasComma)') + t.equal(m.text(), 'i am much better and faster', 'negative in optional function') + + t.end() +}) diff --git a/tests/match/match-tricky.test.js b/tests/match/match-tricky.test.js new file mode 100644 index 000000000..8987b664c --- /dev/null +++ b/tests/match/match-tricky.test.js @@ -0,0 +1,154 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('fancy match', function(t) { + let arr = [ + //misc + ['doug is good', '', 0], + ['doug is good', '.', 3], + ['doug is good', '.?', 3], + ['doug is good', '.+', 3], + + //contractions + ["he's nice", 'he is', 2], + ["he's nice", 'is nice', 2], + ["he's nice", "he's", 1], + ["he's nice", "he's nice", 3], + ["he's nice", 'nice', 1], + + //over/under + ['he is nice', 'is nice and good', 0], + ['is nice', 'he is nice', 0], + + //dot + ['doug is good', 'doug is good', 3], + ['doug is good', 'doug . good', 3], + ['doug is good', 'doug is .', 3], + ['doug is good', '. is .', 3], + ['doug is good', '. . .', 3], + ['doug is good', '. . . .', 0], + + //optional miss + ['doug is good', 'doug is really? good', 3], + ['doug is good', 'doug is good? good', 3], + ['doug is good', 'doug is .? good', 3], //tricky 'anything optional' bug + ['doug is good', 'doug is #Adverb? good', 3], + //optional has + ['doug is really good', 'doug is really? good', 4], + ['doug is really good', 'doug is .? good', 4], + ['doug is really good', 'doug is #Adverb? good', 4], + //asterix empty + ['doug is good', 'doug *', 3], + ['doug is good', 'doug is *', 3], + ['doug is good', '*', 3], + //asterix positive + ['doug is good', 'doug * good', 3], + ['doug is really good', 'doug * good', 4], + ['doug is really so very good', 'doug * good', 6], + ['doug is really so very good at stuff', 'doug * good', 6], + ['we think doug is really so very good at stuff', 'doug * good', 6], + //asterix negative + ['doug is good', 'doug * bad', 0], + ['doug is good', 'spencer * bad', 0], + ['doug is good', 'spencer *', 0], + ['doug is good', 'doug * is', 2], //another tricky 'greedy optional' bug + ['cool, fun, great, nice', '#Adjective+ great', 3], + + // + ['Dr. Spencer Smith says hi', 'dr', 1], + ['Dr. Spencer Smith says hi', 'dr spencer', 2], + ['Dr. Spencer Smith says hi', 'dr spencer smith', 3], + ['Dr. Spencer Smith says hi', 'dr spencer smith says', 4], + ['Lately, Dr. Spencer Smith says hi', 'lately dr spencer smith', 4], + //start ^ + ['in toronto', '^toronto', 0], + ['toronto', '^toronto', 1], + ['in toronto', '^in toronto', 2], + ['in toronto', 'in ^toronto', 0], + //end $ + ['it snows', 'it snows', 2], + ['it snows', 'snows$', 1], + ['it snows', 'it snows$', 2], + ['it snows', 'it$ snows', 0], + ['it snows', 'foo$', 0], + //negative ! + ['it really snows', 'it #adverb snows', 3], + ['it really snows', 'it !#adverb snows', 0], + ['it really snows. it goes.', 'it !#adverb', 2], + ['it is nice.', '!#adverb', 3], + //max/min {} + ['if it goes really well', 'if .{1,2} well', 0], + ['if it goes really well', 'if .{1,6} well', 5], + ['so i said that spencer is nice', '^.{1,3} spencer', 0], + ['so i said that spencer is nice', '^.{1,6} spencer', 5], + ['one two three four five', 'one two{1,2}', 2], + ['one two three four five', 'one two{1,3}', 2], + ['one two three four five', 'one two{0,3}', 2], + ['one two three four five', 'one .{0,3} two', 2], + ['one two three four five', 'one .{0,3} three', 3], + ['one two three four five', 'one .{1,3} two', 0], + ['one two three four five six seven', 'one .{0,4} six seven', 7], + //optional/consecutive + ['is really walking', 'is #Adverb+? walking', 3], + ['is walking', 'is #Adverb+? walking', 2], + ['is really really walking', 'is #Adverb+? walking', 4], + ['is really not walking', 'is (#Adverb|not)+? walking', 4], + ['is really not quickly walking', 'is (#Adverb|not)+? walking', 5], + ['is walking', 'is (#Adverb|not)+? walking', 2], + ['Phoenix AZ', '#City #Region', 2], + //this isn't working + ['the canadian senate', 'the (united states|canadian) senate', 3], + ['the canadian senate', '(canadian|united states|british)', 1], + ] + arr.forEach(function(a) { + const r = + nlp(a[0]) + .match(a[1]) + .terms() || [] + const msg = "'" + a[0] + "' - - - '" + a[1] + "' - - got:" + r.length + ' want:' + a[2] + t.equal(r.length, a[2], msg) + }) + t.end() +}) + +test('consecutive greedy cases', function(t) { + let doc = nlp('one two') + let m = doc.match('#Value #Value') + t.equal(m.length, 1, 'consecutive-found one') + t.equal(m.eq(0).text(), 'one two', 'consecutive-found both') + + m = doc.match('#Value+ #Value') + t.equal(m.length, 1, 'plus-found one') + t.equal(m.eq(0).text(), 'one two', 'plus-found both') + + m = doc.match('#Value* #Value') + t.equal(m.length, 1, 'astrix-found one') + t.equal(m.eq(0).text(), 'one two', 'astrix-found both') + + m = doc.match('#Value? #Value') + t.equal(m.length, 1, 'optional-found one') + t.equal(m.eq(0).text(), 'one two', 'optional-found both') + + m = nlp.tokenize('one one').match('one? one') + t.equal(m.length, 1, 'optional-double') + m = nlp.tokenize('one one two').match('one? one two') + t.equal(m.text(), 'one one two', 'found all three terms') + + t.end() +}) + +test('tricky-case', function(t) { + t.equal(nlp('Number II').has('Number II'), true, 'uppercase-match') + t.equal(nlp('Number I').has('Number I'), true, 'uppercase-match') + t.end() +}) + +test('text-as-input', function(t) { + const doc = nlp('he is from Phoenix AZ') + const m = doc.match('#City') + const matchWith = doc.match(m).out('normal') + const without = doc.not(m).out('text') + t.equal(matchWith, 'phoenix', 'text-as-match') + t.equal(without, 'he is from AZ', 'text-as-not') + t.end() +}) diff --git a/tests/match/match.test.js b/tests/match/match.test.js new file mode 100644 index 000000000..e94d2088e --- /dev/null +++ b/tests/match/match.test.js @@ -0,0 +1,93 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('term-match :', function(t) { + let arr = [ + ['quick', 'quick', true], + ['Quick', 'Quick', true], + ['quick', 's', false], + ['quick', '#Adjective', true], + ['quick', '#Noun', false], + ['quick', '(fun|nice|quick|cool)', true], + ['quick', '(fun|nice|good)', false], + ] + arr.forEach(function(a) { + const m = nlp(a[0]).match(a[1]) + const msg = a[0] + ' matches ' + a[1] + ' ' + a[2] + t.equal(m.found, a[2], msg) + }) + t.end() +}) + +test('sentence-match:', function(t) { + let arr = [ + ['the dog played', 'the dog', 'the dog'], + ['the dog played', 'the dog played', 'the dog played'], + ['the dog played', 'the #Noun', 'the dog'], + ['the dog played', 'the #Noun played', 'the dog played'], + ['the dog played', 'the cat played', ''], + ['the dog played', 'the #Adjective played', ''], + ['the dog played', 'the (cat|dog|piano) played', 'the dog played'], + ['the dog played', 'the (cat|piano) played', ''], + ['the dog played', 'the . played', 'the dog played'], + //optional + ['the dog played', 'the dog quickly? played', 'the dog played'], + ['the dog played', 'the dog #Adverb? played', 'the dog played'], + ['the dog quickly played', 'the dog #Adverb? played', 'the dog quickly played'], + ['the dog quickly played', 'the dog #Adverb played', 'the dog quickly played'], + ['the dog quickly played', 'the dog . played', 'the dog quickly played'], + ['the dog quickly played', 'the dog .? played', 'the dog quickly played'], + // ['the dog played', 'the dog .? played', 'the dog played'], + + //leading/trailing logic + ['the dog played', 'the dog played$', 'the dog played'], + ['the dog played', 'the dog', 'the dog'], + ['the dog played', 'the dog$', ''], + ['the dog played', 'the dog$ played', ''], + ['the dog played', '^the dog', 'the dog'], + ['the dog played', 'dog played', 'dog played'], + ['the dog played', '^dog played', ''], + ['the dog played', '^played', ''], + ['the dog played', '^the', 'the'], + + ['john eats glue', 'john eats glue', 'john eats glue'], + ['john eats glue', 'john eats', 'john eats'], + ['john eats glue', 'eats glue', 'eats glue'], + ['john eats glue', 'eats glue all day', ''], + + //test contractions + // [`if you don't mind`, `you don't mind`, `you don't mind`], + [`if you don't mind`, `you don't care`, ``], + // [`if you don't mind`, `you don't`, `you don't`], + // [`if you don't mind`, `don't mind`, `don't mind`], + + // [`if you didn't care`, `didn't`, `didn't`], //TODO:support me + + // [`if you wouldn't care, i'll eat here`, `i'll eat`, `i'll eat`], //omg hard one + + // [`don't go`, `do not`, `don't`], + [`do not go`, `do not`, `do not`], + // [`i dunno`, `do not`, `dunno`], + //bugs + // [`really remind me to buy`, '#Adverb? #Infinitive (me|us) (to|for)', `really remind me to`], + ] + arr.forEach(function(a) { + const m = nlp(a[0]).match(a[1]) + if (!m.found) { + t.equal(a[2], '', 'no-match: ' + a[0] + ' - -' + a[1]) + } else { + const msg = "'" + a[0] + "' - " + a[1] + " - - have : '" + m.out('normal') + "'" + t.equal(m.out('normal'), a[2], msg) + } + }) + t.end() +}) + +test('tag-match-tag :', function(t) { + const m = nlp('apple is cool') + m.match(['apple', 'susan']).tag('Person') + const p = m.match('#Person') + t.equal(p.out('normal'), 'apple', 'apple-tagged') + t.equal(m.length, 1, 'one-result') + t.end() +}) diff --git a/tests/match/min-max.test.js b/tests/match/min-max.test.js new file mode 100644 index 000000000..bf2d84866 --- /dev/null +++ b/tests/match/min-max.test.js @@ -0,0 +1,24 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('match min-max', function(t) { + let doc = nlp('hello1 one hello2').match('#Value{7,9}') + t.equal(doc.out(), '', 'match was too short') + + doc = nlp('hello1 one two three four five hello2').match('#Value{3}') + t.equal(doc.out(), 'one two three', 'exactly three') + + doc = nlp('hello1 one two three four five hello2').match('#Value{3,3}') + t.equal(doc.out(), 'one two three', 'still exactly three') + + doc = nlp('hello1 one two three four five hello2').match('#Value{3,}') + t.equal(doc.out(), 'one two three four five', 'minimum three') + + doc = nlp('hello1 one two three four five hello2').match('hello1 .{3}') + t.equal(doc.out(), 'hello1 one two three', 'unspecific greedy exact length') + + doc = nlp('hello1 one two').match('hello1 .{3}') + t.equal(doc.out(), '', 'unspecific greedy not long enough') + + t.end() +}) diff --git a/tests/match/not.test.js b/tests/match/not.test.js new file mode 100644 index 000000000..98fd3c725 --- /dev/null +++ b/tests/match/not.test.js @@ -0,0 +1,49 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('not-basic :', function(t) { + let m = nlp('spencer is really cool').not('brown') + t.equal(m.out('text'), 'spencer is really cool', 'missing-not') + t.equal(m.length, 1, 'one-result') + + m = nlp('spencer is really cool').not('#Adverb') + t.equal(m.out('text'), 'spencer is cool', 'one-not') + t.equal(m.length, 2, 'two-results') + + m = nlp('spencer is really cool').not('#Adverb+') + t.equal(m.out('text'), 'spencer is cool', 'still-one-not') + t.equal(m.length, 2, 'two-results-2') + + m = nlp('spencer is really cool').not('#Adverb+') + t.equal(m.out('text'), 'spencer is cool', 'two-not') + t.equal(m.length, 2, 'two-results-3') + + m = nlp('spencer is really cool').not('is #Adverb+') + t.equal(m.out('text'), 'spencer cool', 'three-not') + t.equal(m.length, 2, 'two-results-4') + + m = nlp('spencer is really cool. John is really nice').not('#Adverb') + t.equal(m.out('text'), 'spencer is cool. John is nice', 'two-terms-matches') + t.equal(m.length, 4, 'four-results') + + m = nlp('spencer is really cool. John is really nice.').not('pardon me, #Adverb') + t.equal(m.out('text'), 'spencer is really cool. John is really nice.', 'tricky-no-match') + t.equal(m.length, 2, 'two-original-results') + + t.end() +}) + +test('not-from-array :', function(t) { + let m = nlp('spencer is really cool').not(['spencer']) + t.equal(m.out('normal'), 'is really cool', 'not-spencer') + t.equal(m.length, 1, 'one-results') + + m = nlp('spencer is really cool').not(['']) + t.equal(m.out('normal'), 'spencer is really cool', 'not-spencer') + t.equal(m.length, 1, 'one-results-2') + + m = nlp('spencer is really cool').not(['spencer', 'really']) + t.equal(m.out('normal'), 'is cool', 'not-spencer-really') + t.equal(m.length, 2, 'two-results-arr') + t.end() +}) diff --git a/tests/match/or-operand.test.js b/tests/match/or-operand.test.js new file mode 100644 index 000000000..ebdb8d45c --- /dev/null +++ b/tests/match/or-operand.test.js @@ -0,0 +1,22 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('or-match-basic', function(t) { + let doc = nlp('toronto and montreal. Sydney and Paris') + let m = doc.match('(#Place | and )') + t.equal(m.out(), 'toronto and montreal. Sydney and Paris', 'whitespace-or') + + m = doc.match('(#Place | nonono no no| and )') + t.equal(m.out(), 'toronto and montreal. Sydney and Paris', 'whitespace-or-multi1') + + m = doc.match('( nonono no no|| . )') + t.equal(m.out(), 'toronto and montreal. Sydney and Paris', 'whitespace-or-dot') + t.end() +}) + +// test('or-match-multi', function(t) { +// let doc = nlp('toronto and montreal. Sydney and Paris') +// let m = doc.match('(#Place and montreal )') +// t.equal(m.out(), 'toronto and montreal', 'whitespace-or') +// t.end() +// }) diff --git a/tests/match/prefix.test.js b/tests/match/prefix.test.js new file mode 100644 index 000000000..bf73428f9 --- /dev/null +++ b/tests/match/prefix.test.js @@ -0,0 +1,37 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('prefix/infix/suffix basic', function(t) { + let r = nlp('it is funny and weird') + let m = r.match('/nny$/', true) + t.equal(m.out('normal'), 'funny', 'suffix-match') + m = r.match('/^fu/', true) + t.equal(m.out('normal'), 'funny', 'prefix_match') + m = r.match('/nn/', true) + t.equal(m.out('normal'), 'funny', 'infix-match') + + m = r.match('/ff$/', true) + t.equal(m.out('normal'), '', 'no-false-suffix') + m = r.match('/^ff/', true) + t.equal(m.out('normal'), '', 'no-false-prefix') + m = r.match('/ff/', true) + t.equal(m.out('normal'), '', 'no-false-infix') + + m = r.match('_', true) + t.equal(m.out('normal'), '', 'no-throw1') + m = r.match(' _ ', true) + t.equal(m.out('normal'), '', 'no-throw2') + m = r.match(' __ ', true) + t.equal(m.out('normal'), '', 'no-throw3') + m = r.match(' _ _ ', true) + t.equal(m.out('normal'), '', 'no-throw4') + + m = r.match('/^w/', true) + t.equal(m.out('normal'), 'weird', 'one-char-one-word') + m = r.match('/r/', true) + t.equal(m.out('normal'), 'weird', 'one-char-one-word2') + m = r.match('/y$/', true) + t.equal(m.out('normal'), 'funny', 'one-char-one-word3') + + t.end() +}) diff --git a/tests/match/regex.test.js b/tests/match/regex.test.js new file mode 100644 index 000000000..1ea81af72 --- /dev/null +++ b/tests/match/regex.test.js @@ -0,0 +1,19 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('regex-match:', function(t) { + let doc = nlp('it is waaaay cool') + let m = doc.match('/aaa/') + t.equal(m.out('normal'), 'waaaay', 'basic-match') + + m = doc.match('/[ao]{2}/') + t.equal(m.out('array').length, 2, 'trickier-match') + + m = doc.match('is /aaam?/ .') + t.equal(m.out('normal'), 'is waaaay cool', 'trickier-match') + + m = doc.match('#Copula /a+/ /ool$/') + t.equal(m.out('normal'), 'is waaaay cool', 'even-trickier-match') + + t.end() +}) diff --git a/tests/match/remove.test.js b/tests/match/remove.test.js new file mode 100644 index 000000000..5b64e391e --- /dev/null +++ b/tests/match/remove.test.js @@ -0,0 +1,68 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('remove-basic :', function(t) { + let m = nlp('the brown cat played') + .match('brown') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'brown-cat') + + m = nlp('the nice brown cat played') + .match('nice brown') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'nice-brown') + + m = nlp('the nice brown cat played') + .match('#Adjective') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'adj-each') + + m = nlp('the nice brown cat played') + .match('#Adjective+') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'adj-consecutive') + + t.end() +}) + +test('remove-match :', function(t) { + let m = nlp('the brown cat played').delete('brown') + t.equal(m.out('text'), 'the cat played', 'brown-cat') + + m = nlp('the brown cat played. The brown dog sat down.').delete('brown') + t.equal(m.out('text'), 'the cat played. The dog sat down.', 'brown-cat') + + m = nlp('the nice brown cat played. The nice dog waited.').delete('nice brown') + t.equal(m.out('text'), 'the cat played. The nice dog waited.', 'nice-brown') + + m = nlp('the nice brown cat played. The cute dogs ate.').delete('#Adjective') + t.equal(m.out('text'), 'the cat played. The dogs ate.', 'adj-each') + + m = nlp('the nice brown cat played. The cute dogs ate.').delete('#Adjective+') + t.equal(m.out('text'), 'the cat played. The dogs ate.', 'adj-consecutive') + + t.end() +}) + +test('remove-logic :', function(t) { + let m = nlp('spencer kelly is here') + .match('spencer kelly') + .delete('spencer') + t.equal(m.out('normal'), 'kelly', 'remove(reg) returns this') + + m = nlp('spencer kelly is here') + .match('spencer kelly') + .delete() + .all() + t.equal(m.out('normal'), 'is here', 'remove() returns parent') + + m = nlp('spencer kelly is here') + .match('spencer kelly') + .delete('notfound') + t.equal(m.out('normal'), 'spencer kelly', 'remove(notfound) returns this') + t.end() +}) diff --git a/tests/match/replace.test.js b/tests/match/replace.test.js new file mode 100644 index 000000000..c93cb09af --- /dev/null +++ b/tests/match/replace.test.js @@ -0,0 +1,126 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('replace-basic :', function(t) { + let m = nlp('the dog played') + .match('dog') + .replace('cat') + .all() + t.equal(m.out('text'), 'the cat played', 'dog-cat') + + m = nlp('the dog played') + .match('the dog') + .replace('a cat') + .all() + t.equal(m.out('text'), 'a cat played', 'a-cat') + + m = nlp('the dog played') + .match('#Noun') + .replace('snake') + .all() + t.equal(m.out('text'), 'the snake played', 'snake') + + m = nlp('the pit bull played') + .match('#Noun+') + .replace('snake') + .all() + t.equal(m.out('text'), 'the snake played', 'pit bull') + + m = nlp('the pit bull dog played') + .match('#Noun+') + .replace('grey snake') + .all() + t.equal(m.out('text'), 'the grey snake played', 'pit bull dog') + + t.end() +}) + +test('match-replace :', function(t) { + ;[ + ['the dog played', 'the dog', 'the cat', 'the cat played'], + ['the dog played', 'the #Noun', 'the cat', 'the cat played'], + ['the dog played', 'the (dog|hamster|pet-snake)', 'the cat', 'the cat played'], + ['the boy and the girl', 'the #Noun', 'the house', 'the house and the house'], + ['the boy and the girl', 'the cat', 'the house', 'the boy and the girl'], + ].forEach(function(a) { + const str = nlp(a[0]) + .replace(a[1], a[2]) + .out('text') + const msg = str + ' -- ' + a[3] + t.equal(str, a[3], msg) + }) + + t.end() +}) + +test('replace-with-punctuation', function(t) { + const doc = nlp('Simon, how is Pamela and Jason?') + const str = doc + .match('#Person') + .replace('PERSON') + .all() + .out() + t.equal(str, 'PERSON, how is PERSON and PERSON?', 'replace-with-punctuation') + t.end() +}) + +test('structured-object-replace :', function(t) { + let r = nlp('fun times in cool town') + const term = r.match('times') + r.replace(term, 'day') + t.equal(r.out(), 'fun day in cool town', 'structured-replace') + + r = nlp('fun times in cool town') + const terms = r.match('cool town') + r.replace(terms, 'shitsville') + t.equal(r.out(), 'fun times in shitsville', 'structured-replace-multi') + t.end() +}) + +test('replace-keep some punctuation', function(t) { + let doc = nlp('two weeks').tag('Cool') + doc.replace('two', '2', true) + t.equal(doc.match('#Cool+').text(), '2 weeks', 'replace-keep-tags') + + doc = nlp('first sentence. I am trying it out.') + doc.match('#Gerund').tag('HashTag') + doc.match('trying').replaceWith('working', true) + t.equal(doc.match('#HashTag+').text(), 'working', 'replacewith-keep-tags') + t.end() +}) + +test('replace over implict', function(t) { + let doc = nlp("i'm good") + doc.match('am').replaceWith('was') + t.equal(doc.text(), 'i was good', 'replace over implicit') + t.end() +}) + +test('replace-with-Doc', function(t) { + let b = nlp('sneaks').tag('Cool') + + let doc = nlp(`john walks quickly`) + + doc.match('walks').replaceWith(b) + t.equal(doc.text(), 'john sneaks quickly') + t.equal(doc.has('#Cool'), true) + t.end() +}) + +test('replace-with-function', function(t) { + const repl = p => { + if (p.has('john')) { + return 'johnny' + } + return 'nancy' + } + let doc = nlp('spencer and John').replace('#Person', repl, true, true) + t.equal(doc.text(), 'nancy and Johnny', 'replace function') + + doc = nlp('Thurs, Feb 2nd, 2016') + doc.match('feb').replaceWith(m => { + return m.text({ trim: true }) + '!' + }) + t.equal(doc.text(), 'Thurs, Feb! 2nd, 2016', 'replaceWith function') + t.end() +}) diff --git a/tests/match/soft-match.test.js b/tests/match/soft-match.test.js new file mode 100644 index 000000000..33b19b7f4 --- /dev/null +++ b/tests/match/soft-match.test.js @@ -0,0 +1,15 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('soft-match', function(t) { + let doc = nlp(`a priest walked into the bars`) + doc.cache({ root: true }) + t.equal(doc.match('bars').found, true, 'found bars') + t.equal(doc.match('bar').found, false, 'missed bar without ~') + t.equal(doc.match('~bars~').found, true, 'found ~ bars') + t.equal(doc.match('~bar~').found, true, 'found ~ bar') + t.equal(doc.match('~walk~ into').found, true, 'found infinitive') + t.equal(doc.match('~bar~').found, true, 'found singular') + t.equal(doc.text('root'), 'a priest walk into the bar', 'root-output') + t.end() +}) diff --git a/tests/match/syntax.test.js b/tests/match/syntax.test.js new file mode 100644 index 000000000..0e02798dc --- /dev/null +++ b/tests/match/syntax.test.js @@ -0,0 +1,39 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('negative parentheses', function(t) { + let doc = nlp.tokenize('if he does. does he?') + let m = doc.if('!^(if|cool)') + t.equals(m.out('normal'), 'does he?', 'negative-start') + + m = doc.if('^!(if|cool)') + t.equals(m.out('normal'), 'does he?', 'start-negative') + + doc = nlp.tokenize('spencer other') + t.equals(doc.match('(cool|spencer)').text(), 'spencer', 'optional-true') + t.equals(doc.match('!(cool|spencer)').text(), 'other', 'outside-negative') + t.equals(doc.match('!(foobar)').text(), 'spencer other', 'has-everthing') + t.equals(doc.match('(!spencer)').text(), 'other', 'has-other') + t.equals(doc.match('!(spencer)').text(), 'other', 'has-other-outside') + t.equals(doc.match('(!other|!spencer)').text(), 'spencer other', 'tricky-negative-swap') + t.equals(doc.match('!(!other|!spencer)').text(), '', 'double-tricky') + t.end() +}) + +test('start-end parentheses', function(t) { + let doc = nlp("matt does but matthew doesn't") + let m = doc.match('^(/matt/|frank) .') + t.equals(m.out('normal'), 'matt does', 'choice-start') + + m = doc.match('(^#Person|#Person$)') + t.equals(m.out('normal'), 'matt', 'matt-start') + + doc = nlp("now matt doesn't but yes for matthew") + m = doc.match('(^#Person|#Person$)') + t.equals(m.out('normal'), 'matthew', 'matthew-end') + + doc = nlp("now matt doesn't but yes for matthew") + m = doc.match('(woo|#Person)$') + t.equals(m.out('normal'), 'matthew', 'matthew-end-outside') + t.end() +}) diff --git a/tests/misc.test.js b/tests/misc.test.js new file mode 100644 index 000000000..690fc864b --- /dev/null +++ b/tests/misc.test.js @@ -0,0 +1,34 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('tag-multiples:', function(t) { + const r = nlp('twas brillig in the doofgafoof.') + r.match('brillig').tag(['Foo', 'Barr']) + t.ok(r.match('#Foo').found, 'tagged-foo') + t.ok(r.match('#Barr').found, 'tagged-barr') + t.end() +}) + +// ----- + +test('root-text vs match-text', function(t) { + let str = ` paper, scissors, rock. I run with scissors.` + let doc = nlp(str) + .match('*') + .all() + t.equal(doc.text(), str, 'perfect-root-text') + + let m = doc.match('scissors') + t.equal(m.text(), 'scissors, scissors', 'match-text') + t.end() +}) + +test('barely a term', function(t) { + let str = '.(' + let doc = nlp(str) + t.equal(doc.out(), str, 'barely-term-no-space') + str = '.( ' + doc = nlp(str) + t.equal(doc.out(), str, 'barely-term-with-space') + t.end() +}) diff --git a/tests/money.test.js b/tests/money.test.js new file mode 100644 index 000000000..be2761173 --- /dev/null +++ b/tests/money.test.js @@ -0,0 +1,17 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('money tests', function(t) { + let doc = nlp('i paid 5 USD for the thing, and got $2.50 back.') + let m = doc.money() + t.equal(m.length, 2, 'both money forms') + t.equal(m.eq(0).text(), '5 USD', 'val-currency') + t.equal(m.eq(1).text(), '$2.50', 'sybol-val') + + doc = nlp('i got 1 peso and £30.') + m = doc.money() + t.equal(m.length, 2, 'both intl money forms') + t.equal(m.eq(0).text(), '1 peso', 'val-currency-2') + t.equal(m.eq(1).text(), '£30', 'sybol-val-2') + t.end() +}) diff --git a/tests/multiTag.test.js b/tests/multiTag.test.js new file mode 100644 index 000000000..93ccc46ba --- /dev/null +++ b/tests/multiTag.test.js @@ -0,0 +1,40 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('tag-sequence:', function(t) { + const doc = nlp('it was cold') + doc.tag('#One #Two #Three') + t.equal(doc.match('#One').text(), 'it', 'one') + t.equal(doc.match('#Two').text(), 'was', 'two') + t.equal(doc.match('#Three').text(), 'cold', 'three') + t.end() +}) + +test('multiple-tags:', function(t) { + const doc = nlp('it was cold') + doc.tag(['#One', '#Two', '#Three']) + t.equal(doc.match('#One').text(), 'it was cold', 'multi- all have #One') + t.equal(doc.match('#Two').text(), 'it was cold', 'multi- all have #Two') + t.equal(doc.match('#Three').text(), 'it was cold', 'multi- all have #Three') + t.end() +}) + +test('tag-sequence-skip:', function(t) { + const doc = nlp('it was cold') + doc.tag('#One . #Three') + t.equal(doc.match('#One').text(), 'it', 'one') + t.equal(doc.match('#Two').text(), '', 'no-two') + t.equal(doc.match('#.').text(), '', 'no-dot') + t.equal(doc.match('#Three').text(), 'cold', 'three') + t.end() +}) + +test('multiple-tags-skip:', function(t) { + const doc = nlp('it was cold') + doc.tag(['.', '#Two', '.']) + t.equal(doc.match('#One').found, false, 'skip - none have #One') + t.equal(doc.match('#Two').text(), 'it was cold', 'skip - all have #Two') + t.equal(doc.match('#Three').found, false, 'skip - none have #Three') + t.equal(doc.match('#.').found, false, 'skip - none have #dot') + t.end() +}) diff --git a/tests/nouns/article.test.js b/tests/nouns/article.test.js new file mode 100644 index 000000000..a1ad077f9 --- /dev/null +++ b/tests/nouns/article.test.js @@ -0,0 +1,28 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('.article():', function(t) { + let arr = [ + ['duck', 'a'], + ['eavesdropper', 'an'], + ['alligator', 'an'], + // ['hour', 'an'], + ['NDA', 'an'], + ['F.B.I', 'an'], + ['N.D.A.', 'an'], + ['eulogy', 'a'], + ['ukalele', 'a'], + ['skateboards', 'the'], + ['John Smith', ''], + ['Tony Danza', ''], + ] + arr.forEach(function(a) { + const o = nlp(a[0]) + .tag('Noun') + .nouns() + .json()[0] + const msg = a[0] + ' -> ' + o.article + t.equal(o.article, a[1], msg) + }) + t.end() +}) diff --git a/tests/nouns/inflect.test.js b/tests/nouns/inflect.test.js new file mode 100644 index 000000000..cb1e0b04c --- /dev/null +++ b/tests/nouns/inflect.test.js @@ -0,0 +1,210 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('isPlural:', function(t) { + let arr = [ + ['octopus', false], + ['tree', false], + ['trees', true], + // ['i', false], + ['mayor of chicago', false], + ['mayors of chicago', true], + ['octopus', false], + ['octopi', true], + ['eyebrow', false], + ['eyebrows', true], + ['child', false], + ['children', true], + ["spencer's", false], + ["toronto's", false], + ['circus', false], + ['circuses', true], + // ['simpsons\'', false], + // ['she\'s', false], + ] + arr.forEach(function(a) { + const r = nlp(a[0]).nouns() + const msg = a[0] + t.equal(r.isPlural().found, a[1], msg) + }) + t.end() +}) + +test('toSingular:', function(t) { + let arr = [ + // ["Joneses", "Jones"], + ['children', 'child'], + ['women', 'woman'], + ['men', 'man'], + ['people', 'person'], + ['geese', 'goose'], + ['mice', 'mouse'], + ['barracks', 'barracks'], + ['deer', 'deer'], + ['nuclei', 'nucleus'], + ['syllabi', 'syllabus'], + ['fungi', 'fungus'], + ['cacti', 'cactus'], + ['theses', 'thesis'], + ['crises', 'crisis'], + ['phenomena', 'phenomenon'], + ['embryos', 'embryo'], + ['frescos', 'fresco'], + ['ghettos', 'ghetto'], + ['halos', 'halo'], + ['mangos', 'mango'], + ['mementos', 'memento'], + ['mottos', 'motto'], + ['tornados', 'tornado'], + ['tuxedos', 'tuxedo'], + ['volcanos', 'volcano'], + ['crises', 'crisis'], + ['analyses', 'analysis'], + ['aircraft', 'aircraft'], + ['bass', 'bass'], + ['bison', 'bison'], + ['fish', 'fish'], + ['fowl', 'fowl'], + ['kilos', 'kilo'], + ['kimonos', 'kimono'], + ['logos', 'logo'], + ['memos', 'memo'], + ['ponchos', 'poncho'], + ['photos', 'photo'], + ['pimentos', 'pimento'], + ['pros', 'pro'], + ['sombreros', 'sombrero'], + ['tacos', 'taco'], + ['memos', 'memo'], + ['torsos', 'torso'], + ['xylophones', 'xylophone'], + ['quintuplets', 'quintuplet'], + ['worrywarts', 'worrywart'], + ['nerds', 'nerd'], + ['lollipops', 'lollipop'], + ['eyebrows', 'eyebrow'], + // ['mayors of chicago', 'mayor of chicago'], + //test that sungular.singularize()==singular.. + ['mango', 'mango'], + ['memento', 'memento'], + ['motto', 'motto'], + ['tornado', 'tornado'], + ['person', 'person'], + ['goose', 'goose'], + ['mouse', 'mouse'], + ['calves', 'calf'], + ['olives', 'olive'], + ['loaves', 'loaf'], + ['oafs', 'oaf'], + ['wives', 'wife'], + ['roofs', 'roof'], + ['hooves', 'hoof'], + ['buses', 'bus'], + ['tosses', 'toss'], + ['wishes', 'wish'], + ['geniouses', 'genious'], + ['prognoses', 'prognosis'], + ['analyses', 'analysis'], + ['synopses', 'synopsis'], + ['parentheses', 'parenthesis'], + ['theses', 'thesis'], + ['bases', 'base'], + ] + arr.forEach(function(a) { + const r = nlp(a[0]) + .tag('Noun') + .nouns() + const str = r.toSingular().out('normal') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('toPlural:', function(t) { + let arr = [ + ['snake', 'snakes'], + ['ski', 'skis'], + // ["Barrymore", "Barrymores"], + ['witch', 'witches'], + ['box', 'boxes'], + ['gas', 'gases'], + ['kiss', 'kisses'], + ['index', 'indices'], + ['appendix', 'appendices'], + ['criterion', 'criteria'], + ['berry', 'berries'], + ['activity', 'activities'], + ['daisy', 'daisies'], + ['church', 'churches'], + ['fox', 'foxes'], + ['stomach', 'stomachs'], + ['epoch', 'epochs'], + ['knife', 'knives'], + ['half', 'halves'], + ['scarf', 'scarves'], + ['chief', 'chiefs'], + ['spoof', 'spoofs'], + ['cafe', 'cafes'], + ['gulf', 'gulfs'], + ['alternative', 'alternatives'], + ['solo', 'solos'], + // ['zero', 'zeros'], + ['avocado', 'avocados'], + ['studio', 'studios'], + ['zoo', 'zoos'], + ['embryo', 'embryos'], + ['hero', 'heroes'], + ['banjo', 'banjos'], + ['cargo', 'cargos'], + ['flamingo', 'flamingos'], + ['fresco', 'frescos'], + ['ghetto', 'ghettos'], + ['halo', 'halos'], + ['mango', 'mangos'], + ['memento', 'mementos'], + ['motto', 'mottos'], + ['tornado', 'tornados'], + ['tuxedo', 'tuxedos'], + ['volcano', 'volcanos'], + ['bus', 'buses'], + ['crisis', 'crises'], + ['analysis', 'analyses'], + ['neurosis', 'neuroses'], + ['aircraft', 'aircraft'], + ['halibut', 'halibut'], + ['moose', 'moose'], + ['salmon', 'salmon'], + ['sheep', 'sheep'], + ['spacecraft', 'spacecraft'], + ['tuna', 'tuna'], + ['trout', 'trout'], + ['armadillo', 'armadillos'], + ['auto', 'autos'], + ['bravo', 'bravos'], + ['bronco', 'broncos'], + ['casino', 'casinos'], + ['combo', 'combos'], + ['gazebo', 'gazebos'], + //test that plural.pluralize()==plural.. + ['snakes', 'snakes'], + ['skis', 'skis'], + // ['mayor of chicago', 'mayors of chicago'], + // ["Barrymores", "Barrymores"], + ['witches', 'witches'], + ['boxes', 'boxes'], + ['gases', 'gases'], + ['spoofs', 'spoofs'], + ['solos', 'solos'], + ['avocados', 'avocados'], + ['studios', 'studios'], + ['zoos', 'zoos'], + ] + arr.forEach(function(a) { + const r = nlp(a[0]) + .tag('Noun') + .nouns() + const str = r.toPlural().out('normal') + t.equal(str, a[1], a[0]) + }) + t.end() +}) diff --git a/tests/nouns/misc.test.js b/tests/nouns/misc.test.js new file mode 100644 index 000000000..9c23ffb71 --- /dev/null +++ b/tests/nouns/misc.test.js @@ -0,0 +1,11 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('misc nouns', function(t) { + let doc = nlp(`quickly, suddenly`) + t.equal(doc.nouns().length, 0, 'found no nouns') + + doc = nlp(`john smith, and then Google Inc in Flordia`) + t.equal(doc.nouns().length, 3, 'found three nouns') + t.end() +}) diff --git a/test/unit/subset/noun/nounPhrase.test.js b/tests/nouns/nounPhrase.test.js similarity index 86% rename from test/unit/subset/noun/nounPhrase.test.js rename to tests/nouns/nounPhrase.test.js index 63067ece4..af157ee30 100644 --- a/test/unit/subset/noun/nounPhrase.test.js +++ b/tests/nouns/nounPhrase.test.js @@ -1,5 +1,5 @@ -var test = require('tape'); -var nlp = require('../../lib/nlp'); +const test = require('tape') +const nlp = require('../_lib') //(from https://brenocon.com/JustesonKatz1995.pdf) // AN: linear function; lexical ambiguity; mobile phase @@ -13,7 +13,7 @@ var nlp = require('../../lib/nlp'); // NPN: degrees of freedom; [no example]; energy of adsorption test('noun-phrases', function(t) { - [ + ;[ ['he was a person of interest in the case', 'person of interest'], ['he was the mayor of chicago', 'mayor of chicago'], ['he was the captain of the football team', 'captain of the football team'], @@ -28,14 +28,16 @@ test('noun-phrases', function(t) { ['the 5-person chairlift', '5-person chairlift'], ['he had the right of way', 'right of way'], ['my retail bank sucks', 'retail bank'], - ['my activation code isn\'t working', 'activation code'], + ["my activation code isn't working", 'activation code'], ['my speech recognition system', 'speech recognition system'], ['a typical machine learning documentary film', 'machine learning documentary film'], ['every cold war re-enactment is boring', 'cold war reenactment'], ['two slices of cranberry', 'slices of cranberry'], ].forEach(function(a) { - var str = nlp(a[0]).nouns(0).out('normal'); - t.equal(str, a[1], a[0] + ' -> "' + str + '"'); - }); - t.end(); -}); + const str = nlp(a[0]) + .nouns(0) + .out('normal') + t.equal(str, a[1], a[0] + ' -> "' + str + '"') + }) + t.end() +}) diff --git a/tests/nouns/possessive.test.js b/tests/nouns/possessive.test.js new file mode 100644 index 000000000..4ec3a0977 --- /dev/null +++ b/tests/nouns/possessive.test.js @@ -0,0 +1,24 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('.toPossessive():', function(t) { + let arr = [ + ['duck', `duck's`], + ['eavesdropper', `eavesdropper's`], + ['John', `John's`], + ['hour', `hour's`], + ['F.B.I', `F.B.I's`], + ['John Smith', `John Smith's`], + ['skateboards', `skateboards'`], + ['Flanders', `Flanders'`], + // ['she', 'hers'], + ['peaches', `peaches'`], + ] + arr.forEach(function(a) { + const doc = nlp(a[0]) + .nouns() + .toPossessive() + t.equal(doc.out(), a[1], a[0]) + }) + t.end() +}) diff --git a/tests/output/json.test.js b/tests/output/json.test.js new file mode 100644 index 000000000..6ee306684 --- /dev/null +++ b/tests/output/json.test.js @@ -0,0 +1,102 @@ +const test = require('tape') +const nlp = require('../_lib') + +const hasTag = function(term, want) { + if (!term || !term.tags) { + return false + } + return term.tags.some(tag => tag === want) +} + +test('json out default', function(t) { + let doc = nlp('who are you? what is this?') + let json = doc.json({ terms: true }) + t.equal(json.length, 2, 'json-len') + t.equal(json[1].text, 'what is this?', 'json-text') + t.equal(json[1].terms.length, 3, 'json-three-terms') + t.equal(hasTag(json[1].terms[1], 'Copula'), true, 'json-has-tag') + t.end() +}) + +test('json out trim', function(t) { + let doc = nlp('who are you? what is this?') + let json = doc.json({ trim: false, terms: false }) + t.equal(json.length, 2, 'json-len') + t.equal(json[0].text, 'who are you? ', 'json-text') + t.equal(json[1].text, 'what is this?', 'json-text') + t.equal(json[1].terms, undefined, 'json-no-terms') + t.end() +}) + +test('json out implicit', function(t) { + let str = `he isn't` + let doc = nlp(str) + let json = doc.json() + t.equal(json.length, 1, 'json-len') + t.equal(json[0].text, str, 'json-text') + t.equal(json[0].terms.length, 3, 'json-three-terms') + let t0 = json[0].terms[0] || {} + t.equal(t0.implicit, undefined, 'has-no-implicit') + let t1 = json[0].terms[1] || {} + t.equal(hasTag(t1, 'Copula'), true, 'json-has-tag') + t.equal(t1.implicit, 'is', 'has-implicit1') + t.equal(hasTag(json[0].terms[2], 'Negative'), true, 'json-has-tag2') + let t2 = json[0].terms[2] || {} + t.equal(t2.implicit, 'not', 'has-implicit2') + t.end() +}) + +test('json terms out', function(t) { + let doc = nlp(`she is not`) + let json = doc.json({ text: false, terms: { clean: true, id: true, bestTag: true, whitespace: true } }) + t.equal(json.length, 1, 'json-len') + t.equal(json[0].text, undefined, 'json-text') + t.equal(json[0].terms.length, 3, 'json-terms-length') + let t0 = json[0].terms[0] || {} + t.equal(t0.bestTag, 'Pronoun', 'json-terms-bestTag') + let t1 = json[0].terms[1] || {} + t.equal(t1.bestTag, 'Copula', 'json-terms-bestTag1') + let t2 = json[0].terms[2] || {} + t.equal(t2.bestTag, 'Negative', 'json-terms-bestTag2') + + t.equal(t1.pre, '', 'json-terms-whitespace-pre') + t.equal(t1.post, ' ', 'json-terms-whitespace-post') + t.end() +}) + +test('json-index:', function(t) { + let doc = nlp(`john is not really walking`) + let obj = doc.match('really').json({ index: true })[0] + t.equal(obj.terms[0].index, 3, 'index:3') + t.equal(obj.index, 3, 'phrase-index:3') + t.end() +}) + +test('json-unique:', function(t) { + let doc = nlp(`a b c b a`) + let arr = doc.terms().json({ unique: true, terms: false, count: true }) + t.equal(arr.length, 3, 'no duplicates') + t.end() +}) + +test('out-custom:', function(t) { + const doc = nlp('The competent drum work of Don Brewer?') + const arr = doc.json({ + terms: { + text: true, + normal: false, + tags: true, + sdf: true, + root: true, + }, + })[0].terms + t.equal(arr[0].text, 'The', 'has text') + // t.equal(arr[5].root, 'don', 'has root') + t.equal(arr[5].sdf, undefined, 'has no sdf') + t.equal( + arr[0].tags.some(tag => tag === 'Determiner'), + true, + 'has tags' + ) + t.end() +}) diff --git a/tests/output/out.test.js b/tests/output/out.test.js new file mode 100644 index 000000000..696923fad --- /dev/null +++ b/tests/output/out.test.js @@ -0,0 +1,19 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('out-tags', function(t) { + let out = nlp(`he's cool.`).out('tags') + t.equal(out.length, 1, 'one sentence') + t.equal(out[0].he.indexOf('Pronoun') !== -1, true, 'has he:Pronoun') + t.equal(out[0].is.indexOf('Copula') !== -1, true, 'has is:Copula') + t.equal(out[0].cool.indexOf('Adjective') !== -1, true, 'has cool:Adjective') + t.end() +}) +test('out-topk', function(t) { + let doc = nlp(`What'd I say? Monorail. What's it called? Monorail.`) + let out = doc.out('freq') + t.equal(out.length, 3, 'three results') + t.equal(out[0].reduced, 'monorail', 'top-result is most-frequent') + t.equal(out[0].count, 2, 'got count') + t.end() +}) diff --git a/tests/output/text.test.js b/tests/output/text.test.js new file mode 100644 index 000000000..6a51f6adc --- /dev/null +++ b/tests/output/text.test.js @@ -0,0 +1,84 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('text-formats', function(t) { + let doc = nlp(`Toronto's citizens LOVE toronto! they come here for food.`) + t.equal(doc.text('normal'), `toronto's citizens love toronto! they come here for food.`, 'normal') + t.end() +}) + +test('text(normal):', function(t) { + let arr = [ + ['he is good', 'he is good'], + ['Jack and Jill went up the hill.', 'jack and jill went up the hill.'], + ['Mr. Clinton did so.', 'mr clinton did so.'], + ['he is good', 'he is good'], + ['Jack and Jill went up the hill. She got water.', 'jack and jill went up the hill. she got water.'], + ['Joe', 'joe'], + ['just-right', 'just right'], + ['camel', 'camel'], + ['4', '4'], + ['four', 'four'], + ['john smith', 'john smith'], + ['Dr. John Smith-McDonald', 'dr john smith mcdonald'], + ['Contains no fruit juice. \n\n All rights reserved', 'contains no fruit juice. all rights reserved'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]).text('normal') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('text-text', function(t) { + const str = `My dog LOVES pizza, and grapes!!` + let doc = nlp(str) + + t.equal(doc.json({ text: true })[0].text, str, 'json(text)') + + t.equal(doc.text('text'), str, 'text(text): ') + + t.end() +}) + +test('text-normal', function(t) { + let doc = nlp(`My dog LOVES pizza, and grapes!!`) + const str = 'my dog loves pizza, and grapes!' + + t.equal(doc.json({ normal: true })[0].normal, str, 'json(normal)') + + t.equal(doc.text('normal'), str, 'text(normal): ') + + // doc.normalize() + // t.equal(doc.text('text'), str, 'normalize(): ') + + t.end() +}) + +test('text-reduced', function(t) { + let doc = nlp(`My dog LOVES pizza, and grapes!!`) + const str = 'my dog loves pizza and grapes' + + t.equal(doc.json({ reduced: true })[0].reduced, str, 'json(reduced)') + + t.equal(doc.text('reduced'), str, 'text(reduced): ') + + doc.normalize('reduced') + t.equal(doc.text('reduced'), str, 'normalize(reduced): ') + + t.end() +}) + +test('text-root', function(t) { + let doc = nlp(`My dog LOVES pizza, and grapes!!`) + const str = 'my dog love pizza and grape' + + t.equal(doc.json({ root: true })[0].root, str, 'json(root)') + + t.equal(doc.text('root'), str, 'text(root): ') + + doc.normalize('root') + t.equal(doc.text('root'), str, 'normalize(root): ') + + t.end() +}) diff --git a/tests/people.test.js b/tests/people.test.js new file mode 100644 index 000000000..7b08e8661 --- /dev/null +++ b/tests/people.test.js @@ -0,0 +1,52 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('people:', function(t) { + let doc = nlp('Mary is in the boat. Nancy is in the boat. Fred is in the boat. Jack is too.') + let arr = doc + .people() + .toLowerCase() + .out('array') + t.deepEqual(arr, ['mary', 'nancy', 'fred', 'jack'], 'people-easy') + + doc = nlp('jean jacket. jean Slkje') + arr = doc + .people() + .toLowerCase() + .out('array') + t.deepEqual(arr, ['jean slkje'], 'people-context') + + doc = nlp('The Bill was passed by James MacCarthur') + arr = doc + .people() + .toLowerCase() + .out('array') + t.deepEqual(arr, ['james maccarthur'], 'the-bill') + + doc = nlp('Rod MacDonald bought a Rod') + arr = doc + .people() + .toLowerCase() + .out('array') + t.deepEqual(arr, ['rod macdonald'], 'the-rod-1') + + doc = nlp('Rod L. MacDonald bought a lightening rod') + arr = doc + .people() + .toLowerCase() + .out('text') + t.deepEqual(arr, 'rod l. macdonald', 'the-rod-2') + + doc = nlp("Matt 'the doctor' Smith lasted three seasons.") + arr = doc + .people() + .toLowerCase() + .out() + t.deepEqual(arr, "matt 'the doctor' smith", 'nickname-1') + + doc = nlp("Randal Kieth Orton and Dwayne 'the rock' Johnson had a really funny fight.") + t.equal(doc.people(0).out('normal'), 'randal kieth orton', 'nickname-2a') + t.equal(doc.people(1).out('normal'), 'dwayne the rock johnson', 'nickname-2b') + + t.end() +}) diff --git a/tests/places.test.js b/tests/places.test.js new file mode 100644 index 000000000..a7cec26c7 --- /dev/null +++ b/tests/places.test.js @@ -0,0 +1,42 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('known-regions:', function(t) { + let arr = [ + ['i want to go to Ohio to see George Harrison', 'ohio'], + ['we are visiting Gloucestershire, before we leave', 'gloucestershire'], + ['manitoba is nice this time of year', 'manitoba'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .match('#Region') + .text('normal') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('unknown-places:', function(t) { + let arr = [ + ['live in the Rekcjd Province', 'rekcjd province'], + ['live in the Lekfjs District', 'lekfjs district'], + ['visiting Tojbs Kjeh Region', 'tojbs kjeh region'], + ['visiting the State of Lkjfhe', 'state of lkjfhe'], + ['see you in West Nunavut', 'west nunavut'], + ['see you in western Hunan', 'western hunan'], + ['see you in Northern Hunan province', 'northern hunan province'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .places(0) + .text('normal') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('mixed continents-places:', function(t) { + const doc = nlp('in north africa, eastern asia, guatemala, europe, north america, and japan') + t.equal(doc.places().length, 6, '6-places') + t.end() +}) diff --git a/tests/plugin/addTags.test.js b/tests/plugin/addTags.test.js new file mode 100644 index 000000000..d23ee83d5 --- /dev/null +++ b/tests/plugin/addTags.test.js @@ -0,0 +1,103 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('tagset-change-isA-basic', function(t) { + nlp.extend((Doc, world) => { + world.addTags({ + Doctor: { + isA: 'Person', + }, + }) + world.addWords({ + surgeon: 'Doctor', + 'surgeon general': 'Doctor', + }) + }) + let doc = nlp('the surgeon operated') + + //basic isA + t.equal(doc.match('#Doctor').out('normal'), 'surgeon', 'surgeon is a doctor') + t.equal(doc.match('#Person+').length, 1, 'doctor is a person') + + doc = nlp('lkjsdf').tag('#Person') + t.equal(doc.match('#Doctor').length, 0, 'person isnt a doctor, necessarily') + + doc = nlp('lkjsdf').tag('#Doctor') + t.equal(doc.match('#Person').length, 1, 'post-hoc tags work, too') + + //multi-word + doc = nlp('the surgeon general operated') + t.equal(doc.match('#Doctor').out('normal'), 'surgeon general', 'multi-word') + t.equal(doc.match('#Person').out('normal'), 'surgeon general', 'multi-word-isA') + t.end() +}) + +test('tagset-change-isA', function(t) { + nlp.extend((Doc, world) => { + world.addTags({ + Doctor: { + isA: 'Person', + notA: ['Foo'], + }, + }) + world.addWords({ + lkjj: 'Foo', + }) + }) + let doc = nlp('he is lkjj') + t.equal(doc.match('#Foo').out('normal'), 'lkjj', 'init-there') + doc.match('lkjj').tag('#Doctor') + + t.equal(doc.match('#Doctor').out('normal'), 'lkjj', 'doctor-tag-there') + t.equal(doc.match('#Foo').out('normal'), '', 'foo-is-gone') + + t.end() +}) + +test('tagset-remove-downward', function(t) { + nlp.extend((Doc, world) => { + world.addTags({ + Doctor: { + isA: 'Person', + }, + Surgeon: { + isA: 'Doctor', + }, + }) + }) + let doc = nlp('george is a person.') + doc.match('george').tag('Surgeon') + + t.ok(doc.has('#Surgeon'), 'Surgeon-tag-there') + t.ok(doc.has('#Doctor'), 'doctor-tag-there') + t.ok(doc.has('#Person'), 'person-tag-there') + + //remove one in the middle.. + doc.match('george').unTag('Person') + t.ok(doc.has('#Person') === false, 'person-tag-gone') + t.ok(doc.has('#Doctor') === false, 'doctor-tag-gone1') + t.ok(doc.has('#Surgeon') === false, 'Surgeon-tag-gone') + t.end() +}) + +test('tagset-remove-half-downward', function(t) { + nlp.extend((Doc, world) => { + world.addTags({ + Doctor: { + isA: 'Person', + }, + Surgeon: { + isA: 'Doctor', + }, + }) + }) + let doc = nlp('george is a person.') + doc.match('george').tag('Surgeon') + + //remove one just under the top.. + doc.match('george').unTag('Doctor') + t.ok(doc.has('#Person') === true, 'person-tag-there') + t.ok(doc.has('#Doctor') === false, 'doctor-tag-gone2') + t.ok(doc.has('#Surgeon') === false, 'Surgeon-tag-gone') + t.end() +}) diff --git a/tests/plugin/addWords.test.js b/tests/plugin/addWords.test.js new file mode 100644 index 000000000..ac5857e26 --- /dev/null +++ b/tests/plugin/addWords.test.js @@ -0,0 +1,29 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('persistent-lexicon-change', function(t) { + let nlp2 = nlp.clone() + let doc = nlp('he is marko') + t.equal(doc.match('#Place+').length, 0, 'default-no-place') + t.equal(doc.match('#Person+').length, 1, 'default-one-person') + + nlp2.extend((Doc, world) => { + world.addWords({ + marko: 'Place', + }) + }) + doc = nlp2('he is marko') + t.equal(doc.match('#Place+').length, 1, 'now-one-place') + t.equal(doc.match('#Person+').length, 0, 'now-no-person') + + nlp2.extend((Doc, world) => { + world.addWords({ + foo: 'Place', + }) + }) + doc = nlp2('he is marko') + t.equal(doc.match('#Place+').length, 1, 'still-one-place') + t.equal(doc.match('#Person+').length, 0, 'still-no-person') + + t.end() +}) diff --git a/tests/plugin/clone.test.js b/tests/plugin/clone.test.js new file mode 100644 index 000000000..73e989783 --- /dev/null +++ b/tests/plugin/clone.test.js @@ -0,0 +1,33 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('clone:', function(t) { + const arr = [ + 'he eats the alligator', + 'Jumanji is the best move. He eats cheese.', + 'Uperman is wayyyy better than batman!', + ] + arr.forEach(function(str) { + let m = nlp(str) + t.equal(m.out(), str, 'equals input - ' + m.out()) + + let up = m.clone().toUpperCase() + t.notEqual(str, up.out(), 'neg not equal - ' + str) + + let adv = m + .clone() + .match('#Verb') + .append('really') + t.notEqual(str, adv.out(), 'adv not equal - ' + str) + + let rm = m + .clone() + .match('#Verb') + .delete('#Verb') + t.notEqual(str, rm.out(), 'rm not equal - ' + str) + + let tag = m.clone().tag('#Verb') + t.notEqual(m.match('#Verb').text(), tag.match('#Verb').text(), 'rm not equal - ' + str) + }) + t.end() +}) diff --git a/tests/plugin/plugin.test.js b/tests/plugin/plugin.test.js new file mode 100644 index 000000000..a1c265e66 --- /dev/null +++ b/tests/plugin/plugin.test.js @@ -0,0 +1,129 @@ +const test = require('tape') +const nlp = require('../_lib') + +const myPlugin = function(Doc, world) { + /** add a method */ + Doc.prototype.beNice = function() { + this.match('#Infinitive').prepend('kindly') + return this + } + /** add some tags */ + world.addTags({ + Character: { + isA: 'Person', + notA: 'Adjective', + }, + }) + /** add some words */ + world.addWords({ + gonzo: 'MaleName', + kermit: 'Frog', + 'minnie mouse': 'Character', + }) + /** post-process tagger */ + world.postProcess(doc => { + doc.match('light the lights').tag('#Verb . #Plural') + }) +} + +nlp.extend(myPlugin) + +//TODO: not sure why this doesn't pass when running all-tests +// must be a race-condition? +// test('plugin post-process tagger', function(t) { +// let doc = nlp(`it's time to light the lights.`) +// t.equal(doc.has('#Verb the #Plural'), true, 'post-tagger ran') +// t.end() +// }) + +test('plugin adds a method', function(t) { + let doc = nlp(`wash the floor`) + doc.beNice() + t.equal(doc.text(), 'kindly wash the floor', 'beNice method worked') + t.end() +}) + +test('plugin adds a tag', function(t) { + let doc = nlp(`goofy`) + t.equal(doc.has('#Adjective'), true, 'starts adjective') + // random unknown tag + doc.tag('FooBar') + // our tag + doc.tag('Character') + t.equal(doc.has('#Character'), true, 'has given tag') + t.equal(doc.has('#Person'), true, 'has implied tag') + t.equal(doc.has('#FooBar'), true, 'has unrelated tag') + t.equal(doc.has('#Adjective'), false, 'missing notA tag') + t.end() +}) + +test('plugin adds words', function(t) { + let doc = nlp(`gonzo, minnie mouse and kermit the frog`) + t.equal(doc.match('gonzo').has('#MaleName'), true, 'new word existing tag') + t.equal(doc.match('gonzo').has('#Person'), true, 'new word implied tag') + + t.equal(doc.match('#Frog').text('normal'), 'kermit', 'new word new tag') + + let m = doc.match('minnie mouse') + t.equal(m.has('#Character #Character'), true, 'multi word given tag') + t.equal(m.has('#Person #Person'), true, 'multi word implied tag') + t.end() +}) + +// test('extend-tagset-flat', function(t) { +// const tagSet = { +// Color: {}, +// } +// const lexicon = { +// 'mother of pearl': 'Color', +// } +// nlp.addTags(tagSet) +// var m = nlp('it is mother of pearl', lexicon).match('#Color+') +// t.equal(m.out('normal'), 'mother of pearl', 'text found') +// t.ok(m.has('#Noun'), 'it does not get in the way of the tagger') +// t.end() +// }) + +test('extend-tagset-nested', function(t) { + const tagSet = { + Color: {}, + OffWhite: { + isA: 'Color', + }, + } + nlp.extend((Doc, world) => { + world.addTags(tagSet) + }) + const lexicon = { + 'mother of pearl': 'OffWhite', + } + const m = nlp('it is mother of pearl', lexicon).match('#OffWhite') + t.equal(m.out('normal'), 'mother of pearl', 'text found') + // t.equal(m.has('#Noun'), true, 'it does not get in the way of the tagger') + t.equal(m.has('#Color'), true, 'has isA tag, too') + t.end() +}) + +test('basic-plugin', function(t) { + nlp.extend((Doc, world) => { + world.addWords({ + trex: 'Dinosaur', + }) + world.addTags({ + Dinosaur: { + isA: 'Animal', + }, + Animal: { + isA: 'Noun', + }, + }) + world.postProcess(d => { + d.match('/uuu/').tag('Exaggeration') + }) + }) + const doc = nlp('i saw a HUUUUGE trex') + t.equal(doc.match('#Exaggeration').out('normal'), 'huuuuge', 'regex-works') + t.equal(doc.match('#Dinosaur').out('normal'), 'trex', 'lexicon-works') + t.equal(doc.match('#Animal').out('normal'), 'trex', 'tagset-works') + t.end() +}) diff --git a/tests/possessives.test.js b/tests/possessives.test.js new file mode 100644 index 000000000..f8712d660 --- /dev/null +++ b/tests/possessives.test.js @@ -0,0 +1,31 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('possessives tagger', function(t) { + const arr = [`Spencer's`, `Spencer Kelly's`, `Spencer C. Kelly's`, `Union Corp's`, `Los Angeles's`] + arr.forEach(a => { + const doc = nlp(a) + const m = doc.possessives() + t.equal(m.length, 1, 'one possessive -' + a) + t.equal(m.out(), a, 'possessive match -' + a) + }) + t.end() +}) + +test('possessives strip', function(t) { + const arr = [ + [`Spencer's`, 'Spencer'], + [`Corey Hart's`, 'Corey Hart'], + [`Corey M. Hart's`, 'Corey M. Hart'], + [`Spencer C. Kelly's`, 'Spencer C. Kelly'], + [`Agility Inc's`, 'Agility Inc'], + [`University of Wisconsin's`, 'University of Wisconsin'], + [`Los Angeles's`, 'Los Angeles'], + ] + arr.forEach(a => { + const doc = nlp(a[0]) + doc.possessives().strip() + t.equal(doc.out('text'), a[1], a[0]) + }) + t.end() +}) diff --git a/tests/punctuation.test.js b/tests/punctuation.test.js new file mode 100644 index 000000000..c695546fa --- /dev/null +++ b/tests/punctuation.test.js @@ -0,0 +1,55 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('normalize elipses', function(t) { + const str = `[hello] spencęr…` + const doc = nlp(str) + t.equal(doc.text(), str, 'text out-1') + t.equal(doc.text('normal'), 'hello spencer...', 'normal out-1') + t.end() +}) + +test('normalize question mark', function(t) { + const str = `hello, Spencęr???` + const doc = nlp(str) + t.equal(doc.text(), str, 'text out-2') + t.equal(doc.text('normal'), 'hello, spencer?', 'normal out-2') + t.end() +}) + +test('hyphenated', function(t) { + let doc = nlp('and check this out! a walk-in microwave.') + doc.hyphenated().deHyphenate() + t.equal(doc.text(), 'and check this out! a walk in microwave.', 'dehyphenate') + t.end() +}) + +test('normalize unicode', function(t) { + // const str = `• Spencęr & JOhn™ ⟨lmt⟩.` + const str = ` Spencęr & JOhn™ ⟨lmt⟩.` + const doc = nlp(str) + t.equal(doc.text(), str, 'text out') + t.equal(doc.text('reduced'), 'spencer & john lmt', 'normal out') + t.end() +}) + +test('normalize quotes ', function(t) { + const str = `،one’ «two» ‘three’ “four” 'five' "six."` + const doc = nlp(str) + t.equal(doc.text(), str, 'text out-3') + t.equal(doc.text('clean'), 'one two three four five six.', 'normal out-3') + t.end() +}) + +test('toParentheses', function(t) { + let doc = nlp(`you could still go to McGill, the Harvard of Canada!`) + doc.match('the harvard of #Place').toParentheses() + t.equal(doc.text(), 'you could still go to McGill, (the Harvard of Canada)!', 'toparentheses') + t.end() +}) +test('toQuotation', function(t) { + let doc = nlp(`you could still go to McGill, the Harvard of Canada!`) + doc.match('harvard of #Place').toQuotation() + t.equal(doc.text(), 'you could still go to McGill, the "Harvard of Canada"!', 'toparentheses') + t.end() +}) diff --git a/tests/quotation-tag.test.js b/tests/quotation-tag.test.js new file mode 100644 index 000000000..5e513c5aa --- /dev/null +++ b/tests/quotation-tag.test.js @@ -0,0 +1,224 @@ +const test = require('tape') +const nlp = require('./_lib') + +function testAllQuotes(a, t) { + const str = nlp(a[0]) + .quotations() + .out('normal') + t.equal(str, a[1], a[0]) +} + +test('quotation test:', function(t) { + ;[ + [`he is "really good"`, `really good`], + [`he is "really good" i guess`, `really good`], + [`he is "good" i guess`, `good`], + [`he is "completely and utterly great" i guess`, `completely and utterly great`], + [`“quote”`, `quote`], + [`“quote is here”`, `quote is here`], + ].forEach(function(a) { + const str = nlp(a[0]) + .quotations() + .out('normal') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('Quotations - U+0022 to U+0022', function(t) { + ;[ + ['he is \u0022really good\u0022', 'really good'], + ['he is \u0022really good\u0022 i guess', 'really good'], + ['he is not \u0022good\u0022 at all :/', 'good'], + ['\u0022quote\u0022', 'quote'], + ['\u0022a quote here\u0022', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+FF02 to U+FF02', function(t) { + ;[ + ['he is \uFF02really good\uFF02', 'really good'], + ['he is \uFF02really good\uFF02 i guess', 'really good'], + ['he is not \uFF02good\uFF02 at all :/', 'good'], + ['\uFF02quote\uFF02', 'quote'], + ['\uFF02a quote here\uFF02', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+0027 to U+0027', function(t) { + ;[ + ['he is \u0027really good\u0027', 'really good'], + ['he is \u0027really good\u0027 i guess', 'really good'], + ['he is not \u0027good\u0027 at all :/', 'good'], + ['\u0027quote\u0027', 'quote'], + ['\u0027a quote here\u0027', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) +// +test('Quotations - U+201C to U+201D', function(t) { + ;[ + ['he is \u201Creally good\u201D', 'really good'], + ['he is \u201Creally good\u201D i guess', 'really good'], + ['he is not \u201Cgood\u201D at all :/', 'good'], + ['\u201Cquote\u201D', 'quote'], + ['\u201Ca quote here\u201D', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+2018 to U+2019', function(t) { + ;[ + ['he is \u2018really good\u2019', 'really good'], + ['he is \u2018really good\u2019 i guess', 'really good'], + ['he is not \u2018good\u2019 at all :/', 'good'], + ['\u2018quote\u2019', 'quote'], + ['\u2018a quote here\u2019', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+201F to U+201D', function(t) { + ;[ + ['he is \u201Freally good\u201D', 'really good'], + ['he is \u201Freally good\u201D i guess', 'really good'], + ['he is not \u201Fgood\u201D at all :/', 'good'], + ['\u201Fquote\u201D', 'quote'], + ['\u201Fa quote here\u201D', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+201B to U+2019', function(t) { + ;[ + ['he is \u201Breally good\u2019', 'really good'], + ['he is \u201Breally good\u2019 i guess', 'really good'], + ['he is not \u201Bgood\u2019 at all :/', 'good'], + ['\u201Bquote\u2019', 'quote'], + ['\u201Ba quote here\u2019', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+201E to U+201D', function(t) { + ;[ + ['he is \u201Ereally good\u201D', 'really good'], + ['he is \u201Ereally good\u201D i guess', 'really good'], + ['he is not \u201Egood\u201D at all :/', 'good'], + ['\u201Equote\u201D', 'quote'], + ['\u201Ea quote here\u201D', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+2E42 to U+201D', function(t) { + ;[ + ['he is \u2E42really good\u201D', 'really good'], + ['he is \u2E42really good\u201D i guess', 'really good'], + ['he is not \u2E42good\u201D at all :/', 'good'], + ['\u2E42quote\u201D', 'quote'], + ['\u2E42a quote here\u201D', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+201A to U+2019', function(t) { + ;[ + ['he is \u201Areally good\u2019', 'really good'], + ['he is \u201Areally good\u2019 i guess', 'really good'], + ['he is not \u201Agood\u2019 at all :/', 'good'], + ['\u201Aquote\u2019', 'quote'], + ['\u201Aa quote here\u2019', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+00AB to U+00BB', function(t) { + ;[ + ['he is \u00ABreally good\u00BB', 'really good'], + ['he is \u00ABreally good\u00BB i guess', 'really good'], + ['he is not \u00ABgood\u00BB at all :/', 'good'], + ['\u00ABquote\u00BB', 'quote'], + ['\u00ABa quote here\u00BB', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+2039 to U+203A', function(t) { + ;[ + ['he is \u2039really good\u203A', 'really good'], + ['he is \u2039really good\u203A i guess', 'really good'], + ['he is not \u2039good\u203A at all :/', 'good'], + ['\u2039quote\u203A', 'quote'], + ['\u2039a quote here\u203A', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+2035 to U+2032', function(t) { + ;[ + ['he is \u2035really good\u2032', 'really good'], + ['he is \u2035really good\u2032 i guess', 'really good'], + ['he is not \u2035good\u2032 at all :/', 'good'], + ['\u2035quote\u2032', 'quote'], + ['\u2035a quote here\u2032', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+2036 to U+2033', function(t) { + ;[ + ['he is \u2036really good\u2033', 'really good'], + ['he is \u2036really good\u2033 i guess', 'really good'], + ['he is not \u2036good\u2033 at all :/', 'good'], + ['\u2036quote\u2033', 'quote'], + ['\u2036a quote here\u2033', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+2037 to U+2034', function(t) { + ;[ + ['he is \u2037really good\u2034', 'really good'], + ['he is \u2037really good\u2034 i guess', 'really good'], + ['he is not \u2037good\u2034 at all :/', 'good'], + ['\u2037quote\u2034', 'quote'], + ['\u2037a quote here\u2034', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+301D to U+301E', function(t) { + ;[ + ['he is \u301Dreally good\u301E', 'really good'], + ['he is \u301Dreally good\u301E i guess', 'really good'], + ['he is not \u301Dgood\u301E at all :/', 'good'], + ['\u301Dquote\u301E', 'quote'], + ['\u301Da quote here\u301E', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+0060 to U+00B4', function(t) { + ;[ + ['he is \u0060really good\u00B4', 'really good'], + ['he is \u0060really good\u00B4 i guess', 'really good'], + ['he is not \u0060good\u00B4 at all :/', 'good'], + ['\u0060quote\u00B4', 'quote'], + ['\u0060a quote here\u00B4', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) + +test('Quotations - U+301F to U+301E', function(t) { + ;[ + ['he is \u301Freally good\u301E', 'really good'], + ['he is \u301Freally good\u301E i guess', 'really good'], + ['he is not \u301Fgood\u301E at all :/', 'good'], + ['\u301Fquote\u301E', 'quote'], + ['\u301Fa quote here\u301E', 'a quote here'], + ].forEach(a => testAllQuotes(a, t)) + t.end() +}) diff --git a/tests/quotations.test.js b/tests/quotations.test.js new file mode 100644 index 000000000..3bc781a7d --- /dev/null +++ b/tests/quotations.test.js @@ -0,0 +1,46 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('quotation test', function(t) { + const arr = [ + ['so I said "nah forget it"', 'nah forget it'], + ['so I said "nah, forget it" go home to bel-air!', 'nah, forget it'], + ["so I said 'nah, forget it' go home to bel-air!", 'nah, forget it'], + ['so I said "nah" go home to bel-air!', 'nah'], + ["so 'as if' i said", 'as if'], + ["the 'truthiness' i said", 'truthiness'], + ['yeah, “fun” and stuff', 'fun'], + ['“Fun” and stuff', 'fun'], + //dangling start/end + ["'twas good cookin", ''], + ["twas good cookin'", ''], + // ["twas 'good cookin'", 'good cookin'], + // ["'twas 'good cookin'", 'twas good cookin'], + [`and "Dig Your own grave and Save".`, 'dig your own grave and save'], + ] + arr.forEach(function(a) { + const r = nlp(a[0]) + const str = r.quotations().out('normal') + const msg = a[0] + ' - ' + str + t.equal(str, a[1], msg) + }) + t.end() +}) + +// test('multiple quotation test', function(t) { +// const arr = [ +// [`My "String" "with many" adjacent "nested" 'quotes'`, ['string', 'with many', 'nested', 'quotes']], +// [`My "String 'with manys' adjacent" "nested" 'quotes'`, ['string with manys adjacent', 'nested', 'quotes']], +// [ +// `"May's" 'third day' 'will be a "really cold" day' "in a" 'really cold "month"'`, +// ["may's", 'third day', 'will be a really cold day', 'in a', 'really cold month'], +// ], +// ] +// arr.forEach(function(a) { +// const r = nlp(a[0]) +// const str = r.quotations().out('array') +// const msg = a[0] + ' - ' + str +// t.deepEqual(str, a[1], msg) +// }) +// t.end() +// }) diff --git a/tests/random.test.js b/tests/random.test.js new file mode 100644 index 000000000..4e58b5e61 --- /dev/null +++ b/tests/random.test.js @@ -0,0 +1,71 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('random', function(t) { + const r = nlp('one two three four five six') + let arr = r + .terms() + .random() + .out('array') + t.equal(arr.length, 1, 'default is size 1') + + arr = r + .terms() + .random(2) + .out('array') + t.equal(arr.length, 2, 'size 2') + + arr = r + .terms() + .random(3) + .out('array') + t.equal(arr.length, 3, 'size 3') + + arr = r + .terms() + .random(4) + .out('array') + t.equal(arr.length, 4, 'size 4') + + arr = r + .terms() + .random(5) + .out('array') + t.equal(arr.length, 5, 'size 5') + + arr = r + .terms() + .random(6) + .out('array') + t.equal(arr.length, 6, 'size 6') + + arr = r + .terms() + .random(7) + .out('array') + t.equal(arr.length, 6, '7 is too big') + + arr = r + .terms() + .random(17) + .out('array') + t.equal(arr.length, 6, '17 is too big') + + t.end() +}) + +test('random-null', function(t) { + const r = nlp('toronto') + let arr = r + .match('#Person') + .random(5) + .out('array') + t.equal(arr.length, 0, 'random can be empty') + + arr = r + .match('#Place+') + .random(5) + .out('array') + t.equal(arr.length, 1, 'random can be full-match') + t.end() +}) diff --git a/tests/reduced.test.js b/tests/reduced.test.js new file mode 100644 index 000000000..a708c3069 --- /dev/null +++ b/tests/reduced.test.js @@ -0,0 +1,12 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('reduced matches', function(t) { + let doc = nlp(`the donkey's hotel`) + t.equals(doc.has('donkey'), true, 'apostrophe-s') + + doc = nlp(`the donkeys' hotel`) + t.equals(doc.has('donkeys'), true, 's-apostrophe') + + t.end() +}) diff --git a/tests/remove.test.js b/tests/remove.test.js new file mode 100644 index 000000000..2d25adf54 --- /dev/null +++ b/tests/remove.test.js @@ -0,0 +1,34 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('remove-everything-basic', function(t) { + let doc = nlp(`2pm`) + doc.remove('#Time') + t.equal(doc.text(), '', 'empty-text') + t.equal(doc.length, 0, '0-length') + t.equal(doc.found, false, 'not-found') + + doc.remove('.') + t.equal(doc.found, false, 'still-not-found') + t.end() +}) + +test('remove-everything-nested', function(t) { + let doc = nlp(`see term. term. term after.`) + t.equal(doc.length, 3, 'start-3') + + doc.remove('term') + t.equal(doc.length, 2, 'only-2 now') + + doc.remove('after') + t.equal(doc.length, 1, 'only-1 now') + + doc.remove('.') + t.equal(doc.length, 0, '0 now') + t.equal(doc.found, false, 'not-found') + + doc.remove('.') + t.equal(doc.found, false, 'still-not-found') + + t.end() +}) diff --git a/tests/reservedwords.test.js b/tests/reservedwords.test.js new file mode 100644 index 000000000..a808359db --- /dev/null +++ b/tests/reservedwords.test.js @@ -0,0 +1,115 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('reserved words:', function(t) { + const reserved = [ + 'abstract', + 'boolean', + 'break', + 'byte', + 'case', + 'catch', + 'char', + 'class', + 'const', + 'constructor', + 'continue', + 'debugger', + 'default', + 'delete', + 'do', + 'double', + 'else', + 'enum', + 'export', + 'extends', + 'false', + 'final', + 'finally', + 'float', + 'for', + 'function', + 'goto', + 'if', + 'implements', + 'import', + 'in', + 'instanceof', + 'int', + 'interface', + 'let', + 'long', + 'native', + 'new', + 'null', + 'package', + 'private', + 'protected', + 'prototype', + 'public', + 'return', + 'short', + 'static', + 'super', + 'switch', + 'synchronized', + 'this', + 'throw', + 'throws', + 'transient', + 'true', + 'try', + 'typeof', + 'var', + 'void', + 'volatile', + 'while', + 'with', + 'yeild', + '__prototype__', + '&&', + '||', + '|', + "'", + '&', + 'Math.PI', + 12e34, + '#§$%', + 'π', + 'привет', + // 'hasOwnProperty', + 'café', + '$$$', + 1e2, + '{}', + '[]', + 'constructor', + 'prototype', + ')&@)^', + ' -@%@', + '-constructor', + '#!^@#$', + '..(', + ] + const str = reserved.join(' ') + const r = nlp(str) + t.equal(r.out('text'), str, 'reserved-words-are-printed') + t.equal(r.terms().length, reserved.length, 'reserved-length') + t.ok(r.contractions().data(), 'runs contractions subset') + t.ok(r.parentheses().data(), 'runs parentheses subset') + t.ok(r.lists().data(), 'runs lists subset') + t.ok(r.terms().data(), 'runs terms subset') + t.ok(r.pronouns().data(), 'runs pronouns subset') + t.end() +}) + +test('co-erce reserved words', function(t) { + const r = nlp('constructor prototype') + r.tag('Verb') + t.ok(r.match('#Verb').data(), 'runs tag/match') + r.tag('Adjective') + t.ok(r.match('#Noun').data(), 'runs untag') + t.equal(r.terms().slice(0, 2).length, 2, 'runs slice') + t.ok(r.append('constructor').text(), 'runs append') + t.end() +}) diff --git a/tests/setTag.test.js b/tests/setTag.test.js new file mode 100644 index 000000000..4cc076e2a --- /dev/null +++ b/tests/setTag.test.js @@ -0,0 +1,41 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('custom-tags-persist', function(t) { + let r = nlp('i am two years older now') + let two = r.match('#Value').tag('#FunTag') + two.replaceWith('never') + t.equal(two.has('#FunTag'), false, 'custom tag is forgotten') + + r = nlp('i am two years older now') + two = r.match('#Value').tag('#FunTag') + two.toUpperCase().trim() + t.equal(two.text(), 'TWO', 'term transformed') + t.equal(two.has('#Value'), true, 'original tag stays over transformations') + t.equal(two.has('#FunTag'), true, 'custom tag stays over transformations') + + // r = nlp('i am two years older now') + // two = r.match('#Value').tag('#FunTag') + // two.toUpperCase() + // two.values().toNumber() + // t.equal(two.has('#FunTag'), true, 'custom tag stays over transformations') + + // r = nlp('june 1999') + // r.values().toNumber() + // const year = r.match('#Year') + // t.equal(year.out('normal'), '1999', 'year-stays-a-year') + + //not sure if these should pass.. + // r = nlp('i am two years older now') + // r.match('am').tag('#FunTag') + // r = r.sentences().toFutureTense().toPresentTense().toPastTense() + // const verb = r.match('#FunTag') + // t.equal(verb.out('normal'), 'was', 'tag stays over sentence-change') + + // r = nlp('walked').tag('#FunTag'); + // r = r.verbs().toFutureTense().toPresentTense().toPastTense(); + // verb = r.match('#FunTag'); + // t.equal(verb.out('normal'), 'walked', 'tag stays over verb-change'); + + t.end() +}) diff --git a/tests/slash.test.js b/tests/slash.test.js new file mode 100644 index 000000000..7611c16f4 --- /dev/null +++ b/tests/slash.test.js @@ -0,0 +1,45 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('slash whitespace', function(t) { + let str = 'left his / her backpack ' + let doc = nlp(str) + t.equal(doc.out(), str, 'slash with normal spaces') + + str = 'left his/her backpack ' + doc = nlp(str) + t.equal(doc.out(), str, 'slash with no spaces') + + str = 'left his / her backpack' + doc = nlp(str) + t.equal(doc.out(), str, 'slash with lots of spaces') + t.end() +}) + +test('slash match', function(t) { + let str = 'left his / her backpack ' + let doc = nlp(str) + t.equal(doc.has('his'), true, 'slash with normal spaces - his') + t.equal(doc.has('her'), true, 'slash with normal spaces - her') + // t.equal(doc.has('his / her'), true, 'slash with normal spaces - his / her') + + str = 'left his/her backpack ' + doc = nlp(str) + t.equal(doc.has('his'), true, 'slash with no spaces - his') + t.equal(doc.has('her'), true, 'slash with no spaces - her') + t.equal(doc.has('his/her'), true, 'slash with no spaces - his/her') + + str = 'left his / her backpack' + doc = nlp(str) + t.equal(doc.has('his'), true, 'slash with lots of spaces') + t.equal(doc.has('her'), true, 'slash with lots of spaces') + + str = 'left his/her/their backpack ' + doc = nlp(str) + t.equal(doc.has('his'), true, 'three-slash - his') + t.equal(doc.has('her'), true, 'three-slash - her') + t.equal(doc.has('their'), true, 'three-slash - their') + t.equal(doc.has('his/her/their'), true, 'three-slash - his/her/their ') + + t.end() +}) diff --git a/tests/slashes.test.js b/tests/slashes.test.js new file mode 100644 index 000000000..119f54fee --- /dev/null +++ b/tests/slashes.test.js @@ -0,0 +1,23 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('slashes-basic', function(t) { + let doc = nlp(`spencer is/was trying.`) + t.equal(doc.terms().length, 3, 'three terms') + t.equal(doc.match('#Person #Verb trying').found, true, 'verb trying') + // t.equal(doc.match('#Person is trying').found, true, 'is trying') + t.end() +}) + +test('slashes-complex', function(t) { + // doc = nlp(`spencer is/was trying`) + // 1. doc.has('#PresentTense') == true (choose first) + // 2. doc.has('#Verb') (only common tags) + // 3. doc.has('#PastTense') && doc.has('#PresentTense') :/ + + // doc = nlp(`spencer is/was trying`) + // 1b. doc.has('is') == true (choose first) + // 2b. doc.has('was') == true (find both) + // 3b. doc.has('is') == false (find none) + t.end() +}) diff --git a/tests/sort.test.js b/tests/sort.test.js new file mode 100644 index 000000000..ba7e32286 --- /dev/null +++ b/tests/sort.test.js @@ -0,0 +1,95 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('sortAlpha:', function(t) { + const str = 'John xoo, John fredman, John davis, John fredman,' + let r = nlp(str) + r = r.split('@hasComma') + r.sort('alpha') + const want = ['John davis,', 'John fredman,', 'John fredman,', 'John xoo,'] + t.deepEqual(r.out('array'), want, 'sort-alpha') + t.end() +}) + +test('sortSequential:', function(t) { + const str = 'John xoo, John fredman, John davis' + let r = nlp(str) + r = r.split('@hasComma') + r.sort('alphabetical') + r.sort('seq') + const want = ['John xoo,', 'John fredman,', 'John davis'] + t.deepEqual(r.out('array'), want, 'sort-chron') + t.end() +}) + +test('reverse:', function(t) { + const str = 'John xoo, John fredman, John davis' + let r = nlp(str) + r = r.split('@hasComma') + r.sort('alphabetical') + r = r.reverse() + const want = ['John xoo,', 'John fredman,', 'John davis'] + t.deepEqual(r.out('array'), want, 'alpha-reverse') + t.end() +}) + +test('length:', function(t) { + const str = 'Amy, John Fredman, Dr. Bill, Alexis Smithsonian' + let r = nlp(str) + r = r.split('@hasComma') + r.sort('length') + r = r.reverse() + const want = ['Amy,', 'Dr. Bill,', 'John Fredman,', 'Alexis Smithsonian'] + t.deepEqual(r.out('array'), want, 'sort length') + t.end() +}) + +test('wordCount:', function(t) { + const str = 'John Fredman, Amy, Dr. Bill G. Gates' + let r = nlp(str) + r = r.split('@hasComma') + r.sort('wordCount') + r.reverse() + const want = ['Dr. Bill G. Gates', 'John Fredman,', 'Amy,'] + t.deepEqual(r.out('array'), want, 'sort-wordcount') + t.end() +}) + +test('unique:', function(t) { + const str = 'John xoo, John fredman, john xoo, John davis' + let r = nlp(str) + r = r.split('@hasComma') + r = r.unique() + const want = ['John xoo,', 'John fredman,', 'John davis'] + t.deepEqual(r.out('array'), want, 'sort-unique') + t.end() +}) + +test('custom-sort:', function(t) { + let doc = nlp('Eeny, meeny, miny, moe') + let terms = doc.terms() + terms.sort((a, b) => { + a = a.text('normal') + b = b.text('normal') + if (a.length > b.length) { + return -1 + } + if (a.length < b.length) { + return 1 + } + return 0 + }) + let arr = terms.map(d => d.text('normal')) + t.deepEqual(arr, ['meeny, ', 'eeny, ', 'miny, ', 'moe'], 'custom sort output') + t.end() +}) + +test('frequency:', function(t) { + const str = 'John xoo, John fredman, john xoo, John davis' + let r = nlp(str) + r = r.split('@hasComma') + const a = r.out('frequency') + t.equal(a[0].reduced, 'john xoo', 'topk is sorted') + t.equal(a[0].count, 2, 'topk finds two') + t.end() +}) diff --git a/tests/tagger/inline.test.js b/tests/tagger/inline.test.js new file mode 100644 index 000000000..03ccbfc75 --- /dev/null +++ b/tests/tagger/inline.test.js @@ -0,0 +1,29 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('inline tagging linear:', function(t) { + let r = nlp('one two three four') + + r.match('one two three').tag('. #Person .') + let found = r.match('#Person').out('normal') + t.equal(found, 'two', 'skip-tag-skip') + + r.match('one two three').tag('#FooBar .') + found = r.match('#FooBar').out('normal') + t.equal(found, 'one', 'tag-skip-null') + + r.match('two three').tag('#Two #Three #Four') + t.equal(r.match('#Two').out('normal'), 'two', 'two-is-two') + t.equal(r.match('#Three').out('normal'), 'three', 'three-is-three') + t.equal(r.match('#Four').out('normal'), '', 'four is ignored') + + t.end() +}) + +test('compound tags from lexicon:', function(t) { + const doc = nlp('it was cold') + const arr = doc.match('#Verb+') + t.equal(arr.length, 1, 'one verb') + t.equal(arr.has('#PastTense'), true, 'past-tense') + t.end() +}) diff --git a/tests/tagger/lexicon.test.js b/tests/tagger/lexicon.test.js new file mode 100644 index 000000000..eba60544f --- /dev/null +++ b/tests/tagger/lexicon.test.js @@ -0,0 +1,105 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('default lexicon:', function(t) { + let arr = [ + ['great', 'Adjective'], + ['walked', 'PastTense'], + ['singing', 'Gerund'], + ['funniest', 'Superlative'], + ['sillier', 'Comparative'], + ['the', 'Determiner'], + ['iraqi', 'Demonym'], + ['december', 'Date'], + ['fifth', 'Value'], + ['suddenly', 'Adverb'], + ['shanghai', 'City'], + ['google', 'Organization'], + ] + arr.forEach(function(a) { + const doc = nlp(a[0]) + t.equal(doc.has('#' + a[1]), true, a[0]) + }) + t.end() +}) + +test('root-in-lexicon:', function(t) { + let arr = [ + ['wash', 'Infinitive'], + ['rewash', 'Infinitive'], + ['re-wash', 'Infinitive'], + ['re-washed', 'PastTense'], + ['rewashed', 'PastTense'], + ['rewashes', 'PresentTense'], + ['rewashing', 'Gerund'], + + ['repurchase', 'Infinitive'], + ['re-purchase', 'Infinitive'], + ['unpurchase', 'Infinitive'], + ['purchased', 'PastTense'], + ['unpurchasing', 'Gerund'], + ['unpurchases', 'PresentTense'], + ['resolve', 'Infinitive'], + ['restructure', 'Infinitive'], + ['reconcile', 'Infinitive'], + ['repeat', 'Infinitive'], + ] + arr.forEach(function(a) { + const doc = nlp(a[0]) + t.equal(doc.has('#' + a[1]), true, a[0]) + }) + t.end() +}) + +test('adjusted lexicon:', function(t) { + //place new words + let lexicon = { + geneva: 'Person', + lkjj: 'Adjective', + 'donkey kong': 'City', + } + + const arr = [ + ['geneva is nice', '#Person #Copula #Adjective'], + ['he is lkjj', '#Pronoun #Copula #Adjective'], + ['donkey kong wins the award', '#City #City #Verb #Determiner #Noun'], + ] + arr.forEach(function(a) { + const doc = nlp(a[0], lexicon) + t.equal(doc.has(a[1]), true, a[0]) + }) + // + //set gender from lexicon + const doc = nlp('Kelly', lexicon) + t.equal(doc.has('#FemaleName'), true, 'kelly-female') + //set as male: + lexicon = { + kelly: 'MaleName', + } + const doc2 = nlp('Kelly', lexicon) + t.equal(doc2.has('#MaleName'), true, 'kelly-male') + + //gender follows lumping + const doc3 = nlp('Kelly Gruber', lexicon) + t.equal(doc3.has('#MaleName #LastName'), true, 'kelly-gruber') + + t.end() +}) + +test('tricky lexicon:', function(t) { + let lexicon = { + 'bed bath and beyond': 'Organization', + } + let r = nlp('shopping at Bed Bath and Beyond, the store', lexicon) + let str = r.match('#Organization+').out('normal') + t.equal(str, 'bed bath and beyond', 'four-word') + + r = nlp('shopping at Bed Bath and-beyond the store', lexicon) + str = r.match('#Organization+').out('normal') + t.equal(str, 'bed bath and beyond', 'partially-hyphenated-word') + + r = nlp('shopping at Bed-bath and-beyond the store', lexicon) + str = r.match('#Organization+').out('normal') + t.equal(str, 'bed bath and beyond', 'many-hyphenated-word') + t.end() +}) diff --git a/tests/tagger/multi.test.js b/tests/tagger/multi.test.js new file mode 100644 index 000000000..336896972 --- /dev/null +++ b/tests/tagger/multi.test.js @@ -0,0 +1,44 @@ +const test = require('tape') +const nlp = require('../_lib') + +const lexicon = { + 'Jardas al Abid': 'Place', + 'Umm Ar Rizam': 'Place', + Tobruk: 'Place', +} + +test('user-lex-with-hyphenation:', function(t) { + const sentence = + 'A suicide attack hit the centre of Jardas-al-Abid killing one person (and the attacker) and injuring more than twenty.' + const found = nlp(sentence, lexicon).match('#Place+') + t.equal('jardas al abid', found.eq(0).text('normal'), 'found-place1') + t.equal(lexicon, lexicon, 'lexicon-unchanged') + t.end() +}) + +test('user-lex-with-possessive form:', function(t) { + const sentence = + "A suicide attack hit Jardas al Abid's center killing one person (and the attacker) and injuring more than twenty." + const found = nlp(sentence, lexicon).match('#Place+') + t.equal("jardas al abid's", found.eq(0).text('normal'), 'found-place2') + t.equal(lexicon, lexicon, 'lexicon-unchanged') + t.end() +}) + +test('user-lex-with-proper name in front:', function(t) { + const sentence = + "A suicide attack hit Lybia's Jardas al Abid city killing one person (and the attacker) and injuring more than twenty." + const found = nlp(sentence, lexicon).match('#Place+') + t.equal('jardas al abid', found.eq(0).text('normal'), 'found-place3') + t.equal(lexicon, lexicon, 'lexicon-unchanged') + t.end() +}) + +test('user-lex-with-punctuation:', function(t) { + const sentence = + 'A suicide attack hit Jardas al Abid, which killed one person (and the attacker) and injured more than twenty.' + const found = nlp(sentence, lexicon).match('#Place+') + t.equal('jardas al abid', found.eq(0).text('normal'), 'found-place4') + t.equal(lexicon, lexicon, 'lexicon-unchanged') + t.end() +}) diff --git a/tests/tagger/organization.test.js b/tests/tagger/organization.test.js new file mode 100644 index 000000000..472e1b617 --- /dev/null +++ b/tests/tagger/organization.test.js @@ -0,0 +1,25 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('organization test', function(t) { + const arr = [ + 'google', + 'google inc', + 'Capital One', + 'HSBC', + 'NASA', + '7-eleven', + 'al qaeda', + 'FBI', + 'monsanto', + 'Johnson & Johnson', + // 'Johnson & Johnson LLC', + ] + arr.forEach(function(str) { + const r = nlp(str) + const orgs = r.match('#Organization+') + const msg = orgs.out('text') + ' - ' + str + t.equal(orgs.out('text'), str, msg) + }) + t.end() +}) diff --git a/tests/tagger/penn.test.js b/tests/tagger/penn.test.js new file mode 100644 index 000000000..f76be0f46 --- /dev/null +++ b/tests/tagger/penn.test.js @@ -0,0 +1,61 @@ +const test = require('tape') +const nlp = require('../_lib') +const penn = require('../_pennSample') + +const softMapping = { + CC: 'Conjunction', + CD: 'Cardinal', + DT: 'Determiner', + FW: 'Expression', + IN: 'Preposition', + JJ: 'Adjective', + JJR: 'Comparative', + JJS: 'Superlative', + MD: 'Verb', + NN: 'Noun', + NNS: 'Noun', + NNP: 'Noun', + NNPS: 'Noun', + POS: 'Possessive', + PRP: 'Pronoun', + PRP$: 'Pronoun', + RB: 'Adverb', + RBR: 'Comparative', + RBS: 'Superlative', + TO: 'Conjunction', + UH: 'Expression', + VB: 'Verb', + VBD: 'Verb', + VBG: 'Gerund', + VBN: 'Verb', // past participle + VBP: 'Verb', // non-3rd person singular present + VBZ: 'Verb', // 3rd person singular present + WDT: 'Determiner', + WP: 'Pronoun', + WP$: 'Noun', + WRB: 'Adverb', +} + +test('pennTreebank-test:', function(t) { + penn.forEach((sentence, index) => { + sentence.tags = sentence.tags.split(', ') + + let doc = nlp(sentence.text) + t.equal(doc.length, 1, 'one sentence #' + index) + let terms = doc.json(0).terms + t.equal(terms.length, sentence.tags.length, 'tokenize#' + index) + + for (let i = 0; i < sentence.tags.length; i++) { + const want = softMapping[sentence.tags[i]] + if (!terms[i]) { + t.ok(false, sentence.text) + return + } + let found = terms[i].tags.some(tag => tag === want) + let msg = `'` + sentence.text.substr(0, 20) + `'.. - ` + msg += `'${terms[i].text}' missing #${want}` + t.equal(found, true, msg) + } + }) + t.end() +}) diff --git a/tests/tagger/swears.test.js b/tests/tagger/swears.test.js new file mode 100644 index 000000000..7ef5198f9 --- /dev/null +++ b/tests/tagger/swears.test.js @@ -0,0 +1,28 @@ +const test = require('tape') +const nlp = require('../_lib') +//nsfw! + +test('swears:', function(t) { + let m = nlp('shit, i am tired').match('^#Expression') + t.ok(m.found, 'swear-1') + + m = nlp('the shit keeps piling up').match('the #Noun') + t.ok(m.found, 'swear-2') + + m = nlp('damn them all').match('^#Verb') + t.ok(m.found, 'swear-3') + + m = nlp('fuck the government').match('^#Verb') + t.ok(m.found, 'swear-4') + + // m = nlp('when hell freezes over').match('^when #Noun'); + // t.ok(m.found, 'swear-5'); + + // m = nlp('he fucked up').match('he #Verb #Particle'); + // t.ok(m.found, 'swear-6'); + + m = nlp('it is fucked up').match('is #Adjective #Adjective') + t.ok(m.found, 'swear-7') + + t.end() +}) diff --git a/tests/tagger/tagWord.test.js b/tests/tagger/tagWord.test.js new file mode 100644 index 000000000..4fbbe9735 --- /dev/null +++ b/tests/tagger/tagWord.test.js @@ -0,0 +1,75 @@ +const test = require('tape') +const nlp = require('../_lib') + +//test a word from each file in ./data/** +test('pos from-lexicon', function(t) { + const arr = [ + ['toronto', 'City'], + ['mexico', 'Country'], + ['Jamaica', 'Country'], + ['legendary', 'Adjective'], + ['above', 'Adjective'], + ['moderate', 'Adjective'], + ['extreme', 'Adjective'], + ['august', 'Month'], + ['saturday', 'WeekDay'], + ['really', 'Adverb'], + ['each', 'Determiner'], + ['voila', 'Expression'], + ['new england', 'Place'], + ['hers', 'Possessive'], + ['onto', 'Preposition'], + ['blvd', 'Place'], + ['belgian', 'Demonym'], + ['cactus', 'Singular'], + ['cacti', 'Plural'], + ['economy', 'Noun'], + ['engineer', 'Noun'], + ['clothing', 'Noun'], + ['duran duran', 'Organization'], + ['american express', 'Organization'], + ['brotherhood', 'Noun'], + ['oakland athletics', 'SportsTeam'], + ['jamie', 'Person'], + ['claire', 'FemaleName'], + ['arthur', 'MaleName'], + ['¥', 'Currency'], + ['pence', 'Currency'], + ['seven', 'Value'], + ['seventeen', 'Value'], + ['twenty', 'Value'], + ['thousand', 'Value'], + ['eighteenth', 'Value'], + ['tbsp', 'Unit'], + ['wrote', 'PastTense'], + ['write', 'Verb'], + ['survive', 'Verb'], + ['attempt', 'Verb'], + ["mc'adams", 'LastName'], + ['Müller', 'LastName'], + ['muller', 'LastName'], + ['425-1231', 'PhoneNumber'], + ['823-425-1231', 'PhoneNumber'], + ['823 425-1231', 'PhoneNumber'], + ['(823) 425-1231', 'PhoneNumber'], + ['invest', 'Verb'], + ['investing', 'Verb'], + [`wallys'`, 'Possessive'], + // [`JDI University'`, 'Organization'], + ['ocean', 'Noun'], + ['shiver', 'Verb'], + [`flanders'`, 'Possessive'], + [`chillin'`, 'Gerund'], + [`'cool'`, 'Adjective'], + ['MMMCMXXIII', 'RomanNumeral'], + ['MIMMCMXXIII', 'Acronym'], //invalid roman numeral + ['c.e.o', 'Acronym'], + ['MDMA', 'Acronym'], + ['unless', 'Condition'], + ] + arr.forEach(function(a) { + const term = nlp(a[0]).termList()[0] + t.equal(term.tags[a[1]], true, a[0]) + }) + t.end() +}) diff --git a/tests/tagger/tagger.test.js b/tests/tagger/tagger.test.js new file mode 100644 index 000000000..e94d7bb71 --- /dev/null +++ b/tests/tagger/tagger.test.js @@ -0,0 +1,128 @@ +const test = require('tape') +const nlp = require('../_lib') +// const pos_test = require('../_lib').pos_test + +test('pos-basic-tag:', function(t) { + ;[ + ['John is pretty', ['Person', 'Copula', 'Adjective']], + ['John was lofty', ['Person', 'Copula', 'Adjective']], + ['John Smith was lofty', ['FirstName', 'LastName', 'Copula', 'Adjective']], + ['asdfes was lofty', ['Noun', 'Copula', 'Adjective']], + ['asdfes lksejfj was lofty', ['Noun', 'Noun', 'Copula', 'Adjective']], + ['Spencer Kelly is in Canada', ['Person', 'Person', 'Copula', 'Preposition', 'Place']], + ['He is in Canada', ['Pronoun', 'Copula', 'Preposition', 'Place']], + ['5 red roses', ['Value', 'Adjective', 'Noun']], + ['3 trains', ['Value', 'Noun']], + ['3 trainers', ['Value', 'Noun']], + ['5 buses', ['Value', 'Noun']], + ['101010101010101010101010101010101010101010', ['NumericValue']], + + ['walk the walk', ['Verb', 'Determiner', 'Noun']], + ['Peter the man', ['Person', 'Determiner', 'Noun']], + // ['book the flight', ['Verb', 'Determiner', 'Noun']], + + //slang, contractions + ['u r nice', ['Pronoun', 'Copula', 'Adjective']], + ['canadian bacon', ['Demonym', 'Noun']], + ['canadian dollar', ['Currency', 'Currency']], + + //possessive rules + ["john lkjsdf's", ['Person', 'Possessive']], + ["john lkjsdf's house", ['Person', 'Possessive', 'Noun']], + ["john Lkjsdf's house", ['Person', 'Possessive', 'Noun']], + ["john Lkjsdf's House", ['Person', 'Possessive', 'Noun']], + ["mark's question mark", ['Possessive', 'Noun', 'Noun']], + + //question-words + ['who is good?', ['QuestionWord', 'Copula', 'Adjective']], + ['which is good?', ['QuestionWord', 'Copula', 'Adjective']], + // ['bacon which is good', ['Noun', 'Pronoun', 'Copula', 'Adjective']], + // ['bacon which really is good', ['Noun', 'Pronoun', 'Adverb', 'Copula', 'Adjective']], + // ['Douglas who really is good', ['Person', 'Pronoun', 'Adverb', 'Copula', 'Adjective']], + + //web text things + ['lkj@fun.com', ['Email']], + ['j@f.ti', ['Email']], + ['j@ti', ['Noun']], + ['@ti', ['AtMention']], + ['#funtimes', ['HashTag']], + ['http://fun.com/cool?fun=yes', ['Url']], + ['#cool fun.com @cooman', ['HashTag', 'Url', 'AtMention']], + + //determiner-corrections + ['this rocks dude', ['Determiner', 'Verb', 'Noun']], + ['that rocks dude', ['Determiner', 'Verb', 'Noun']], + ['the rocks dude', ['Determiner', 'Plural', 'Noun']], + ['these rocks dude', ['Determiner', 'Plural', 'Noun']], + ['those rocks dude', ['Determiner', 'Plural', 'Noun']], + ['the test string', ['Determiner', 'Noun', 'Noun']], + + //people + ['John swim', ['Person', 'Verb']], + ['John, John', ['Person', 'Person']], + ['John, you', ['FirstName', 'Pronoun']], + ['John you', ['MaleName', 'Pronoun']], + ['you John you', ['Pronoun', 'Person', 'Pronoun']], + // ['10 + 9', ['Value', 'Symbol', 'Value']], + // ['2 * 90 = 180', ['Value', 'Symbol', 'Value', 'Symbol', 'Value']], + // ['one - seventy-six', ['Value', 'Symbol', 'Value']], + ['The stream runs', ['Determiner', 'Noun', 'Verb']], + ['The stream really runs', ['Determiner', 'Noun', 'Adverb', 'Verb']], + ['The nice stream really runs', ['Determiner', 'Adjective', 'Noun', 'Adverb', 'Verb']], + + ['he is walking', ['Pronoun', 'Copula', 'Gerund']], + ['walking is fun', ['Activity', 'Copula', 'Adjective']], + ["walking's great", ['Activity', 'Copula', 'Adjective']], + ['jack cheered', ['Person', 'PastTense']], + ['jack guarded', ['Person', 'PastTense']], + ['jack is guarded', ['Person', 'Copula', 'Adjective']], + ['jack seems guarded', ['Person', 'Verb', 'Adjective']], + //more + ['there are reasons', ['Noun', 'Copula', 'Plural']], + ['there were many walks', ['Noun', 'Copula', 'Adjective', 'Plural']], + ['there were the walks', ['Noun', 'Copula', 'Determiner', 'Noun']], + + ['it was fixed', ['Noun', 'Copula', 'PastTense']], + ['it will be boxed', ['Noun', 'Verb', 'Verb', 'PastTense']], + //ambiguous adverbs + ['it was pretty', ['Noun', 'Copula', 'Adjective']], + ['it was pretty cool', ['Noun', 'Copula', 'Adverb', 'Adjective']], + // ['it was really pretty cool', ['Noun', 'Copula', 'Adverb', 'Adverb', 'Adjective']], + ['it was just', ['Noun', 'Copula', 'Adjective']], + ['it was just gorgeous', ['Noun', 'Copula', 'Adverb', 'Adjective']], + + ['N.V.,', ['Noun']], + ['16.125', ['Cardinal']], + ['$19', ['Money']], + ['butterfly', ['Singular']], + ['he blamed the girl', ['Pronoun', 'PastTense', 'Determiner', 'Singular']], + ['his fine', ['Possessive', 'Noun']], + ['contracted AIDS', ['PastTense', 'Acronym']], + ['city/town', ['Noun', 'Noun']], + ['boyfriend to Jane', ['Noun', 'Conjunction', 'Person']], + // ['boyfriend of Jane', ['Noun', 'Conjunction', 'Person']], + ['his fines', ['Possessive', 'Noun']], + ['100+ rumours', ['Value', 'Plural']], + ['John & John,', ['Noun', 'Noun', 'Noun']], + + //abbreviations + [ + 'col. Patrick said march and feb. etc.', + ['Abbreviation', 'Person', 'PastTense', 'Month', 'Conjunction', 'Abbreviation', 'Abbreviation'], + ], + //dates + + ['germans are nice', ['Demonym', 'Verb', 'Adjective']], + ['Iraqis are nice', ['Plural', 'Copula', 'Adjective']], + ['canadians are nice', ['ProperNoun', 'Verb', 'Adjective']], + ['thom is smart', ['ProperNoun', 'Verb', 'Adjective']], + ].forEach(function(a) { + let terms = nlp(a[0]).json(0).terms + terms.forEach((term, i) => { + let tag = a[1][i] + let found = term.tags.some(tg => tg === tag) + t.equal(found, true, term.text + ' ' + tag) + }) + }) + t.end() +}) diff --git a/tests/tagger/topics.test.js b/tests/tagger/topics.test.js new file mode 100644 index 000000000..cdda8c892 --- /dev/null +++ b/tests/tagger/topics.test.js @@ -0,0 +1,29 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('proper-nouns', function(t) { + const arr = [ + ['I met John Smith in Toronto', ['john smith', 'toronto']], + ['Toronto and Vancouver Canada', ['toronto', 'vancouver canada']], + // ['we ate shellfish at 23 Main st.', []], + ['google is suing motorola inc', ['google', 'motorola inc']], + ['the doctor and his brother see the mayor of france', ['france']], + ] + arr.forEach(a => { + const out = nlp(a[0]) + .match('#ProperNoun+') + .toLowerCase() + .out('array') + t.deepEqual(out, a[1], a[0]) + }) + t.end() +}) + +//after we change pos, untag propernoun +test('remove-proper-nouns', function(t) { + const doc = nlp('do what Theresa May') + t.equal(doc.match('may').has('#ProperNoun'), true, 'propernoun-init') + doc.match('may').tag('Verb') + t.equal(doc.match('may').has('#ProperNoun'), false, 'propernoun-missing') + t.end() +}) diff --git a/tests/tagger/untag.test.js b/tests/tagger/untag.test.js new file mode 100644 index 000000000..3d8a115c5 --- /dev/null +++ b/tests/tagger/untag.test.js @@ -0,0 +1,72 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('tag inference:', function(t) { + let m = nlp('aasdf2') + .unTag('Noun') + .unTag('NounPhrase') + let term = m.list[0].terms(0) + t.equal(Object.keys(term.tags).length, 0, 'aasdf2 has no tags') + //give it a specific tag- + m.tag('SportsTeam') + term = m.list[0].terms(0) + t.equal(term.tags.Noun, true, 'aasdf2 now has Noun') + t.equal(term.tags.Organization, true, 'aasdf2 now has Organization(inferred)') + //give it a redundant tag- + m.tag('Organization') + term = m.list[0].terms(0) + t.equal(term.tags.Noun, true, 'aasdf2 still has Noun') + t.equal(term.tags.Organization, true, 'aasdf2 still has Organization') + t.end() +}) + +test('untag inference:', function(t) { + let m = nlp('aasdf') + m.tag('FemaleName') + let term = m.list[0].terms(0) + t.equal(term.tags.FemaleName, true, 'aasdf first has FemaleName') + t.equal(term.tags.Person, true, 'aasdf first has person') + t.equal(term.tags.Noun, true, 'aasdf first has noun') + //remove the assumption.. + m.unTag('Noun') + t.equal(term.tags.Noun, undefined, 'aasdf now has no noun') + t.equal(term.tags.Person, undefined, 'aasdf now has no person(inferred)') + t.equal(term.tags.FemaleName, undefined, 'aasdf now has no FemaleName(inferred)') + t.end() +}) + +test('tag idempodence:', function(t) { + const m = nlp('walk').tag('Verb') + const term = m.list[0].terms(0) + t.equal(term.tags.Verb, true, 'walk has Verb') + t.equal(term.tags.Value, undefined, 'walk has no Value') + //untag irrelevant stuff + m.unTag('Value') + m.unTag('Determiner') + m.unTag('Country') + m.unTag('Place') + t.equal(term.tags.Verb, true, 'walk has Verb after') + t.equal(term.tags.Value, undefined, 'walk has no Value after') + t.end() +}) + +test('tags are self-removing', function(t) { + const terms = ['Person', 'Place', 'PastTense', 'FemaleName', 'Infinitive', 'HashTag', 'Month'] + terms.forEach(function(tag) { + const m = nlp('aasdf') + .tag(tag) + .unTag(tag) + const t0 = m.list[0].terms(0) + t.equal(t0.tags[tag], undefined, 'tag removes self ' + tag) + }) + t.end() +}) + +test('untag wildcard', function(t) { + const r = nlp('we live in Toronto Canada and it is cold') + r.match('#Place+').unTag('*') + t.equal(r.match('#Place').found, false, 'place-tag-is-gone') + const term = r.list[0].terms(3) || {} + t.equal(Object.keys(term.tags || {}).length, 0, 'toronto-has-no-tags-now') + t.end() +}) diff --git a/tests/tagger/web.test.js b/tests/tagger/web.test.js new file mode 100644 index 000000000..502e95e86 --- /dev/null +++ b/tests/tagger/web.test.js @@ -0,0 +1,66 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('is-email:', function(t) { + ;[ + [`s@s.com`, true], + [`sasdf@sasdf.com`, true], + [`sasdf@sasdf.ti`, true], + [`sasdf@sasdf.t`], + [`sasdf@sasdft`], + [`sasdfsasdft.com`], + [`@sasdft.com`], + [`_@_.com`, true], + [`_@_._`], + [`sas df@sasdf.com`], + [`sasdf@sa sdf.com`], + ].forEach(function(a) { + const term = nlp(a[0]).list[0].terms(0) + const msg = a[0] + ' is email: ' + a[1] + t.equal(term.tags['Email'], a[1], msg) + }) + t.end() +}) + +test('is-hashtag:', function(t) { + ;[ + [`#lkjsdf`, true], + [`#ll`, true], + [`#22ll`, true], + [`#_22ll`, true], + // [`#l`,], + [`# l`], + [`l#l`], + ].forEach(function(a) { + const term = nlp(a[0]).list[0].terms(0) + const msg = a[0] + ' is hashtag: ' + a[1] + t.equal(term.tags['HashTag'], a[1], msg) + }) + t.end() +}) + +test('is-url:', function(t) { + ;[ + [`http://cool.com/fun`, true], + [`https://cool.com`, true], + [`https://cool.com/`, true], + [`https://www.cool.com/`, true], + [`http://subdomain.cool.com/`, true], + [`www.fun.com/`, true], + [`www.fun.com`, true], + [`www.fun.com/foobar/fun`, true], + [`www.subdomain.cool.com/`, true], + [`wwwsubdomain.cool.com/`, true], + [`woo.br`, true], + [`woohoo.biz`, true], + [`woop.org/news`, true], + [`http://woop.org/news?foo=bar`, true], + [`http:subdomain.cool.com/`], + [`coolcom`], + ].forEach(function(a) { + const term = nlp(a[0]).list[0].terms(0) + const msg = a[0] + ' is url: ' + a[1] + t.equal(term.tags['Url'], a[1], msg) + }) + t.end() +}) diff --git a/tests/tokenize.test.js b/tests/tokenize.test.js new file mode 100644 index 000000000..b5dc1575f --- /dev/null +++ b/tests/tokenize.test.js @@ -0,0 +1,37 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('em-dash, en-dash', function(t) { + // '-': //dash + // '–': //en-dash + // '—': //em-dash + let doc = nlp('fun-time') + t.equal(doc.terms().length, 2, 'dash') + doc = nlp('fun–time') + t.equal(doc.terms().length, 2, 'en-dash') + doc = nlp('fun—time') + t.equal(doc.terms().length, 2, 'em-dash') + + //not a full word, either + doc = nlp('fun - time') + t.equal(doc.terms().length, 2, 'dash-word') + doc = nlp('fun – time') + t.equal(doc.terms().length, 2, 'en-dash-word') + doc = nlp('fun — time') + t.equal(doc.terms().length, 2, 'em-dash-word') + + //numeric forms are split, but contractions too + doc = nlp('20-20') + t.equal(doc.terms().length, 3, 'dash-num') + doc = nlp('20–20') + t.equal(doc.terms().length, 3, 'en-dash-num') + doc = nlp('20—20') + t.equal(doc.terms().length, 3, 'em-dash-num') + t.end() +}) + +test('emoji-only sentence', function(t) { + let doc = nlp('good night! 💋') + t.equal(doc.length, 2, 'boemojith sentence') + t.end() +}) diff --git a/tests/topics.test.js b/tests/topics.test.js new file mode 100644 index 000000000..1ea074283 --- /dev/null +++ b/tests/topics.test.js @@ -0,0 +1,70 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('topics:', function(t) { + let list = [ + ['Tony Hawk lives in Toronto. Tony Hawk is cool.', 'tony hawk'], + ['I live Toronto. I think Toronto is cool.', 'toronto'], + ['The EACD united in 1972. EACD must follow regulations.', 'eacd'], + // ['The Elkjsdflkjsdf sells hamburgers. I think the Elkjsdflkjsdf eats turky.', 'elkjsdflkjsdf'], + ["Toronto's citizens love toronto!", 'toronto'], + ] + list.forEach(function(a) { + const arr = nlp(a[0]) + .topics() + .out('freq') + t.equal(arr[0].reduced, a[1], a[0]) + }) + t.end() +}) + +test('topics-false-positives:', function(t) { + const arr = [ + 'somone ate her lunch', + 'everybody is dancing all night', + "a man and a woman ate her son's breakfast", + 'my brother walks to school', + `She's coming by`, + `if she doesn't like something about us she can keep us off`, + ` She's it! She could be a soap opera.`, + `she's a little dare-devil!`, + ] + arr.forEach(function(str, i) { + const doc = nlp(str).topics() + t.equal(doc.length, 0, 'topics #' + i + ' -> ' + doc.out()) + }) + t.end() +}) + +test('topics-basic', function(t) { + let doc = nlp('i went to Gloop University in Paris, France, with John H. Smith') + let arr = doc.topics().out('array') + t.deepEqual(arr, ['Gloop University', 'Paris, France,', 'John H. Smith'], 'found all three topics') + t.end() +}) + +test('misc entities', function(t) { + let doc = nlp('The Children are right to laugh at you, Ralph') + let m = doc.people() + t.equal(m.length, 1, 'one person') + + m = doc.places() + t.equal(m.length, 0, 'no places') + + m = doc.organizations() + t.equal(m.length, 0, 'no organizations') + + m = doc.entities() + t.equal(m.length, 1, 'one entity') + t.end() +}) + +test('topics concat:', function(t) { + const things = nlp('spencer and danny are in Paris France and germany for Google Inc and IBM') + .topics() + .json({ normal: true, trim: true }) + .map(o => o.normal) + const want = ['spencer', 'danny', 'paris france', 'germany', 'google inc', 'ibm'] + t.equal(things.join(', '), want.join(', '), 'found right things') + t.end() +}) diff --git a/tests/transform/delete.test.js b/tests/transform/delete.test.js new file mode 100644 index 000000000..5b64e391e --- /dev/null +++ b/tests/transform/delete.test.js @@ -0,0 +1,68 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('remove-basic :', function(t) { + let m = nlp('the brown cat played') + .match('brown') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'brown-cat') + + m = nlp('the nice brown cat played') + .match('nice brown') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'nice-brown') + + m = nlp('the nice brown cat played') + .match('#Adjective') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'adj-each') + + m = nlp('the nice brown cat played') + .match('#Adjective+') + .delete() + .all() + t.equal(m.out('text'), 'the cat played', 'adj-consecutive') + + t.end() +}) + +test('remove-match :', function(t) { + let m = nlp('the brown cat played').delete('brown') + t.equal(m.out('text'), 'the cat played', 'brown-cat') + + m = nlp('the brown cat played. The brown dog sat down.').delete('brown') + t.equal(m.out('text'), 'the cat played. The dog sat down.', 'brown-cat') + + m = nlp('the nice brown cat played. The nice dog waited.').delete('nice brown') + t.equal(m.out('text'), 'the cat played. The nice dog waited.', 'nice-brown') + + m = nlp('the nice brown cat played. The cute dogs ate.').delete('#Adjective') + t.equal(m.out('text'), 'the cat played. The dogs ate.', 'adj-each') + + m = nlp('the nice brown cat played. The cute dogs ate.').delete('#Adjective+') + t.equal(m.out('text'), 'the cat played. The dogs ate.', 'adj-consecutive') + + t.end() +}) + +test('remove-logic :', function(t) { + let m = nlp('spencer kelly is here') + .match('spencer kelly') + .delete('spencer') + t.equal(m.out('normal'), 'kelly', 'remove(reg) returns this') + + m = nlp('spencer kelly is here') + .match('spencer kelly') + .delete() + .all() + t.equal(m.out('normal'), 'is here', 'remove() returns parent') + + m = nlp('spencer kelly is here') + .match('spencer kelly') + .delete('notfound') + t.equal(m.out('normal'), 'spencer kelly', 'remove(notfound) returns this') + t.end() +}) diff --git a/tests/transform/join.test.js b/tests/transform/join.test.js new file mode 100644 index 000000000..793640f09 --- /dev/null +++ b/tests/transform/join.test.js @@ -0,0 +1,26 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('join-basic', function(t) { + let str = `What's with these homies dissin' my girl? Why do they gotta front? + + What did we ever do to these guys that made them so violent? + + ` + let doc = nlp(str).join() + t.equal(doc.length, 1, 'one phrase') + doc = doc.splitOn('we ever') + t.equal(doc.length, 3, 'three phrases now') + // t.equal(doc.text(), str, 'original text unchanged') //TODO:fix me + t.end() +}) + +test('join-parents', function(t) { + let str = `left side. middle part one. two middle part two. right side.` + let doc = nlp(str) + doc.if('middle').join() + t.equal(doc.length, 3, 'three parts now') + t.equal(doc.all().length, 3, 'three sentences now') + t.equal(doc.text(), str, 'original text unchanged') + t.end() +}) diff --git a/tests/transform/normalize-light.test.js b/tests/transform/normalize-light.test.js new file mode 100644 index 000000000..4ac3c2cd0 --- /dev/null +++ b/tests/transform/normalize-light.test.js @@ -0,0 +1,63 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('normalize - light', function(t) { + let arr = [ + [ + ' so... you like donuts? have all the donuts in the world!!!', + 'so you like donuts? have all the donuts in the world!', + ], + // ['This is a test. .', 'this is a test.'], + ['This is a test?!', 'This is a test?'], + ['Björk, the singer-songwriter...', 'Bjork the singer songwriter'], + // ['the so-called “fascist dictator”', 'the so called "fascist dictator"'], + // ['the so-called ❛singer-songwriter❜', 'the so called \'singer songwriter\''], + // ['the so-called ❛group of seven❜', 'the so called \'group of 7\''], + ['Director of the F.B.I.', 'Director of the FBI.'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .normalize() + .out('text') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('normalize - medium', function(t) { + let arr = [ + [ + ' so... you like DONUTS? have all the donuts in the WORLD!!!', + 'so you like donuts? have all the donuts in the world!', + ], + ['This is a test?!', 'this is a test?'], + ['Björk, the singer-songwriter...', 'bjork the singer songwriter'], + ['Director of the F.B.I.', 'director of the fbi.'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .normalize('medium') + .out('text') + t.equal(str, a[1], a[0]) + }) + t.end() +}) + +test('normalize - heavy', function(t) { + let arr = [ + [ + ' so... you like DONUTS? have all the donuts in the WORLD!!!', + 'so you like donut? have all the donut in the world!', + ], + // ['This is a test?!', 'this be a test?'], + ['Björk, the singer-songwriter...', 'bjork the singer songwriter'], + ['Director of the F.B.I.', 'director of the fbi.'], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .normalize('heavy') + .out('text') + t.equal(str, a[1], a[0]) + }) + t.end() +}) diff --git a/tests/transform/normalize-more.test.js b/tests/transform/normalize-more.test.js new file mode 100644 index 000000000..6918f8acd --- /dev/null +++ b/tests/transform/normalize-more.test.js @@ -0,0 +1,133 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('possessives', function(t) { + let doc = nlp(`Corey Hart's pudding and Google's advertising`) + doc = doc.normalize({ + possessives: true, + case: false, + }) + t.equal(doc.out(), 'Corey Hart pudding and Google advertising', 'normalize possessives') + t.end() +}) + +test('optional params', function(t) { + const doc = nlp(`John Smith bought automobiles (for us)`).normalize({ + case: true, + possessives: true, + parentheses: true, + // plurals: true, + verbs: true, + }) + t.equal(doc.out(), 'john smith buy automobiles for us', 'many-on') + t.end() +}) + +test('optional param - verbs and plurals together', function(t) { + const plurals = [['batmobiles', 'batmobile']] + const verbs = [['I was walking', 'I walk']] + + // good + plurals.forEach(a => { + const doc = nlp(a[0]) + const pluralsOn = doc.normalize({ + plurals: true, + }) + t.equal(pluralsOn.out(), a[1], a[0]) + }) + + // good + verbs.forEach(a => { + const doc = nlp(a[0]) + const verbsOn = doc.normalize({ + verbs: true, + }) + t.equal(verbsOn.out(), a[1], a[0]) + }) + + // bad + plurals.concat(verbs).forEach(a => { + const doc = nlp(a[0]) + const bothOn = doc.normalize({ + plurals: true, + verbs: true, + }) + t.equal(bothOn.out(), a[1], a[0]) + }) + + t.end() +}) + +test('honorifics', function(t) { + const tests = [ + ['rear admiral Smith', 'smith'], + ['Lieutenant John Smith', 'john smith'], + // ['Admiral Davis Jr', 'davis jr'], + ['Field marshal Herring', 'herring'], + ['General Lou Gobbells of the US air force', 'lou gobbells of the us air force'], + ['Rear admiral John', 'john'], + ['Lieutenant general James Baker', 'james baker'], + ['Lieutenant colonel Bing Crosby', 'bing crosby'], + ['Major Tom', 'tom'], + ['major effort by President Xi', 'major effort by xi'], + ['Corporal John Herring', 'john herring'], + ['sergeant major Harold', 'harold'], + ['Second lieutenant Semore Hirthman', 'semore hirthman'], + ['first lady Michelle obama', 'michelle obama'], + ['prime minister Stephen Hawking', 'stephen hawking'], + //no names + // ['first lieutenant', '1st lieutenant'], + // ['Sergeant', 'sergeant'], + ] + tests.forEach(a => { + let doc = nlp(a[0]) + doc = doc.normalize({ + honorifics: true, + case: true, + }) + t.equal(doc.out('normal'), a[1], a[0]) + }) + t.end() +}) + +test('hyphen-whitespace:', function(t) { + let doc = nlp(`the so-called “fascist dictator”`) + doc.normalize({ whitespace: true, punctuation: false }) + t.equal(doc.text(), `the so-called “fascist dictator”`, 'keep hyphen') + t.end() +}) + +test('dash-whitespace:', function(t) { + let str = `a dash seperates words - like that` + let doc = nlp(str) + doc.normalize({ whitespace: true, punctuation: false }) + t.equal(doc.text(), str, 'keep the dash') + t.end() +}) + +test('elipses-whitespace:', function(t) { + let doc = nlp('about this ...').normalize() + t.equal(doc.out('text'), 'about this', 'normalize seperate elipses') + + doc = nlp('about this ...').toLowerCase() + t.equal(doc.out('text'), 'about this ...', 'lowercase elipses') + + doc = nlp('about this...').normalize() + t.equal(doc.out('text'), 'about this', 'normalize attatched elipses') + t.end() +}) + +test('more-normalize:', function(t) { + let doc = nlp(`i saw first lady michelle obama`) + doc.normalize({ + honorifics: true, + }) + t.equal(doc.out('text'), 'i saw michelle obama', 'normalize honorifics') + + doc = nlp(`google's tax return`) + doc.normalize({ + possessives: true, + }) + t.equal(doc.out('text'), 'google tax return', 'normalize possessives') + t.end() +}) diff --git a/tests/transform/normalize-one.test.js b/tests/transform/normalize-one.test.js new file mode 100644 index 000000000..83fdfa783 --- /dev/null +++ b/tests/transform/normalize-one.test.js @@ -0,0 +1,60 @@ +const test = require('tape') +const nlp = require('../_lib') + +const only = function(options) { + const none = { + case: false, + whitespace: false, + unicode: false, + punctuation: false, + contraction: false, + } + return Object.assign({}, none, options) +} + +test('normalize defaults', function(t) { + let doc = nlp.tokenize(` it's coöl, (i think) . He is cool; i said .`) + doc.normalize() + t.equal(doc.text(), `it's cool (i think). He is cool i said.`, 'normalize-defaults') + t.end() +}) + +test('normalize unicode', function(t) { + let doc = nlp.tokenize(` it's coöl, (i think) . He is cool; i said .`) + let options = only({ unicode: true }) + doc.normalize(options) + t.equal(doc.text(), ` it's cool, (i think) . He is cool; i said .`, 'normalize-unicode') + t.end() +}) + +test('normalize punctuation', function(t) { + let doc = nlp.tokenize(` it's coöl, (i think) . He is cool; i said .`) + let options = only({ punctuation: true }) + doc.normalize(options) + t.equal(doc.text(), ` it's coöl (i think) . He is cool i said .`, 'normalize-punct') + t.end() +}) + +test('normalize whitespace', function(t) { + let doc = nlp.tokenize(` it's coöl, (i think) . He is cool; i said .`) + let options = only({ whitespace: true }) + doc.normalize(options) + t.equal(doc.text(), `it's coöl, (i think). He is cool; i said.`, 'normalize-whitespace') + t.end() +}) + +test('normalize parentheses', function(t) { + let doc = nlp(` it's coöl, (i think) . He is cool; i said .`) + let options = only({ parentheses: true }) + doc.normalize(options) + t.equal(doc.text(), ` it's coöl, i think . He is cool; i said .`, 'normalize-parentheses') + t.end() +}) + +test('normalize contractions', function(t) { + let doc = nlp(` it's coöl, (i think) . He is cool; i said .`) + let options = only({ contractions: true }) + doc.normalize(options) + t.equal(doc.text(), ` it is coöl, (i think) . He is cool; i said .`, 'normalize-contractions') + t.end() +}) diff --git a/tests/transform/prepend.test.js b/tests/transform/prepend.test.js new file mode 100644 index 000000000..328d9d2a5 --- /dev/null +++ b/tests/transform/prepend.test.js @@ -0,0 +1,55 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('prepend parent start', function(t) { + let doc = nlp(`one two three`) + doc.prepend('zero') + t.equal(doc.text(), 'zero one two three', 'prepended in parent') + t.end() +}) + +test('prepend middle', function(t) { + let doc = nlp(`one two four five`) + let m = doc.match('four').prepend('three') + t.equal(m.text().trim(), 'three four', 'prepended in child') + t.equal(doc.text(), 'one two three four five', 'prepended in parent') + t.end() +}) + +test('prepend multi', function(t) { + let doc = nlp('one two. three four') + doc.prepend('oooo') + t.equal(doc.text(), 'oooo one two. oooo three four') + t.end() +}) + +test('prepend children', function(t) { + let doc = nlp(`one four five six.`) + let m1 = doc.match('one four') + let m2 = m1.match('four') + m2.prepend('two three') + + t.equal(m1.text(), 'one two three four', 'prepended in child 1') + t.equal(m2.text(), 'two three four', 'prepended in child 2') + t.equal(doc.text(), 'one two three four five six.', 'prepended in parent') + t.end() +}) + +test('prepend start child', function(t) { + let doc = nlp(`one two three four`) + doc.match('one').prepend('zero') + t.equal(doc.text(), 'zero one two three four', 'prepended in parent') + t.end() +}) + +test('prepend many children', function(t) { + let doc = nlp(`one two three four`) + doc + .match('one two three') + .match('one two') + .match('.') + .match('one') + .prepend('zero') + t.equal(doc.text(), 'zero one two three four', 'prepended in parent') + t.end() +}) diff --git a/tests/transform/split.test.js b/tests/transform/split.test.js new file mode 100644 index 000000000..21cd838ee --- /dev/null +++ b/tests/transform/split.test.js @@ -0,0 +1,101 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('splitAfter', function(t) { + ;[ + ['doug and nancy', 'and', ['doug and', 'nancy']], + ['doug and also nancy', 'and also', ['doug and also', 'nancy']], + ['doug and definetly nancy', 'and #Adverb', ['doug and definetly', 'nancy']], + ['maybe doug but possibly nancy', 'but', ['maybe doug but', 'possibly nancy']], + + ['a x b x c', 'x', ['a x', 'b x', 'c']], + ['a b x c x', 'x', ['a b x', 'c x']], + ['x a b x c', 'x', ['x', 'a b x', 'c']], + ['x x a b c', 'x', ['x', 'x', 'a b c']], + ['a x b x', 'x', ['a x', 'b x']], + ['a x b c x', 'x', ['a x', 'b c x']], + ['x x a b c', 'x', ['x', 'x', 'a b c']], + + ['john paul george ringo', '.', ['john', 'paul', 'george', 'ringo']], + ['doug is really nice', 'is', ['doug is', 'really nice']], + ].forEach(function(a) { + const want = a[2] + const got = nlp(a[0]) + .splitAfter(a[1]) + .out('array') + t.deepEqual(got, want, a[0]) + }) + t.end() +}) + +test('splitOn', function(t) { + ;[ + ['doug and nancy', 'and', ['doug', 'and', 'nancy']], + ['doug and also nancy', 'and also', ['doug', 'and also', 'nancy']], + ['doug and definetly nancy', 'and #Adverb', ['doug', 'and definetly', 'nancy']], + ['maybe doug but possibly nancy', 'but', ['maybe doug', 'but', 'possibly nancy']], + ['doug is really nice', 'is', ['doug', 'is', 'really nice']], + + ['a x b x c', 'x', ['a', 'x', 'b', 'x', 'c']], + ['a b x x c', 'x', ['a b', 'x', 'x', 'c']], + ['x a b x c', 'x', ['x', 'a b', 'x', 'c']], + ['x x a b c', 'x', ['x', 'x', 'a b c']], + ['a x b x', 'x', ['a', 'x', 'b', 'x']], + ].forEach(function(a) { + const want = a[2] + const got = nlp(a[0]) + .splitOn(a[1]) + .out('array') + t.deepEqual(got, want, a[0]) + }) + t.end() +}) + +test('splitBefore', function(t) { + ;[ + ['doug and nancy', 'and', ['doug', 'and nancy']], + ['doug and also nancy', 'and also', ['doug', 'and also nancy']], + ['doug and definetly nancy', 'and #Adverb', ['doug', 'and definetly nancy']], + ['maybe doug but possibly nancy', 'but', ['maybe doug', 'but possibly nancy']], + ['doug is really nice', 'is', ['doug', 'is really nice']], + + ['a x b x c', 'x', ['a', 'x b', 'x c']], + ['a b x x c', 'x', ['a b', 'x', 'x c']], + ['x a b x c', 'x', ['x a b', 'x c']], + ['x x a b c', 'x', ['x', 'x a b c']], + ['a x b x', 'x', ['a', 'x b', 'x']], + ].forEach(function(a) { + const want = a[2] + const got = nlp(a[0]) + .splitBefore(a[1]) + .out('array') + t.deepEqual(got, want, a[0]) + }) + t.end() +}) + +test('multi splitBefore, multi sentence', function(t) { + let doc = nlp('before before match1, match2 after after. then a match3 over here. none found') + let m = doc.splitBefore('/^match/') + t.equal(m.length, 6, 'found 6') + t.equal(m.get(0).out('normal'), 'before before', 'found before') + t.equal(m.get(1).out('normal'), 'match1', 'found match1') + t.equal(m.get(2).out('normal'), 'match2 after after', 'found match2') + t.equal(m.get(3).out('normal'), 'then a', 'next sentence') + t.equal(m.get(4).out('normal'), 'match3 over here', 'next sentence match') + t.equal(m.get(5).out('normal'), 'none found', 'unfound') + t.end() +}) + +test('multi splitAfter, multi sentence', function(t) { + let doc = nlp('before before match1, match2 after after. then a match3 over here. none found') + let m = doc.splitAfter('/^match/') + t.equal(m.length, 6, 'found 6') + t.equal(m.get(0).out('normal'), 'before before match1', 'found match1') + t.equal(m.get(1).out('normal'), 'match2', 'found match2') + t.equal(m.get(2).out('normal'), 'after after', 'after') + t.equal(m.get(3).out('normal'), 'then a match3', 'next sentence match') + t.equal(m.get(4).out('normal'), 'over here', 'next sentence after') + t.equal(m.get(5).out('normal'), 'none found', 'unfound') + t.end() +}) diff --git a/tests/transform/splitOn.test.js b/tests/transform/splitOn.test.js new file mode 100644 index 000000000..2f93f2763 --- /dev/null +++ b/tests/transform/splitOn.test.js @@ -0,0 +1,100 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('one split, one sentence', function(t) { + let doc = nlp('before before match, after after.') + let m = doc.splitOn('@hasComma') + t.equal(m.length, 3, 'found 3') + t.equal(m.get(0).out('normal'), 'before before', 'found before') + t.equal(m.get(1).out('normal'), 'match', 'found match') + t.equal(m.get(2).out('normal'), 'after after', 'found after') + t.end() +}) + +test('multi split, one sentence', function(t) { + let doc = nlp('before before match, then a match, after after.') + let m = doc.splitOn('@hasComma') + t.equal(m.length, 5, 'found 5') + t.equal(m.get(0).out('normal'), 'before before', 'found before') + t.equal(m.get(1).out('normal'), 'match', 'found match') + t.equal(m.get(2).out('normal'), 'then a', 'found between') + t.equal(m.get(3).out('normal'), 'match', 'found match2') + t.equal(m.get(4).out('normal'), 'after after', 'found after') + t.end() +}) + +test('one split, multi sentence', function(t) { + let doc = nlp('before before match, after after. then over here') + let m = doc.splitOn('match') + t.equal(m.length, 4, 'found 4') + t.equal(m.get(0).out('normal'), 'before before', 'found before') + t.equal(m.get(1).out('normal'), 'match', 'found match') + t.equal(m.get(2).out('normal'), 'after after', 'found after') + t.equal(m.get(3).out('normal'), 'then over here', 'next sentence') + t.end() +}) + +test('multi split, multi sentence', function(t) { + let doc = nlp('before before match1, match2 after after. then a match3 over here') + let m = doc.splitOn('/^match/') + t.equal(m.length, 7, 'found 7') + t.equal(m.get(0).out('normal'), 'before before', 'found before') + t.equal(m.get(1).out('normal'), 'match1', 'found match1') + t.equal(m.get(2).out('normal'), 'match2', 'found match2') + t.equal(m.get(3).out('normal'), 'after after', 'found after') + t.equal(m.get(4).out('normal'), 'then a', 'next sentence') + t.equal(m.get(5).out('normal'), 'match3', 'next sentence match') + t.equal(m.get(6).out('normal'), 'over here', 'next sentence after') + t.end() +}) + +test('greedy split', function(t) { + let doc = nlp('match match middle middle match. then over here') + let m = doc.splitOn('match+') + t.equal(m.length, 4, 'found 4') + t.equal(m.get(0).out('normal'), 'match match', 'found two') + t.equal(m.get(1).out('normal'), 'middle middle', 'found middles') + t.equal(m.get(2).out('normal'), 'match', 'found one') + t.equal(m.get(3).out('normal'), 'then over here', 'next sentence') + t.end() +}) + +test('split skip sentence', function(t) { + let doc = nlp('before match. nothing found here. two match after') + let m = doc.splitOn('match') + t.equal(m.length, 6, 'found 6') + t.equal(m.get(0).out('normal'), 'before', 'found before') + t.equal(m.get(1).out('normal'), 'match', 'found match') + t.equal(m.get(2).out('normal'), 'nothing found here.', 'no-match sentence') + t.equal(m.get(3).out('normal'), 'two', 'found before2') + t.equal(m.get(4).out('normal'), 'match', 'found match2') + t.equal(m.get(5).out('normal'), 'after', 'found after') + t.end() +}) + +test('no match split', function(t) { + let doc = nlp('nothing found here. none here either') + let m = doc.splitOn('match') + t.equal(m.length, 2, 'found 2') + t.equal(m.get(0).out('normal'), 'nothing found here.', 'not found 1') + t.equal(m.get(1).out('normal'), 'none here either', 'not found 2') + t.end() +}) + +test('split-parent', function(t) { + let doc = nlp('if so, he is the best, that i see. he is the greatest in the world') + t.equal(doc.length, 2, 'init parent is 2 sentence') + + let m = doc.match('he is').splitOn() + t.equal(m.length, 5, 'splitOn parent into 5') + + m = doc.match('he is').splitAfter() + t.equal(m.length, 4, 'splitAfter parent into 4') + + m = doc.match('he is').splitBefore() + t.equal(m.length, 3, 'splitBefore parent into 3') + + t.equal(doc.length, 2, 'parent is still 2 sentence') + + t.end() +}) diff --git a/tests/unique.test.js b/tests/unique.test.js new file mode 100644 index 000000000..2789863ce --- /dev/null +++ b/tests/unique.test.js @@ -0,0 +1,30 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('term-unique', function(t) { + let doc = nlp(`him and her and him`) + let m = doc.terms().unique() + t.equal(m.text(), 'him and her', 'terms-unique') + t.equal(doc.text(), `him and her and him`, 'original-has-duplicates') + t.end() +}) + +test('sentence-unique', function(t) { + let str = `him and her. in toronto. him and her. him.` + let doc = nlp(str) + let uniq = doc.unique() + t.equal(uniq.text(), 'him and her. in toronto. him.', 'remove dup sentences') + t.equal(doc.text(), str, 'keep dup sentences') + t.end() +}) + +test('unique-normalize', function(t) { + let doc = nlp(`SPENCER's house (spencer)`) + doc = doc.terms().unique() + t.equal(doc.text(), "SPENCER's house", 'normalize-posessive') + + doc = nlp(`is not isn't`) + doc = doc.terms().unique() + t.equal(doc.text(), 'is not', 'normalize-contraction') + t.end() +}) diff --git a/tests/verbs/conjugate.test.js b/tests/verbs/conjugate.test.js new file mode 100644 index 000000000..696849f83 --- /dev/null +++ b/tests/verbs/conjugate.test.js @@ -0,0 +1,255 @@ +const test = require('tape') +const nlp = require('../_lib') + +const arr = [ + { + Infinitive: 'convolute', + PresentTense: 'convolutes', + Gerund: 'convoluting', + PastTense: 'convoluted', + }, + { + PresentTense: 'presents', + Gerund: 'presenting', + PastTense: 'presented', + Infinitive: 'present', + }, + { + PresentTense: 'angulates', + Gerund: 'angulating', + PastTense: 'angulated', + Infinitive: 'angulate', + }, + { + PresentTense: 'conjures', + Gerund: 'conjuring', + PastTense: 'conjured', + Infinitive: 'conjure', + }, + { + PresentTense: 'denounces', + Gerund: 'denouncing', + PastTense: 'denounced', + Infinitive: 'denounce', + }, + { + PresentTense: 'watches', + Gerund: 'watching', + PastTense: 'watched', + Infinitive: 'watch', + }, + { + PresentTense: 'tingles', + Gerund: 'tingling', + PastTense: 'tingled', + Infinitive: 'tingle', + }, + { + PresentTense: 'mortises', + Gerund: 'mortising', + PastTense: 'mortised', + Infinitive: 'mortise', + }, + { + PresentTense: 'disguises', + Gerund: 'disguising', + PastTense: 'disguised', + Infinitive: 'disguise', + }, + { + Infinitive: 'effect', + Gerund: 'effecting', + PastTense: 'effected', + PresentTense: 'effects', + }, + { + Infinitive: 'want', + Gerund: 'wanting', + PastTense: 'wanted', + PresentTense: 'wants', + }, + { + Infinitive: 'power', + Gerund: 'powering', + PastTense: 'powered', + PresentTense: 'powers', + }, + { + Infinitive: 'overcompensate', + PresentTense: 'overcompensates', + PastTense: 'overcompensated', + Gerund: 'overcompensating', + }, + { + Infinitive: 'ice', + PresentTense: 'ices', + PastTense: 'iced', + Gerund: 'icing', + }, + { + Infinitive: 'buy', + PresentTense: 'buys', + PastTense: 'bought', + Gerund: 'buying', + }, + { + Infinitive: 'flower', + PresentTense: 'flowers', + PastTense: 'flowered', + Gerund: 'flowering', + }, + { + Infinitive: 'rage', + PresentTense: 'rages', + PastTense: 'raged', + Gerund: 'raging', + }, + { + Infinitive: 'drive', + PresentTense: 'drives', + PastTense: 'drove', + Gerund: 'driving', + }, + { + Infinitive: 'foul', + PresentTense: 'fouls', + PastTense: 'fouled', + Gerund: 'fouling', + }, + { + Infinitive: 'overthrow', + PresentTense: 'overthrows', + Gerund: 'overthrowing', + PastTense: 'overthrew', + }, + { + Infinitive: 'aim', + PresentTense: 'aims', + PastTense: 'aimed', + Gerund: 'aiming', + }, + { + PresentTense: 'unifies', + Gerund: 'unifying', + PastTense: 'unified', + Infinitive: 'unify', + }, + { + PresentTense: 'addresses', + Gerund: 'addressing', + PastTense: 'addressed', + Infinitive: 'address', + }, + { + Infinitive: 'bumble', + PresentTense: 'bumbles', + PastTense: 'bumbled', + Gerund: 'bumbling', + }, + { + Infinitive: 'snipe', + PresentTense: 'snipes', + PastTense: 'sniped', + Gerund: 'sniping', + }, + { + PresentTense: 'relishes', + Gerund: 'relishing', + PastTense: 'relished', + Infinitive: 'relish', + }, + { + Infinitive: 'lengthen', + Gerund: 'lengthening', + PastTense: 'lengthened', + PresentTense: 'lengthens', + }, + { + Infinitive: 'farm', + PresentTense: 'farms', + PastTense: 'farmed', + Gerund: 'farming', + }, + { + Infinitive: 'develop', + PresentTense: 'develops', + PastTense: 'developed', + Gerund: 'developing', + }, + { + Infinitive: 'study', + PresentTense: 'studies', + PastTense: 'studied', + Gerund: 'studying', + }, + { + Infinitive: 'criticise', + PresentTense: 'criticises', + PastTense: 'criticised', + Gerund: 'criticising', + }, + { + Infinitive: 'speak', + PresentTense: 'speaks', + PastTense: 'spoke', + Gerund: 'speaking', + }, + { + Infinitive: 'fuzz', + PresentTense: 'fuzzes', + PastTense: 'fuzzed', + Gerund: 'fuzzing', + }, + { + Infinitive: 'invest', + PresentTense: 'invests', + PastTense: 'invested', + Gerund: 'investing', + }, + { + Infinitive: 'age', + PresentTense: 'ages', + PastTense: 'aged', + Gerund: 'ageing', + }, + { + Infinitive: 'shed', + PresentTense: 'sheds', + PastTense: 'shed', + Gerund: 'shedding', + }, + { + Infinitive: 'ace', + PresentTense: 'aces', + PastTense: 'aced', + Gerund: 'acing', + }, + { + Infinitive: 'egg', + PresentTense: 'eggs', + PastTense: 'egged', + Gerund: 'egging', + }, +] +test('conjugation:', function(t) { + const test_conjugation = function(inf, o, form, original) { + const msg = 'from ' + original + ' to ' + form + ': [' + o[original] + '] -> [' + inf[form] + ']' + t.equal(inf[form], o[form], msg) + } + + arr.forEach(function(o) { + const forms = ['Infinitive', 'PastTense', 'PresentTense', 'Gerund'] + for (let i = 0; i < forms.length; i++) { + const from = forms[i] + const inf = nlp(o[from]) + .tag('Verb') + .verbs() + .conjugate()[0] + test_conjugation(inf, o, 'Infinitive', from) + test_conjugation(inf, o, 'PastTense', from) + test_conjugation(inf, o, 'PresentTense', from) + test_conjugation(inf, o, 'Gerund', from) + } + }) + t.end() +}) diff --git a/tests/verbs/misc.test.js b/tests/verbs/misc.test.js new file mode 100644 index 000000000..42ea337f8 --- /dev/null +++ b/tests/verbs/misc.test.js @@ -0,0 +1,18 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('verbs.adverbs', function(t) { + let doc = nlp('spencer is really great! Spencer really really was superb.') + doc + .verbs() + .adverbs() + .delete() + t.equal(doc.out(), 'spencer is great! Spencer was superb.', 'no-adverbs') + + doc = nlp('spencer truly would really run quickly') + .verbs() + .adverbs() + t.equal(doc.length, 3, 'found all three adverbs') + t.equal(doc.text('reduced'), 'truly really quickly', 'found adverbs in order') + t.end() +}) diff --git a/tests/verbs/modal.test.js b/tests/verbs/modal.test.js new file mode 100644 index 000000000..2e07bbccf --- /dev/null +++ b/tests/verbs/modal.test.js @@ -0,0 +1,37 @@ +const test = require('tape') +const nlp = require('../_lib') + +//ignore some modals during conjugation, i guess +test('ignore-would-behaviour', t => { + let doc = nlp('he would walk') + doc.verbs().toPastTense() + t.equal(doc.text(), 'he walked', 'would-past') + + doc = nlp('he would walk') + doc.verbs().toFutureTense() + t.equal(doc.out(), 'he will walk', 'would-future') + + doc = nlp('he would walk') + doc.verbs().toPresentTense() + t.equal(doc.out(), 'he walks', 'would-present') + + // str = nlp('he would walk') + // .verbs() + // .toContinuous() + // .out() + // t.equal(str, 'he is walking', 'would-continuous') + + t.end() +}) + +// test('ignore-would-behaviour', t => { +// const doc = nlp(`best look after`).verbs() +// const out = doc.conjugation() +// t.equal(doc.length, 1, 'one-verb') +// t.ok(out, 'no-error') +// t.end() +// }) + +//can/could +//might +//should diff --git a/tests/verbs/negate.test.js b/tests/verbs/negate.test.js new file mode 100644 index 000000000..b34a134a6 --- /dev/null +++ b/tests/verbs/negate.test.js @@ -0,0 +1,34 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('verb negate:', function(t) { + let arr = [ + ['is', 'is not'], + ['will', 'will not'], + ['will be', 'will not be'], + ['was', 'was not'], + + ['walks', 'does not walk'], + ['walked', 'did not walk'], + // ['walking', 'not walking'], + // ['walk', 'do not walk'], + ['will walk', 'will not walk'], + ['will have walked', 'will not have walked'], + + // ['corrupted', 'did not corrupt'], + ['jumped', 'did not jump'], + ['stunk up', 'did not stink up'], + + [`would study`, `would not study`], + [`could study`, `could not study`], + [`should study`, `should not study`], + ] + arr.forEach(function(a) { + const str = nlp(a[0]) + .verbs() + .toNegative() + .out('normal') + t.equal(str, a[1], a[1] + ' --- ' + str) + }) + t.end() +}) diff --git a/tests/verbs/parts.test.js b/tests/verbs/parts.test.js new file mode 100644 index 000000000..a53f520d7 --- /dev/null +++ b/tests/verbs/parts.test.js @@ -0,0 +1,114 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('verb-parts:', function(t) { + const tests = [ + ['john is walking', '', 'is', ''], + ['john was walking', '', 'was', ''], + ['john will be walking', '', 'will be', ''], + ['john has been walking', '', 'has been', ''], + ['john had been walking', '', 'had been', ''], + ['john would have had been walking', '', 'would have had been', ''], + //negatives + ['john is not walking', 'not', 'is', ''], + ['john was not walking', 'not', 'was', ''], + ['john will not be walking', 'not', 'will be', ''], + ['john will be not walking', 'not', 'will be', ''], + ['john has not been walking', 'not', 'has been', ''], + ['john has been not walking', 'not', 'has been', ''], + ['john had not been walking', 'not', 'had been', ''], + ['john had been not walking', 'not', 'had been', ''], + ['john would be walking', '', 'would be', ''], + ['john would not be walking', 'not', 'would be', ''], + ['john would be not walking', 'not', 'would be', ''], + ['john would not have had been walking', 'not', 'would have had been', ''], + ['john would have not had been walking', 'not', 'would have had been', ''], + ['john would have had not been walking', 'not', 'would have had been', ''], + ['john would have had been not walking', 'not', 'would have had been', ''], + //adverbs + negatives combinations + ['john is really walking', '', 'is', 'really'], + ['john really is walking', '', 'is', ''], + ['john is walking really', '', 'is', ''], + ['john is not really walking', 'not', 'is', 'really'], + ['john is really not walking', 'not', 'is', 'really'], + ['john really is not walking', 'not', 'is', ''], + ['john is not walking really', 'not', 'is', ''], + ['john has really been not walking', 'not', 'has been', 'really'], + ['john has been really not walking', 'not', 'has been', 'really'], + ['john has been not really walking', 'not', 'has been', 'really'], + ['john has been not walking really', 'not', 'has been', ''], + ['john really would not have had been walking', 'not', 'would have had been', ''], + ['john would really not have had been walking', 'not', 'would have had been', 'really'], + ['john would not really have had been walking', 'not', 'would have had been', 'really'], + ['john would not have really had been walking', 'not', 'would have had been', 'really'], + ['john would not have had really been walking', 'not', 'would have had been', 'really'], + ['john would not have had been really walking', 'not', 'would have had been', 'really'], + ['john would not have had been walking really', 'not', 'would have had been', ''], + ] + tests.forEach(function(a) { + const arr = nlp(a[0]) + .verbs() + .json() + t.equal(arr.length, 1, '#verbs - ' + arr.length) + t.equal(arr[0].parts.negative || '', a[1], "neg-test - '" + a[0] + "'") + t.equal(arr[0].parts.auxiliary || '', a[2], "aux-test - '" + a[0] + "'") + t.equal(arr[0].parts.verb || '', 'walking', "verb-test - '" + a[0] + "'") + t.equal(arr[0].parts.adverb || '', a[3], "adverb-test - '" + a[0] + "'") + }) + t.end() +}) + +//dont take it too-far +test('verb-greedy:', function(t) { + let arr = nlp('he would be, had he survived') + .verbs() + .json() + t.equal(arr.length, 2, 'split-on-clause') + + arr = nlp('we walked, talked, and sang') + .verbs() + .json() + t.equal(arr.length, 3, 'split-on-list') + + arr = nlp('we walked, talked, and quickly sang') + .verbs() + .json() + t.equal(arr.length, 3, 'split-on-list2') + + arr = nlp('we suddenly walked, talked, and abruptly sang') + .verbs() + .json() + t.equal(arr.length, 3, 'split-on-list3') + + arr = nlp('we really') + .verbs() + .json() + t.equal(arr.length, 0, 'adverb-isnt-a-verb') + + arr = nlp('we really really') + .verbs() + .json() + t.equal(arr.length, 0, 'two-adverbs-isnt-a-verb') + + arr = nlp('not good') + .verbs() + .json() + t.equal(arr.length, 0, 'not-isnt-a-verb') + + let str = nlp('we must not') + .verbs() + .out('normal') + t.equal(str, 'must not', 'verb-not') + + str = nlp('we must really') + .verbs() + .out('normal') + t.equal(str, 'must', 'verb-adverb') + + str = nlp('we must really not') + .verbs() + .out('normal') + t.equal(str, 'must really not', 'verb-adverb-not') + + t.end() +}) diff --git a/tests/verbs/phrasal.test.js b/tests/verbs/phrasal.test.js new file mode 100644 index 000000000..8087e613f --- /dev/null +++ b/tests/verbs/phrasal.test.js @@ -0,0 +1,22 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('phrasal-verbs:', function(t) { + ;[ + [`he is really good`, ['he', 'is', 'really', 'good']], + [`he is upset about it`, ['he', 'is', 'upset', 'about', 'it']], + [`he will mess about with it`, ['he', 'will', 'mess about', 'with', 'it']], + + [`come forward`, ['come forward']], + [`come together`, ['come together']], + [`come apart`, ['come apart']], + + [`frighten back`, ['frighten', 'back']], + [`frighten away`, ['frighten away']], + ].forEach(function(a) { + const terms = nlp(a[0]).out('array') + const msg = terms.join(' ') + ' -- ' + a[1].join(' ') + t.equal(terms.join(' '), a[1].join(' '), msg) + }) + t.end() +}) diff --git a/tests/verbs/plural.test.js b/tests/verbs/plural.test.js new file mode 100644 index 000000000..fec91ee84 --- /dev/null +++ b/tests/verbs/plural.test.js @@ -0,0 +1,34 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('plural-verbs:', function(t) { + let r = nlp('i look at') + let len = r.verbs().isPlural().length + t.equal(len, 0, 'i singular') + + r = nlp('we look at it. They report on it') + len = r.verbs().isPlural().length + t.equal(len, 2, 'they plural') + + r = nlp('lkjsdf are cool') + let str = r + .verbs() + .isPlural() + .out('normal') + t.equal(str, 'are', 'are plural') + + r = nlp('lkjsdf does eat bugs') + str = r + .verbs() + .isPlural() + .out('normal') + t.equal(str, 'does eat', 'does plural') + + r = nlp('lkjsdf is cool') + str = r + .verbs() + .isPlural() + .out('normal') + t.equal(str, '', 'is singular') + t.end() +}) diff --git a/tests/verbs/toGerund.test.js b/tests/verbs/toGerund.test.js new file mode 100644 index 000000000..710dd5a3e --- /dev/null +++ b/tests/verbs/toGerund.test.js @@ -0,0 +1,22 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('verb-to-gerund:', function(t) { + ;[ + ['walk', 'walking'], + ['sing', 'singing'], + ['win', 'winning'], + ['will convert', 'converting'], + ['see', 'seeing'], + ['is', 'being'], + ['was', 'being'], + ['am', 'being'], + ].forEach(function(a) { + const str = nlp(a[0]) + .verbs() + .toGerund() + .out('normal') + t.equal(str, a[1], str + ' -> ' + a[1]) + }) + t.end() +}) diff --git a/tests/verbs/toNegative.test.js b/tests/verbs/toNegative.test.js new file mode 100644 index 000000000..049a9ce49 --- /dev/null +++ b/tests/verbs/toNegative.test.js @@ -0,0 +1,49 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('verb-to-negative:', function(t) { + let arr = [ + [`he is nice`, 'is not'], + [`she was nice`, 'was not'], + + [`she has walked`, 'has not walked'], + [`she had walked`, 'had not walked'], + [`we have had problems`, 'have not had'], + [`we would walk`, 'would not walk'], + [`we would have walked`, 'would not have walked'], + + //conjugations + [`she walked`, 'did not walk'], + [`it all came apart`, 'did not come apart'], + + //phrasals + [`he would come forward`, 'would not come forward'], + [`we come together`, 'do not come together'], + [`he was frightened`, 'was not'], + [`i didn't want to`, "didn't want"], + + //===singular + // pastTense - + ['john played', 'did not play'], + // presentTense - + ['john plays', 'does not play'], + // futureTense - + ['john will play', 'will not play'], + + ///===plural + // pastTense - + ['we played', 'did not play'], + // presentTense - + ['we play', 'do not play'], + // futureTense - + ['we will play', 'will not play'], + ] + arr.forEach(function(a) { + const vb = nlp(a[0]) + .verbs() + .toNegative() + const str = vb.out('text') + t.equal(str, a[1], "'" + str + "' - - want: " + a[1]) + }) + t.end() +}) diff --git a/tests/verbs/verb-contractions.test.js b/tests/verbs/verb-contractions.test.js new file mode 100644 index 000000000..d8730dc00 --- /dev/null +++ b/tests/verbs/verb-contractions.test.js @@ -0,0 +1,20 @@ +const test = require('tape') +const nlp = require('../_lib') + +test('conjugate-contractions:', t => { + let arr = [ + [`i'm good`, 'i was good'], + [`they're good`, 'they were good'], + //TODO: missing auxillary + [`we've said`, 'we said'], //or 'we have said' + [`they'd said`, 'they said'], //or 'they have said' + // (ambiguous) + [`he's good`, 'he was good'], + ] + arr.forEach(a => { + const doc = nlp(a[0]) + doc.verbs().toPastTense() + t.equal(doc.out(), a[1], a[1]) + }) + t.end() +}) diff --git a/tests/whitespace-out.test.js b/tests/whitespace-out.test.js new file mode 100644 index 000000000..7a5ca1ed0 --- /dev/null +++ b/tests/whitespace-out.test.js @@ -0,0 +1,25 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('whitespace-out', function(t) { + let str = 'one, two three. One, two, four?' + const doc = nlp(str) + + t.equal(doc.out(), str, 'original-okay') // ✅ + + // some phrases, but full-phrases + t.equal(doc.eq(0).text(), 'one, two three.', '.eq(0) okay') // ✅ + t.equal(doc.eq(1).text(), 'One, two, four?', '.eq(1) okay') // ✅ + + t.equal(doc.match('four').text(), 'four', 'one match') // ✅ + + t.equal(doc.match('two').text(), 'two two', 'two single matches') // ✅ + t.equal(doc.match('one').text(), 'one, One', 'two more single matches') // ✅ + + t.equal(doc.match('one two').text(), 'one, two One, two', 'two multi-matches') // ✅ + + // t.equal(doc.not('two').out(), 'one, three. One, four?', '.not() okay') // ❌ + + // t.equal(doc.match('.').out(), str, 'every word') // ❌ + t.end() +}) diff --git a/tests/wordcount.test.js b/tests/wordcount.test.js new file mode 100644 index 000000000..f9f0b7c7a --- /dev/null +++ b/tests/wordcount.test.js @@ -0,0 +1,33 @@ +const test = require('tape') +const nlp = require('./_lib') + +test('==WordCount==', function(t) { + let arr = [ + ['he is good', 3], + ['jack and jill went up the hill.', 7], + ['Mr. Clinton did so.', 4], + ['Bill Clinton ate cheese.', 4], + ['5kb of data.', 3], + ['it was five hundred and seventy two.', 7], + ['jack and jill went up the hill. They got water.', 10], + ['Bill Clinton went walking', 4], + ['Bill Clinton will go walking', 5], + [`is not isn't. it sure is.`, 6], + ] + arr.forEach(function(a) { + const doc = nlp(a[0]) + t.equal(doc.wordCount(), a[1], a[0]) + }) + t.end() +}) + +test('match-wordcount', function(t) { + let doc = nlp("he is cool. she is nice. it isn't here.") + t.equal(doc.eq(1).wordCount(), 3, 'middle-sentence') + t.equal(doc.match('(he|she)').wordCount(), 2, 'he/she match') + t.equal(doc.match('is').wordCount(), 3, 'is-contraction match') + //i guess!? + t.equal(doc.match('not').wordCount(), 0, 'not-contraction match') + t.equal(doc.match('not').length, 1, 'length-vs-wordCount') + t.end() +}) diff --git a/types/index.d.ts b/types/index.d.ts index 5d7676201..b5802a7c0 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,189 +1,233 @@ -declare function compromise(text: string, lexicon?: { [word: string]: string }): compromise.Text; -declare namespace compromise { - const version: string; - function verbose(str: any): void; - function tokenize(str: string): any; - function plugin(obj: any): any; - function clone(): any; - function unpack(...args: any[]): void; - function addWords(...args: any[]): void; - function addTags(...args: any[]): void; - function addRegex(...args: any[]): void; - function addPatterns(...args: any[]): void; - function addPlurals(...args: any[]): void; - function addConjugations(conj: { [verb: string]: Conjugation }): void; - - interface Conjugation { - Gerund?: string; - PresentTense?: string; - PastTense?: string; - PerfectTense?: string; - PluPerfectTense?: string; - FuturePerfect?: string; - Actor?: string; - } - - interface Text { - /** did it find anything? */ - readonly found: boolean; - /** just a handy wrap */ - readonly parent: Text; - /** how many Texts are there? */ - readonly length: number; - /** nicer than constructor.call.name or whatever */ - readonly isA: 'Text'; - /** the whitespace before and after this match */ - readonly whitespace: { - before(str: string): Text, - after(str: string): Text - }; - - acronyms(...args: any[]): any; - adjectives(...args: any[]): any; - adverbs(...args: any[]): any; - contractions(...args: any[]): any; - dates(...args: any[]): any; - nouns(...args: any[]): any; - people(...args: any[]): any; - sentences(...args: any[]): any; - terms(...args: any[]): any; - possessives(...args: any[]): any; - values(...args: any[]): any; - verbs(...args: any[]): any; - ngrams(...args: any[]): any; - startGrams(...args: any[]): any; - endGrams(...args: any[]): any; - words(...args: any[]): any; - - // misc - all(...args: any[]): any; - index(...args: any[]): any; - wordCount(...args: any[]): any; - data(...args: any[]): any; - /* javascript array loop-wrappers */ - map(...args: any[]): any; - forEach(...args: any[]): any; - filter(...args: any[]): any; - reduce(...args: any[]): any; - find(...args: any[]): any; - /** copy data properly so later transformations will have no effect */ - clone(...args: any[]): any; - - /** get the nth term of each result */ - term(...args: any[]): any; - firstTerm(...args: any[]): any; - lastTerm(...args: any[]): any; - - /** grab a subset of the results */ - slice(...args: any[]): any; - - /** use only the nth result */ - get(...args: any[]): any; - /** use only the first result */ - first(...args: any[]): any; - /** use only the last result */ - last(...args: any[]): any; - - concat(...args: any[]): any; - - /** make it into one sentence/termlist */ - flatten(...args: any[]): any; - - /** see if these terms can become this tag */ - canBe(...args: any[]): any; - - /** sample part of the array */ - random(...args: any[]): any; - setPunctuation(...args: any[]): any; - getPunctuation(...args: any[]): any; - // jquery-like api aliases - offset(...args: any[]): any; - text(...args: any[]): any; - eq(...args: any[]): any; - join(...args: any[]): any; - - // loops - toTitleCase(...args: any[]): any; - toUpperCase(...args: any[]): any; - toLowerCase(...args: any[]): any; - toCamelCase(...args: any[]): any; - - hyphenate(...args: any[]): any; - dehyphenate(...args: any[]): any; - trim(...args: any[]): any; - - insertBefore(...args: any[]): any; - insertAfter(...args: any[]): any; - insertAt(...args: any[]): any; - - replace(...args: any[]): any; - replaceWith(...args: any[]): any; - - delete(...args: any[]): any; - lump(...args: any[]): any; - - tagger(...args: any[]): any; - - tag(...args: any[]): any; - unTag(...args: any[]): any; - - // match - /** do a regex-like search through terms and return a subset */ - match(...args: any[]): any; - - not(...args: any[]): any; - - if(...args: any[]): any; - - ifNo(...args: any[]): any; - - has(...args: any[]): any; - - /** find a match and return everything in front of it */ - before(...args: any[]): any; - - /** find a match and return everything after it */ - after(...args: any[]): any; - // alias 'and' - and(...args: any[]): any; - notIf(...args: any[]): any; - only(...args: any[]): any; - onlyIf(...args: any[]): any; - - // out - out(...args: any[]): any; - debug(...args: any[]): any; - - // sort - /** reorder result.list alphabetically */ - sort(...args: any[]): any; - /** reverse the order of result.list */ - reverse(...args: any[]): any; - unique(...args: any[]): any; - - // split - /** turn result into two seperate results */ - splitAfter(...args: any[]): any; - /** turn result into two seperate results */ - splitBefore(...args: any[]): any; - /** turn result into two seperate results */ - splitOn(...args: any[]): any; - - // normalize - normalize(...args: any[]): any; - - // subsets - clauses(...args: any[]): any; - hashTags(...args: any[]): any; - organizations(...args: any[]): any; - phoneNumbers(...args: any[]): any; - places(...args: any[]): any; - quotations(...args: any[]): any; - topics(...args: any[]): any; - urls(...args: any[]): any; - questions(...args: any[]): any; - statements(...args: any[]): any; - parentheses(...args: any[]): any; +export as namespace nlp + +declare function nlp(text: string): nlp.Document + +// Constructor +declare module nlp { + /** parse text into a compromise object, without running POS-tagging */ + export function tokenize(text: string): Document + /** mix in a compromise-plugin */ + export function extend(plugin: any): Document + /** re-generate a Doc object from .json() results */ + export function load(json: any): Document + /** log our decision-making for debugging */ + export function verbose(bool: boolean): Document + /** current semver version of the library */ + export const version: Document + + class Document { + // Utils + /** return the whole original document ('zoom out') */ + all(): Document + /** is this document empty? */ + found: Boolean + /** return the previous result */ + parent(): Document + /** return all of the previous results */ + parents(): Document[] + /** (re)run the part-of-speech tagger on this document */ + tagger(): Document + /** count the # of terms in each match */ + wordCount(): Number + /** count the # of characters of each match */ + length(): Number + /** deep-copy the document, so that no references remain */ + clone(shallow?: Boolean): Document + /** freeze the current state of the document, for speed-purposes */ + cache(options?: Object): Document + /** un-freezes the current state of the document, so it may be transformed */ + uncache(options?: Object): Document + + // Accessors + /** use only the first result(s) */ + first(n?: Number): Document + /** use only the last result(s) */ + last(n?: Number): Document + /** grab a subset of the results */ + slice(start: Number, end?: Number): Document + /** use only the nth result */ + eq(n: Number): Document + /** get the first word in each match */ + firstTerm(): Document + /** get the end word in each match */ + lastTerm(): Document + /** return a flat list of all Term objects in match */ + termList(): any + + // Match + /** return a new Doc, with this one as a parent */ + match(match: String | Document): Document + /** return all results except for this */ + not(match: String | Document): Document + /** return only the first match */ + matchOne(match: String | Document): Document + /** return each current phrase, only if it contains this match */ + if(match: String | Document): Document + /** Filter-out any current phrases that have this match */ + ifNo(match: String | Document): Document + /** Return a boolean if this match exists */ + has(match: String | Document): Document + /** search through earlier terms, in the sentence */ + lookBehind(match: String | Document): Document + /** search through following terms, in the sentence */ + lookAhead(match: String | Document): Document + /** return the terms before each match */ + before(match: String | Document): Document + /** return the terms after each match */ + after(match: String | Document): Document + /** quick find for an array of string matches */ + lookup(matches: String[]): Document + + // Case + /** turn every letter of every term to lower-cse */ + toLowerCase(): Document + /** turn every letter of every term to upper case */ + toUpperCase(): Document + /** upper-case the first letter of each term */ + toTitleCase(): Document + /** remove whitespace and title-case each term */ + toCamelCase(): Document + + // Whitespace + /** add this punctuation or whitespace before each match */ + pre(str: String): Document + /** add this punctuation or whitespace after each match */ + post(str: String): Document + /** remove start and end whitespace */ + trim(): Document + /** connect words with hyphen, and remove whitespace */ + hyphenate(): Document + /** remove hyphens between words, and set whitespace */ + dehyphenate(): Document + + // Tag + /** Give all terms the given tag */ + tag(tag: String, reason?: String): Document + /** Only apply tag to terms if it is consistent with current tags */ + tagSafe(tag: String, reason?: String): Document + /** Remove this term from the given terms */ + unTag(tag: String, reason?: String): Document + /** return only the terms that can be this tag */ + canBe(tag: String): Document + + // Loops + /** run each phrase through a function, and create a new document */ + map(fn: Function): Document | [] + /** run a function on each phrase, as an individual document */ + forEach(fn: Function): Document + /** return only the phrases that return true */ + filter(fn: Function): Document + /** return a document with only the first phrase that matches */ + find(fn: Function): Document | undefined + /** return true or false if there is one matching phrase */ + some(fn: Function): Document + /** sample a subset of the results */ + random(n?: Number): Document + + // Insert + /** substitute-in new content */ + replaceWith(text: String | Function, keepTags?: Boolean, keepCase?: Boolean): Document + /** search and replace match with new content */ + replace(match: String, text?: String | Function, keepTags?: Boolean, keepCase?: Boolean): Document + /** fully remove these terms from the document */ + delete(match: String): Document + /** add these new terms to the end (insertAfter) */ + append(text: String): Document + /** add these new terms to the front (insertBefore) */ + prepend(text: String): Document + /** add these new things to the end */ + concat(text: String): Document + + // transform + /**re-arrange the order of the matches (in place) */ + sort(method?: String | Function): Document + /**reverse the order of the matches, but not the words */ + reverse(): Document + /** clean-up the document, in various ways */ + normalize(options?: String | Object): String + /** remove any duplicate matches */ + unique(): Document + /** return a Document with three parts for every match ('splitOn') */ + split(match?: String): Document + /** separate everything after the match as a new phrase */ + splitBefore(match?: String): Document + /** separate everything before the word, as a new phrase */ + splitAfter(match?: String): Document + /** split a document into labeled sections */ + segment(regs: Object, options?: Object): Document + /** make all phrases into one phrase */ + join(str?: String): Document + + // Output + /** return the document as text */ + text(options?: String | Object): String + /** pull out desired metadata from the document */ + json(options?: String | Object): any + /** some named output formats */ + out(format?: string): String + /** pretty-print the current document and its tags */ + debug(): Document + /** store a parsed document for later use */ + export(): any + + // Selections + /** split-up results by each individual term */ + terms(n?: Number): Document + /** split-up results into multi-term phrases */ + clauses(n?: Number): Document + /** return all terms connected with a hyphen or dash like `'wash-out'`*/ + hyphenated(n?: Number): Document + /** add quoation marks around each match */ + toQuoations(start?: String, end?: String): Document + /** add brackets around each match */ + toParentheses(start?: String, end?: String): Document + /** return things like `'(939) 555-0113'` */ + phoneNumbers(n?: Number): Document + /** return things like `'#nlp'` */ + hashTags(n?: Number): Document + /** return things like `'hi@compromise.cool'` */ + emails(n?: Number): Document + /** return things like `:)` */ + emoticons(n?: Number): Document + /** return athings like `💋` */ + emoji(n?: Number): Document + /** return things like `'@nlp_compromise'`*/ + atMentions(n?: Number): Document + /** return things like `'compromise.cool'` */ + urls(n?: Number): Document + /** return things like `'quickly'` */ + adverbs(n?: Number): Document + /** return things like `'he'` */ + pronouns(n?: Number): Document + /** return things like `'but'`*/ + conjunctions(n?: Number): Document + /** return things like `'of'`*/ + prepositions(n?: Number): Document + /** return things like `'Mrs.'`*/ + abbreviations(n?: Number): Document + + // Subsets + /** alias for .all(), until plugin overloading */ + sentences(): Document + /** return any multi-word terms, like "didn't" */ + contractions(n?: Number): Document + /** contract words that can combine, like "did not" */ + contract(): Document + /** return anything inside (parentheses) */ + parentheses(n?: Number): Document + /** return things like "Spencer's" */ + possessives(n?: Number): Document + /** return any terms inside 'quotation marks' */ + quotations(n?: Number): Document + /** return things like `'FBI'` */ + acronyms(n?: Number): Document + /** return things like `'eats, shoots, and leaves'` */ + lists(n?: Number): Document + /** return any subsequent terms tagged as a Noun */ + nouns(n?: Number): Document + /** return any subsequent terms tagged as a Verb */ + verbs(n?: Number): Document } } -export = compromise; + +export default nlp diff --git a/types/test.ts b/types/test.ts deleted file mode 100644 index 25a82afd6..000000000 --- a/types/test.ts +++ /dev/null @@ -1,16 +0,0 @@ -// tslint:disable:no-relative-import-in-test - -// importing via absolute path appears to be broken because this package -// indirectly imports itself (compromise -> compromise-plugin -> compromise), -// which brings in an older, broken version of its typings that typescript -// always seems to prefer over the typings in the repo proper. -import * as compromise from '.'; - -// $ExpectType Text -const r = compromise('he is fun', {}); - -r.verbs().out(); -r.debug(); - -// $ExpectType void -compromise.addConjugations({ eat: { Actor: "eater" } }); diff --git a/types/tsconfig.json b/types/tsconfig.json index 981f19be5..dd1bf1f5b 100644 --- a/types/tsconfig.json +++ b/types/tsconfig.json @@ -1,14 +1,23 @@ { "compilerOptions": { + "target": "es5", "module": "commonjs", - "lib": [ - "es6" - ], + "lib": [], + "checkJs": true, + "allowJs": true, + "sourceMap": false, + "importHelpers": true, + "downlevelIteration": true, + "strict": true, "noImplicitAny": true, - "noImplicitThis": true, "strictNullChecks": true, - "strictFunctionTypes": true, - "noEmit": true, - "baseUrl": "." + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "allowSyntheticDefaultImports": true } } diff --git a/types/types.test.ts b/types/types.test.ts new file mode 100644 index 000000000..0848f7ae6 --- /dev/null +++ b/types/types.test.ts @@ -0,0 +1,15 @@ +// a smoke-test for our typescipt typings +// to run: +// npm install -g typescript +// npm install -g ts-node +// npm install --no-save @types/tape @types/node +// npm run test:types + +const test = require('tape') +import nlp from '../' + +test('typefile smoketest', (t: any) => { + const doc = nlp('hello world') + t.equal(doc.text(), 'hello world', 'basic-smoketest') + t.end() +})