first commit
This commit is contained in:
3
node_modules/indefinite/.babelrc
generated
vendored
Normal file
3
node_modules/indefinite/.babelrc
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": [["@babel/preset-env", { "modules": false }]]
|
||||
}
|
||||
22
node_modules/indefinite/.codeclimate.yml
generated
vendored
Normal file
22
node_modules/indefinite/.codeclimate.yml
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
engines:
|
||||
eslint:
|
||||
enabled: true
|
||||
channel: "eslint-3"
|
||||
config:
|
||||
config: '.eslint.json'
|
||||
duplication:
|
||||
enabled: false
|
||||
config:
|
||||
languages:
|
||||
- javascript
|
||||
exclude_patterns:
|
||||
- ".*.*"
|
||||
- ".*"
|
||||
- "dist/**.js"
|
||||
- "gulp/**.js"
|
||||
- "test/**.*"
|
||||
- "**.json"
|
||||
- "**.md"
|
||||
- "*.js"
|
||||
- "**.coffee"
|
||||
- "LICENSE"
|
||||
90
node_modules/indefinite/.eslint.json
generated
vendored
Normal file
90
node_modules/indefinite/.eslint.json
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"mocha": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"strict": "off",
|
||||
"quotes": ["error", "single", {
|
||||
"avoidEscape": true,
|
||||
"allowTemplateLiterals": true
|
||||
}],
|
||||
"no-undef": "error",
|
||||
"no-unused-vars": ["error", {
|
||||
"args": "none"
|
||||
}],
|
||||
"no-trailing-spaces": "error",
|
||||
"no-underscore-dangle": "off",
|
||||
"indent": ["error", 2, {
|
||||
"SwitchCase": 1
|
||||
}],
|
||||
"no-octal": "off",
|
||||
"no-multiple-empty-lines": ["error", {
|
||||
"max": 1
|
||||
}],
|
||||
"no-debugger": "error",
|
||||
"no-empty": ["error", {
|
||||
"allowEmptyCatch": true
|
||||
}],
|
||||
"no-template-curly-in-string": "warn",
|
||||
"no-unreachable": "error",
|
||||
"valid-typeof": "error",
|
||||
"dot-notation": ["error", {
|
||||
"allowKeywords": false
|
||||
}],
|
||||
"eqeqeq": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-multi-spaces": "error",
|
||||
"no-sequences": "error",
|
||||
"wrap-iife": ["error", "inside"],
|
||||
"yoda": ["error", "never"],
|
||||
"no-path-concat": "error",
|
||||
"array-bracket-spacing": ["error", "always", {
|
||||
"singleValue": false,
|
||||
"objectsInArrays": false,
|
||||
"arraysInArrays": false
|
||||
}],
|
||||
"brace-style": ["error", "1tbs"],
|
||||
"camelcase": ["error", {
|
||||
"properties": "always"
|
||||
}],
|
||||
"comma-spacing": ["error", {
|
||||
"before": false,
|
||||
"after": true
|
||||
}],
|
||||
"comma-style": ["error", "last"],
|
||||
"consistent-this": ["error", "self"],
|
||||
"func-style": ["error", "expression", {
|
||||
"allowArrowFunctions": true
|
||||
}],
|
||||
"key-spacing": ["error", {
|
||||
"beforeColon": false,
|
||||
"afterColon": true,
|
||||
"mode": "strict"
|
||||
}],
|
||||
"keyword-spacing": ["error", {
|
||||
"before": true,
|
||||
"after": true
|
||||
}],
|
||||
"no-lonely-if": "error",
|
||||
"no-tabs": "error",
|
||||
"no-whitespace-before-property": "error",
|
||||
"object-curly-spacing": ["error", "always", {
|
||||
"arraysInObjects": false,
|
||||
"objectsInObjects": false
|
||||
}],
|
||||
"object-property-newline": "error",
|
||||
"semi": ["error", "always", {
|
||||
"omitLastInOneLineBlock": true
|
||||
}],
|
||||
"space-before-blocks": ["error", "always"],
|
||||
"arrow-spacing": ["error", {
|
||||
"before": true,
|
||||
"after": true
|
||||
}],
|
||||
"prefer-template": "error",
|
||||
"no-const-assign": "error"
|
||||
}
|
||||
}
|
||||
19
node_modules/indefinite/.travis.yml
generated
vendored
Normal file
19
node_modules/indefinite/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
addons:
|
||||
code_climate:
|
||||
repo_token: "7db887541ba6df3075e3a6ead2456b0ddf6bee65969308191c62afe1ea461566"
|
||||
install:
|
||||
- "npm install"
|
||||
script:
|
||||
- "npm run travis"
|
||||
node_js:
|
||||
- 9
|
||||
- 10
|
||||
- 11
|
||||
- 12
|
||||
- 13
|
||||
- 14
|
||||
cache:
|
||||
directories:
|
||||
- 'node_modules'
|
||||
77
node_modules/indefinite/CONTRIBUTING.md
generated
vendored
Normal file
77
node_modules/indefinite/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
# Contributing
|
||||
|
||||
First, contributions are welcome! I expect smaller requests to be handled without issue. If you have a larger feature request that you want to contribute yourself, you might consider opening an issue first, as I make no guarantees about merging things, especially if they change the nature of the project, or make it do _a lot_ more than it already does. I'm a proponent of small, concise, single-purpose modules that do one thing and do it well.
|
||||
|
||||
## Style
|
||||
|
||||
Please try to adhere, as close as possible, to the style and structure already present in this repository. Please don't be offended if I ask you clean something up, as consistency is important. Please see the `.eslint.json` config for a comprehensive style guide. Some of the more salient points follow:
|
||||
|
||||
1. Two spaces. No literal tabs.
|
||||
2. "Cuddled" elses and else ifs: e.g. `} else {`
|
||||
3. Prefer
|
||||
|
||||
```
|
||||
exports.foo = function() {
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```
|
||||
module.exports = {
|
||||
foo: function() {
|
||||
```
|
||||
|
||||
unless you're exporting a single a function, like
|
||||
|
||||
```
|
||||
module.exports = function() {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
4. Use spaces at the beginning and end of inline objects and arrays: `{ foo: 'bar' }` and `[ 'foo', 'bar' ]`
|
||||
5. But . . . if you have longer objects, please use line breaks like this:
|
||||
|
||||
```
|
||||
var obj = {
|
||||
foo: 'bar',
|
||||
list: [
|
||||
{
|
||||
name: baz'
|
||||
},
|
||||
{
|
||||
name: 'quux'
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
I could also be okay with the slightly more compact array-of-object format:
|
||||
|
||||
```
|
||||
var obj = {
|
||||
foo: 'bar',
|
||||
list: [{
|
||||
name: baz'
|
||||
}, {
|
||||
name: 'quux'
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
6. Use semi-colons to end lines.
|
||||
7. Prefer single quotes _almost all the time_. The only places I use double quotes are 1) in json strings, 2) in html attributes, and 3) in quotes that have apostrophes in them (and even then, I sometimes just escape the apostrophe).
|
||||
8. Be modular. I like semantically-named noun-based modules (e.g. a module that handles git stuff in a repo would be called "git") with one or more verb-named functions (like, "getRepo") that do related things. Individual functions should fit on the screen whenever possible. I don't like scrolling to see what's happening at the end of a function. And in general, modules should be relatively short. I would rather have a larger number of short modules, than a smaller number of long modules.
|
||||
9. Use camel casing for variables. I have an inexplicable and arbitrary dislike for snake case.
|
||||
10. Use kebab case (foo-bar) for file names.
|
||||
11. Be DRY. If you find yourself reusing code, pull it out into a separate function.
|
||||
12. No coffeescript, typescript, or flow. I like javascript the way it is. Please do use es6 features if you like though.
|
||||
13. Please comment where appropriate. When in doubt, add a comment. I'm finding more and more that things that seem self-documenting when I write them are actually semi-incomprehensible when I read them. Inline comments are fine most of the time, though jsdoc style block comments before functions are nice too.
|
||||
|
||||
## Testing
|
||||
|
||||
Please write tests for any added feature or bug fix. Tests are run with gulp.
|
||||
|
||||
## Commits and Git History
|
||||
|
||||
I actually don't care much about commit message formatting or keeping a clean history via squashes. Obviously, if you _want_ to do those things, that's fine, but I won't make you. In general, I think a commit message should be atomic (which is to say, if you need to use the word "and," then it should be two commits), should summarize the changes in the commit, and should use present tense, as in "Fix bug" (not "Fixed" or "Fixes").
|
||||
21
node_modules/indefinite/LICENSE
generated
vendored
Normal file
21
node_modules/indefinite/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Andrew Nichols
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
75
node_modules/indefinite/README.md
generated
vendored
Normal file
75
node_modules/indefinite/README.md
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
[](https://travis-ci.org/tandrewnichols/indefinite) [](https://npmjs.org/package/indefinite) [](https://npmjs.org/package/indefinite) [](https://codeclimate.com/github/tandrewnichols/indefinite) [](https://codeclimate.com/github/tandrewnichols/indefinite) [](https://david-dm.org/tandrewnichols/indefinite) 
|
||||
|
||||
# indefinite
|
||||
|
||||
Prefix a noun with an indefinite article - a or an - based on whether it begins with a vowel.
|
||||
|
||||
## Installation
|
||||
|
||||
`npm install --save indefinite`
|
||||
|
||||
## Summary
|
||||
|
||||
It's not hard to check whether a noun begins with a vowel and decide whether to prefix with "a" or "an," but I got tired of doing it manually every time. So now there's this. Just pass in the word, and `indefinite` will return the word prefixed with either "a " or "an " depending on the first letter of the word.
|
||||
|
||||
As of version 2.0.0, `indefinite` will attempt to detect when an acronym is passed in and treat the response differently. E.g. it should be "a UFO" not "an UFO" because of how we pronounce a long U. This isn't a perfect science, so you might have false positives.
|
||||
|
||||
As of version 2.0.2, `indefinite` will also consult a list of irregular words to determine the appropriate article. For example, it should be "an hour" not "a hour." It also _attempts_ to do this with various forms of the words (checking for singular, plural, and even past tense, since past tense verbs can be used as adjectives, as in "an honored man"). This is not an exact science either, and the list of irregulars is not exhaustive (and probably won't ever be), but if you find a word that's not in the list that's returning the wrong thing, please open an issue so it can be corrected.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var a = require('indefinite');
|
||||
|
||||
console.log(a('apple')); // "an apple"
|
||||
console.log(a('banana')); // "a banana"
|
||||
console.log(a('UFO')); // 'a UFO'
|
||||
console.log(a('hour')); // 'an hour'
|
||||
console.log(a('ukelele')); // 'a ukelele'
|
||||
```
|
||||
|
||||
Indefinite also accepts an options object as the second parameter. The following options are supported:
|
||||
|
||||
- `articleOnly` - Return only the article.
|
||||
- `capitalize` - Capitalize the article.
|
||||
- `caseInsensitive` - Ignore the casing of the word passed in (i.e. bypassing the acronym checking). This is useful if, for some reason, you're yelling on the internet and want to make sure "UGLY GARDEN GNOME" doesn't become "a UGLY GARDEN GNOME."
|
||||
- `numbers` - When numbers are passed in, they are prefixed with "a" except for 8, 11, 18, and higher numbers starting with 8. _However_, numbers like 1100 are ambiguous. Should it be "a one thousand one hundred" or "an eleven hundred"? There's not really any programmatic way to know this for sure, but if _you_ know for sure, you can use the `numbers` option to tell `indefinite` how to handle these cases. The default is "formal" in which numbers are read literally (the way you'd say them if they were written out), but if you pass `numbers: 'colloquial'`, the "eleven hundred"/"eighteen hundred" readings will be used.
|
||||
|
||||
```js
|
||||
console.log(a('apple', { articleOnly: true })); // 'an'
|
||||
console.log(a('banana', { articleOnly: true })); // 'a'
|
||||
console.log(a('apple', { capitalize: true })); // 'An apple'
|
||||
console.log(a('banana', { capitalize: true })); // 'A banana'
|
||||
console.log(a('UGLY SWEATER', { caseInsensitive: true })); // 'an UGLY SWEATER'
|
||||
console.log(a('2')); // 'a 2'
|
||||
console.log(a('8')); // 'an 8'
|
||||
console.log(a('1892')); // 'a 1892' -> read "a one thousand eight hundred ninety-two"
|
||||
console.log(a('1892', { numbers: 'colloquial' })); // 'an 1892' -> read "an eighteen ninety-two"
|
||||
```
|
||||
|
||||
### Browser
|
||||
|
||||
Files in `dist` are UMD format, and `package.json` contains a `browser` field pointing to `dist/indefinite.js`, so you should be able to bundle this via webpack, rollup, browserify, etc. or serve it in ye olde javascript fashion and access it via window.
|
||||
|
||||
## Detecting the need for an indefinite article
|
||||
|
||||
It's worth mentioning that `indefintite` currently only differentiates between `a` and `an` for you. It doesn't do anything to decide if an indefinite article is required, so if you pass a plural to `indefinite`, you'll get something like "a shoes" back, which is obviously wrong. You can look at [this issue](https://github.com/tandrewnichols/indefinite/issues/23) for more context on why this isn't supported at the moment. It _could_ be in the future, but there are some prohibitive issues to work through first. For now, it is up to you (the consumer) to either call or not call `indefinite` depending on the plurality of the word. You can do something like the suggestion in that issue:
|
||||
|
||||
```javascript
|
||||
const indefinite = require('indefinite');
|
||||
const pluralize = require('pluralize');
|
||||
|
||||
module.exports = (subject) => {
|
||||
if (pluralize(subject) === subject) {
|
||||
return subject;
|
||||
}
|
||||
|
||||
return indefinite(subject);
|
||||
};
|
||||
```
|
||||
|
||||
Or you can try [is-singular](https://www.npmjs.com/package/is-singular) or [is-plural](https://www.npmjs.com/package/is-plural).
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [the contribution guidelines](contributing.md).
|
||||
306
node_modules/indefinite/dist/indefinite.js
generated
vendored
Normal file
306
node_modules/indefinite/dist/indefinite.js
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory();
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define([], factory);
|
||||
else if(typeof exports === 'object')
|
||||
exports["indefinite"] = factory();
|
||||
else
|
||||
root["indefinite"] = factory();
|
||||
})(self, () => {
|
||||
return /******/ (() => { // webpackBootstrap
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 769:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
var STARTS_WITH_VOWEL = /^[aeiouAEIOU]/;
|
||||
|
||||
/**
|
||||
* Array#indexOf is faster IF the word starts with "a" (for example),
|
||||
* but negligibly faster when you have to .toLowerCase() the word, and
|
||||
* slower if the word happens to start with (e.g.) "u."
|
||||
*/
|
||||
exports.startsWithVowel = function (word) {
|
||||
return STARTS_WITH_VOWEL.test(word);
|
||||
};
|
||||
exports.capitalize = function (article, opts) {
|
||||
if (opts.capitalize) {
|
||||
article = "".concat(article.charAt(0).toUpperCase()).concat(article.slice(1));
|
||||
}
|
||||
return article;
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 393:
|
||||
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
||||
|
||||
var _require = __webpack_require__(769),
|
||||
capitalize = _require.capitalize;
|
||||
var irregulars = __webpack_require__(725);
|
||||
var rules = __webpack_require__(803);
|
||||
var indefinite = function indefinite(word) {
|
||||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
var article;
|
||||
|
||||
/**
|
||||
* I'd really prefer to use for of here, but babel converts that
|
||||
* to something using Symbol.iterator, which PhantomJS chokes on.
|
||||
*/
|
||||
rules.some(function (rule) {
|
||||
if (rule.check(word, opts)) {
|
||||
article = rule.run(word, opts);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return handleOptions(article, opts, word);
|
||||
};
|
||||
var handleOptions = function handleOptions(article, opts, word) {
|
||||
article = capitalize(article, opts);
|
||||
if (opts.articleOnly) {
|
||||
return article;
|
||||
}
|
||||
return "".concat(article, " ").concat(word);
|
||||
};
|
||||
indefinite.irregularWords = irregulars.list;
|
||||
module.exports = indefinite;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 725:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
exports.check = function (word, ending) {
|
||||
if (ending) {
|
||||
// If the word ends in the ending, remove it.
|
||||
var regex = new RegExp("".concat(ending, "$"));
|
||||
word = word.replace(regex, '');
|
||||
if (word.length <= 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return exports.list.indexOf(word) > -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Here follows a List of words that take irregular articles because their
|
||||
* first letter is either a consonant pronounced like a vowel (hour) or a
|
||||
* vowel proncounced like a consonant (ukelele). Note that this is not only
|
||||
* nouns because adjectives and adverbs that start with these letters could
|
||||
* also follow an article when they identify a later noun, as in "a useless
|
||||
* tool."
|
||||
*
|
||||
* This is not an attempt at a complete list, but rather a collection of
|
||||
* words used in at least moderate frequency. A list of ALL irregular words
|
||||
* would be too exhaustive to compile without some sort of tool.
|
||||
* http://www.thefreedictionary.com/words-that-start-with-eu says there are
|
||||
* over 1800 words starting with "eu" alone.
|
||||
*
|
||||
* At least for now, this list omits proper names, as they aren't USUALLY
|
||||
* used in such a way as to require an _indefinite_ article. I can't think,
|
||||
* for example, of a case where you'd want to say "a Eustace."
|
||||
*/
|
||||
exports.list = [
|
||||
// Nouns: eu like y
|
||||
'eunuch', 'eucalyptus', 'eugenics', 'eulogy', 'euphemism', 'euphony', 'euphoria', 'eureka',
|
||||
// Adjectives: eu like y
|
||||
'euro', 'european', 'euphemistic', 'euphonic', 'euphoric',
|
||||
// Adverbs: eu like y
|
||||
'euphemistically', 'euphonically', 'euphorically',
|
||||
// Nouns: silent h
|
||||
'heir', 'heiress', 'herb', 'homage', 'honesty', 'honor', 'honour', 'honoree', 'hour',
|
||||
// Adjectives: silent h
|
||||
'honest', 'honorous', 'honorific', 'honorable', 'honourable',
|
||||
// Adverbs: silent h
|
||||
'honestly', 'hourly',
|
||||
// Nouns: o like w
|
||||
'one', 'ouija',
|
||||
// Adjectives: o like w
|
||||
'once',
|
||||
// Adverbs: o like w
|
||||
|
||||
// Nouns: u like y
|
||||
'ubiquity', 'udometer', 'ufo', 'uke', 'ukelele', 'ululate', 'unicorn', 'unicycle', 'uniform', 'unify', 'union', 'unison', 'unit', 'unity', 'universe', 'university', 'upas', 'ural', 'uranium', 'urea', 'ureter', 'urethra', 'urine', 'urologist', 'urology', 'urus', 'usage', 'use', 'user', 'usual', 'usurp', 'usurper', 'usury', 'utensil', 'uterus', 'utility', 'utopia', 'utricle', 'uvarovite', 'uvea', 'uvula', 'utah', 'utahn',
|
||||
// Adjectives: u like y
|
||||
'ubiquitous', 'ugandan', 'ukrainian', 'unanimous', 'unicameral', 'unified', 'unique', 'unisex', 'universal', 'urinal', 'urological', 'useful', 'useless', 'usurious', 'utilitarian', 'utopic',
|
||||
// Adverbs: u like y
|
||||
'ubiquitously', 'unanimously', 'unicamerally', 'uniquely', 'universally', 'urologically', 'usefully', 'uselessly', 'usuriously',
|
||||
// Nouns: y like i
|
||||
'yttria', 'yggdrasil', 'ylem', 'yperite', 'ytterbia', 'ytterbium', 'yttrium',
|
||||
// Adjectives: y like i
|
||||
'ytterbous', 'ytterbic', 'yttric',
|
||||
// Single letters
|
||||
'f', 'h', 'l', 'm', 'n', 'r', 's', 'u', 'x'];
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 803:
|
||||
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
||||
|
||||
module.exports = [__webpack_require__(374), __webpack_require__(532), __webpack_require__(202)];
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 532:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
var _require = __webpack_require__(769),
|
||||
startsWithVowel = _require.startsWithVowel;
|
||||
var ACRONYM = /^[A-Z]+$/;
|
||||
var IRREGULAR_ACRONYM = /^[UFHLMNRSX]/;
|
||||
var isIrregularAcronym = function isIrregularAcronym(word) {
|
||||
return IRREGULAR_ACRONYM.test(word.charAt(0));
|
||||
};
|
||||
|
||||
/**
|
||||
* Both = a && b
|
||||
* Neither = !a && !b
|
||||
* In the case of Booleans, this means
|
||||
* either both true or both false, so
|
||||
* we can just compare the equality of
|
||||
* a and b.
|
||||
*/
|
||||
var bothOrNeither = function bothOrNeither(a, b) {
|
||||
return a === b;
|
||||
};
|
||||
|
||||
/**
|
||||
* If the entirety of the first word is capital letters
|
||||
* and case insensitivity is off, it's an acronym.
|
||||
*/
|
||||
exports.check = function (word, _ref) {
|
||||
var caseInsensitive = _ref.caseInsensitive;
|
||||
return caseInsensitive ? false : ACRONYM.test(word.split(' ')[0]);
|
||||
};
|
||||
exports.run = function (word) {
|
||||
var isIrregular = isIrregularAcronym(word);
|
||||
var initialVowel = startsWithVowel(word);
|
||||
/*
|
||||
* If it starts with U: "a"
|
||||
* If it starts with any other vowel: "an"
|
||||
* If it starts with F, H, L, M, N, R, S, or X: "an"
|
||||
* If it starts with any other consonant: "a"
|
||||
*/
|
||||
var article = bothOrNeither(initialVowel, isIrregular) ? 'a' : 'an';
|
||||
return article;
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 374:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
var NUMBERS = /^([0-9,]+)/;
|
||||
var EIGHT_ELEVEN_EIGHTEEN = /^(11|8|18)/;
|
||||
var ELEVEN_EIGHTEEN = /^(11|18)/;
|
||||
exports.check = function (word) {
|
||||
return NUMBERS.test(word);
|
||||
};
|
||||
exports.run = function (word, opts) {
|
||||
var number = word.toString().match(NUMBERS)[1].replace(/,/g, '');
|
||||
var article = 'a';
|
||||
if (EIGHT_ELEVEN_EIGHTEEN.test(number)) {
|
||||
var startsWith11Or18 = ELEVEN_EIGHTEEN.test(number);
|
||||
|
||||
// If the number starts with 11 or 18 and is of length 4,
|
||||
// the pronunciation is ambiguous so check opts.numbers to see
|
||||
// how to render it. Otherwise, if it starts with 11 or 18
|
||||
// and has 2, 5, 8, 11, etc. digits, use 'an.' Finally, if it
|
||||
// starts with an 8, use 'an.' For everything else, use 'a.'
|
||||
if (startsWith11Or18 && number.length === 4) {
|
||||
article = opts.numbers === 'colloquial' ? 'an' : 'a';
|
||||
} else if (startsWith11Or18 && (number.length - 2) % 3 === 0) {
|
||||
article = 'an';
|
||||
} else {
|
||||
article = number.startsWith('8') ? 'an' : 'a';
|
||||
}
|
||||
}
|
||||
return article;
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 202:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
var _require = __webpack_require__(769),
|
||||
startsWithVowel = _require.startsWithVowel;
|
||||
var irregulars = __webpack_require__(725);
|
||||
var EXTRAS = /[\s'-]/;
|
||||
var getFirst = function getFirst(word) {
|
||||
return word.split(EXTRAS)[0].toLowerCase();
|
||||
};
|
||||
var xor = function xor(a, b) {
|
||||
return (a || b) && !(a && b);
|
||||
};
|
||||
|
||||
/**
|
||||
* Try some variations on the word to determine whether it's irregular.
|
||||
* Specifically, try trimming s, then es, then ed because those are common
|
||||
* forms of plurals and past tense verbs (which can be used like adjectives).
|
||||
*/
|
||||
var checkForIrregulars = function checkForIrregulars(part) {
|
||||
return [null, 's', 'es', 'ed'].reduce(function (memo, ending) {
|
||||
return memo || irregulars.check(part, ending);
|
||||
}, false);
|
||||
};
|
||||
exports.check = function () {
|
||||
return true;
|
||||
};
|
||||
exports.run = function (word, opts) {
|
||||
// Only check the first word. Also, if it's hyphenated, only
|
||||
// check the first part. Finally, if it's possessive, ignore
|
||||
// the possessive part.
|
||||
var first = getFirst(word);
|
||||
var isIrregular = checkForIrregulars(first);
|
||||
|
||||
/**
|
||||
* If it starts with a vowel and isn't irregular: "an"
|
||||
* If it starts with a vowel and IS irregular: "a"
|
||||
* If it starts with a consonant and isn't irregular: "a"
|
||||
* If it starts with a consonant and IS irregular: "an"
|
||||
*/
|
||||
var article = xor(startsWithVowel(word), isIrregular) ? 'an' : 'a';
|
||||
return article;
|
||||
};
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ // This entry module is referenced by other modules so it can't be inlined
|
||||
/******/ var __webpack_exports__ = __webpack_require__(393);
|
||||
/******/
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
||||
1
node_modules/indefinite/dist/indefinite.min.js
generated
vendored
Normal file
1
node_modules/indefinite/dist/indefinite.min.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e,u){"object"==typeof exports&&"object"==typeof module?module.exports=u():"function"==typeof define&&define.amd?define([],u):"object"==typeof exports?exports.indefinite=u():e.indefinite=u()}(self,(()=>{return e={769:(e,u)=>{var t=/^[aeiouAEIOU]/;u.startsWithVowel=function(e){return t.test(e)},u.capitalize=function(e,u){return u.capitalize&&(e="".concat(e.charAt(0).toUpperCase()).concat(e.slice(1))),e}},393:(e,u,t)=>{var r=t(769).capitalize,n=t(725),i=t(803),o=function(e){var u,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return i.some((function(r){if(r.check(e,t))return u=r.run(e,t),!0})),a(u,t,e)},a=function(e,u,t){return e=r(e,u),u.articleOnly?e:"".concat(e," ").concat(t)};o.irregularWords=n.list,e.exports=o},725:(e,u)=>{u.check=function(e,t){if(t){var r=new RegExp("".concat(t,"$"));if((e=e.replace(r,"")).length<=1)return!1}return u.list.indexOf(e)>-1},u.list=["eunuch","eucalyptus","eugenics","eulogy","euphemism","euphony","euphoria","eureka","euro","european","euphemistic","euphonic","euphoric","euphemistically","euphonically","euphorically","heir","heiress","herb","homage","honesty","honor","honour","honoree","hour","honest","honorous","honorific","honorable","honourable","honestly","hourly","one","ouija","once","ubiquity","udometer","ufo","uke","ukelele","ululate","unicorn","unicycle","uniform","unify","union","unison","unit","unity","universe","university","upas","ural","uranium","urea","ureter","urethra","urine","urologist","urology","urus","usage","use","user","usual","usurp","usurper","usury","utensil","uterus","utility","utopia","utricle","uvarovite","uvea","uvula","utah","utahn","ubiquitous","ugandan","ukrainian","unanimous","unicameral","unified","unique","unisex","universal","urinal","urological","useful","useless","usurious","utilitarian","utopic","ubiquitously","unanimously","unicamerally","uniquely","universally","urologically","usefully","uselessly","usuriously","yttria","yggdrasil","ylem","yperite","ytterbia","ytterbium","yttrium","ytterbous","ytterbic","yttric","f","h","l","m","n","r","s","u","x"]},803:(e,u,t)=>{e.exports=[t(374),t(532),t(202)]},532:(e,u,t)=>{var r=t(769).startsWithVowel,n=/^[A-Z]+$/,i=/^[UFHLMNRSX]/;u.check=function(e,u){return!u.caseInsensitive&&n.test(e.split(" ")[0])},u.run=function(e){var u=function(e){return i.test(e.charAt(0))}(e),t=r(e);return t===u?"a":"an"}},374:(e,u)=>{var t=/^([0-9,]+)/,r=/^(11|8|18)/,n=/^(11|18)/;u.check=function(e){return t.test(e)},u.run=function(e,u){var i=e.toString().match(t)[1].replace(/,/g,""),o="a";if(r.test(i)){var a=n.test(i);o=a&&4===i.length?"colloquial"===u.numbers?"an":"a":a&&(i.length-2)%3==0||i.startsWith("8")?"an":"a"}return o}},202:(e,u,t)=>{var r=t(769).startsWithVowel,n=t(725),i=/[\s'-]/;u.check=function(){return!0},u.run=function(e,u){var t,o,a,s=function(e){return e.split(i)[0].toLowerCase()}(e),l=(t=s,[null,"s","es","ed"].reduce((function(e,u){return e||n.check(t,u)}),!1));return o=r(e),a=l,!o&&!a||o&&a?"a":"an"}}},u={},function t(r){var n=u[r];if(void 0!==n)return n.exports;var i=u[r]={exports:{}};return e[r](i,i.exports,t),i.exports}(393);var e,u}));
|
||||
6
node_modules/indefinite/gulp/clean.js
generated
vendored
Normal file
6
node_modules/indefinite/gulp/clean.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
const gulp = require('gulp');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
gulp.task('clean:coverage', done => rimraf('./coverage', done));
|
||||
gulp.task('clean:dist', done => rimraf('./dist', done));
|
||||
|
||||
14
node_modules/indefinite/gulp/codeclimate.js
generated
vendored
Normal file
14
node_modules/indefinite/gulp/codeclimate.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
const gulp = require('gulp');
|
||||
const codeclimate = require('gulp-codeclimate-reporter');
|
||||
|
||||
gulp.task('codeclimate', (done) => {
|
||||
if (process.version.indexOf('v8') > -1) {
|
||||
return gulp.src('coverage/lcov.info', { read: false })
|
||||
.pipe(codeclimate({
|
||||
token: process.env.CODECLIMATE_REPO_TOKEN
|
||||
}));
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
7
node_modules/indefinite/gulp/config.js
generated
vendored
Normal file
7
node_modules/indefinite/gulp/config.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
root: path.resolve(__dirname, '..') + path.sep,
|
||||
tests: ['test/**/*.js'],
|
||||
lib: ['lib/**/*.js']
|
||||
};
|
||||
16
node_modules/indefinite/gulp/karma.js
generated
vendored
Normal file
16
node_modules/indefinite/gulp/karma.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
const gulp = require('gulp');
|
||||
const Server = require('karma').Server;
|
||||
const path = require('path');
|
||||
|
||||
gulp.task('browser', (done) => {
|
||||
new Server({
|
||||
configFile: path.resolve(__dirname, '../karma.conf.js'),
|
||||
singleRun: true
|
||||
}, done).start();
|
||||
});
|
||||
|
||||
gulp.task('ci', (done) => {
|
||||
new Server({
|
||||
configFile: path.resolve(__dirname, '../karma.conf.js')
|
||||
}, done).start();
|
||||
});
|
||||
11
node_modules/indefinite/gulp/lint.js
generated
vendored
Normal file
11
node_modules/indefinite/gulp/lint.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
const gulp = require('gulp');
|
||||
const config = require('./config');
|
||||
const eslint = require('gulp-eslint');
|
||||
|
||||
gulp.task('lint', () => {
|
||||
return gulp.src(config.lib)
|
||||
.pipe(eslint(config.root + '.eslint.json'))
|
||||
.pipe(eslint.format('node_modules/eslint-codeframe-formatter'))
|
||||
.pipe(eslint.failAfterError());
|
||||
});
|
||||
|
||||
7
node_modules/indefinite/gulp/open.js
generated
vendored
Normal file
7
node_modules/indefinite/gulp/open.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
const gulp = require('gulp');
|
||||
const open = require('opn');
|
||||
|
||||
gulp.task('open', (done) => {
|
||||
open('coverage/lcov-report/index.html', { wait: false }).then(() => done(), done);
|
||||
});
|
||||
|
||||
11
node_modules/indefinite/gulp/spawn.js
generated
vendored
Normal file
11
node_modules/indefinite/gulp/spawn.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
const gulp = require('gulp');
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
const task = (cmd, args) => {
|
||||
return (done) => {
|
||||
spawn(cmd, args, { stdio: 'inherit' }).on('close', () => done());
|
||||
};
|
||||
};
|
||||
|
||||
gulp.task('spawn:nyc', task('npm', [ 'run', 'cover' ]));
|
||||
gulp.task('spawn:webpack', task('npm', [ 'run', 'build' ]));
|
||||
6
node_modules/indefinite/gulp/watch.js
generated
vendored
Normal file
6
node_modules/indefinite/gulp/watch.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
const gulp = require('gulp');
|
||||
const config = require('./config');
|
||||
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch(config.lib.concat(config.tests), gulp.series('cover'));
|
||||
});
|
||||
9
node_modules/indefinite/gulpfile.js
generated
vendored
Normal file
9
node_modules/indefinite/gulpfile.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
const gulp = require('gulp');
|
||||
require('file-manifest').generate('./gulp', { match: '*.js' });
|
||||
|
||||
gulp.task('build', gulp.series('clean:dist', 'spawn:webpack'));
|
||||
gulp.task('cover', gulp.series('clean:coverage', 'spawn:nyc'));
|
||||
gulp.task('ci', gulp.series(gulp.parallel('lint', 'cover'), 'codeclimate'));
|
||||
gulp.task('test', gulp.series('cover', 'browser', 'build'));
|
||||
gulp.task('unit', gulp.series('spawn:nyc'));
|
||||
gulp.task('default', gulp.series('lint', 'test'));
|
||||
37
node_modules/indefinite/karma.conf.js
generated
vendored
Normal file
37
node_modules/indefinite/karma.conf.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// Karma configuration
|
||||
// Generated on Fri Oct 23 2015 14:00:27 GMT-0400 (EDT)
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['mocha'],
|
||||
reporters: ['dots'],
|
||||
browsers: [ 'Chrome' ],
|
||||
preprocessors: {
|
||||
'test/**/*.js': ['webpack']
|
||||
},
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'node_modules/babel-polyfill/dist/polyfill.js',
|
||||
'test/**/*.js'
|
||||
],
|
||||
|
||||
webpack: {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
logLevel: config.LOG_ERROR
|
||||
});
|
||||
};
|
||||
16
node_modules/indefinite/lib/helpers.js
generated
vendored
Normal file
16
node_modules/indefinite/lib/helpers.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
const STARTS_WITH_VOWEL = /^[aeiouAEIOU]/;
|
||||
|
||||
/**
|
||||
* Array#indexOf is faster IF the word starts with "a" (for example),
|
||||
* but negligibly faster when you have to .toLowerCase() the word, and
|
||||
* slower if the word happens to start with (e.g.) "u."
|
||||
*/
|
||||
exports.startsWithVowel = word => STARTS_WITH_VOWEL.test(word);
|
||||
|
||||
exports.capitalize = (article, opts) => {
|
||||
if (opts.capitalize) {
|
||||
article = `${article.charAt(0).toUpperCase()}${article.slice(1)}`;
|
||||
}
|
||||
|
||||
return article;
|
||||
};
|
||||
34
node_modules/indefinite/lib/indefinite.js
generated
vendored
Normal file
34
node_modules/indefinite/lib/indefinite.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
const { capitalize } = require('./helpers');
|
||||
const irregulars = require('./irregular-words');
|
||||
const rules = require('./rules');
|
||||
|
||||
const indefinite = (word, opts = {}) => {
|
||||
let article;
|
||||
|
||||
/**
|
||||
* I'd really prefer to use for of here, but babel converts that
|
||||
* to something using Symbol.iterator, which PhantomJS chokes on.
|
||||
*/
|
||||
rules.some((rule) => {
|
||||
if (rule.check(word, opts)) {
|
||||
article = rule.run(word, opts);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return handleOptions(article, opts, word);
|
||||
};
|
||||
|
||||
const handleOptions = (article, opts, word) => {
|
||||
article = capitalize(article, opts);
|
||||
|
||||
if (opts.articleOnly) {
|
||||
return article;
|
||||
}
|
||||
|
||||
return `${article} ${word}`;
|
||||
};
|
||||
|
||||
indefinite.irregularWords = irregulars.list;
|
||||
|
||||
module.exports = indefinite;
|
||||
83
node_modules/indefinite/lib/irregular-words.js
generated
vendored
Normal file
83
node_modules/indefinite/lib/irregular-words.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
exports.check = (word, ending) => {
|
||||
if (ending) {
|
||||
// If the word ends in the ending, remove it.
|
||||
let regex = new RegExp(`${ending}$`);
|
||||
word = word.replace(regex, '');
|
||||
|
||||
if (word.length <= 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return exports.list.indexOf(word) > -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Here follows a List of words that take irregular articles because their
|
||||
* first letter is either a consonant pronounced like a vowel (hour) or a
|
||||
* vowel proncounced like a consonant (ukelele). Note that this is not only
|
||||
* nouns because adjectives and adverbs that start with these letters could
|
||||
* also follow an article when they identify a later noun, as in "a useless
|
||||
* tool."
|
||||
*
|
||||
* This is not an attempt at a complete list, but rather a collection of
|
||||
* words used in at least moderate frequency. A list of ALL irregular words
|
||||
* would be too exhaustive to compile without some sort of tool.
|
||||
* http://www.thefreedictionary.com/words-that-start-with-eu says there are
|
||||
* over 1800 words starting with "eu" alone.
|
||||
*
|
||||
* At least for now, this list omits proper names, as they aren't USUALLY
|
||||
* used in such a way as to require an _indefinite_ article. I can't think,
|
||||
* for example, of a case where you'd want to say "a Eustace."
|
||||
*/
|
||||
exports.list = [
|
||||
// Nouns: eu like y
|
||||
'eunuch', 'eucalyptus', 'eugenics', 'eulogy', 'euphemism', 'euphony', 'euphoria', 'eureka',
|
||||
|
||||
// Adjectives: eu like y
|
||||
'euro', 'european', 'euphemistic', 'euphonic', 'euphoric',
|
||||
|
||||
// Adverbs: eu like y
|
||||
'euphemistically', 'euphonically', 'euphorically',
|
||||
|
||||
// Nouns: silent h
|
||||
'heir', 'heiress', 'herb', 'homage', 'honesty', 'honor', 'honour', 'honoree', 'hour',
|
||||
|
||||
// Adjectives: silent h
|
||||
'honest', 'honorous', 'honorific', 'honorable', 'honourable',
|
||||
|
||||
// Adverbs: silent h
|
||||
'honestly', 'hourly',
|
||||
|
||||
// Nouns: o like w
|
||||
'one', 'ouija',
|
||||
|
||||
// Adjectives: o like w
|
||||
'once',
|
||||
|
||||
// Adverbs: o like w
|
||||
|
||||
// Nouns: u like y
|
||||
'ubiquity', 'udometer', 'ufo', 'uke', 'ukelele', 'ululate', 'unicorn', 'unicycle', 'uniform',
|
||||
'unify', 'union', 'unison', 'unit', 'unity', 'universe', 'university', 'upas', 'ural', 'uranium',
|
||||
'urea', 'ureter', 'urethra', 'urine', 'urologist', 'urology', 'urus', 'usage', 'use', 'user', 'usual', 'usurp',
|
||||
'usurper', 'usury', 'utensil', 'uterus', 'utility', 'utopia', 'utricle', 'uvarovite', 'uvea', 'uvula', 'utah',
|
||||
'utahn',
|
||||
|
||||
// Adjectives: u like y
|
||||
'ubiquitous', 'ugandan', 'ukrainian', 'unanimous', 'unicameral', 'unified', 'unique', 'unisex',
|
||||
'universal', 'urinal', 'urological', 'useful', 'useless', 'usurious', 'utilitarian',
|
||||
'utopic',
|
||||
|
||||
// Adverbs: u like y
|
||||
'ubiquitously', 'unanimously', 'unicamerally', 'uniquely', 'universally', 'urologically', 'usefully', 'uselessly', 'usuriously',
|
||||
|
||||
// Nouns: y like i
|
||||
'yttria', 'yggdrasil', 'ylem', 'yperite', 'ytterbia', 'ytterbium', 'yttrium',
|
||||
|
||||
// Adjectives: y like i
|
||||
'ytterbous', 'ytterbic', 'yttric',
|
||||
|
||||
// Single letters
|
||||
'f', 'h', 'l', 'm', 'n', 'r', 's', 'u', 'x'
|
||||
];
|
||||
5
node_modules/indefinite/lib/rules.js
generated
vendored
Normal file
5
node_modules/indefinite/lib/rules.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = [
|
||||
require('./rules/numbers'),
|
||||
require('./rules/acronyms'),
|
||||
require('./rules/other')
|
||||
];
|
||||
35
node_modules/indefinite/lib/rules/acronyms.js
generated
vendored
Normal file
35
node_modules/indefinite/lib/rules/acronyms.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
const { startsWithVowel } = require('../helpers');
|
||||
const ACRONYM = /^[A-Z]+$/;
|
||||
const IRREGULAR_ACRONYM = /^[UFHLMNRSX]/;
|
||||
|
||||
const isIrregularAcronym = word => IRREGULAR_ACRONYM.test(word.charAt(0));
|
||||
|
||||
/**
|
||||
* Both = a && b
|
||||
* Neither = !a && !b
|
||||
* In the case of Booleans, this means
|
||||
* either both true or both false, so
|
||||
* we can just compare the equality of
|
||||
* a and b.
|
||||
*/
|
||||
const bothOrNeither = (a, b) => a === b;
|
||||
|
||||
/**
|
||||
* If the entirety of the first word is capital letters
|
||||
* and case insensitivity is off, it's an acronym.
|
||||
*/
|
||||
exports.check = (word, { caseInsensitive }) => caseInsensitive ? false : ACRONYM.test(word.split(' ')[0]);
|
||||
|
||||
exports.run = (word) => {
|
||||
let isIrregular = isIrregularAcronym(word);
|
||||
let initialVowel = startsWithVowel(word);
|
||||
/*
|
||||
* If it starts with U: "a"
|
||||
* If it starts with any other vowel: "an"
|
||||
* If it starts with F, H, L, M, N, R, S, or X: "an"
|
||||
* If it starts with any other consonant: "a"
|
||||
*/
|
||||
let article = bothOrNeither(initialVowel, isIrregular) ? 'a' : 'an';
|
||||
return article;
|
||||
};
|
||||
|
||||
29
node_modules/indefinite/lib/rules/numbers.js
generated
vendored
Normal file
29
node_modules/indefinite/lib/rules/numbers.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
const NUMBERS = /^([0-9,]+)/;
|
||||
const EIGHT_ELEVEN_EIGHTEEN = /^(11|8|18)/;
|
||||
const ELEVEN_EIGHTEEN = /^(11|18)/;
|
||||
|
||||
exports.check = (word) => NUMBERS.test(word);
|
||||
|
||||
exports.run = (word, opts) => {
|
||||
let number = word.toString().match(NUMBERS)[1].replace(/,/g, '');
|
||||
let article = 'a';
|
||||
|
||||
if (EIGHT_ELEVEN_EIGHTEEN.test(number)) {
|
||||
const startsWith11Or18 = ELEVEN_EIGHTEEN.test(number);
|
||||
|
||||
// If the number starts with 11 or 18 and is of length 4,
|
||||
// the pronunciation is ambiguous so check opts.numbers to see
|
||||
// how to render it. Otherwise, if it starts with 11 or 18
|
||||
// and has 2, 5, 8, 11, etc. digits, use 'an.' Finally, if it
|
||||
// starts with an 8, use 'an.' For everything else, use 'a.'
|
||||
if (startsWith11Or18 && number.length === 4) {
|
||||
article = opts.numbers === 'colloquial' ? 'an' : 'a';
|
||||
} else if (startsWith11Or18 && (number.length - 2) % 3 === 0) {
|
||||
article = 'an';
|
||||
} else {
|
||||
article = number.startsWith('8') ? 'an' : 'a';
|
||||
}
|
||||
}
|
||||
|
||||
return article;
|
||||
};
|
||||
33
node_modules/indefinite/lib/rules/other.js
generated
vendored
Normal file
33
node_modules/indefinite/lib/rules/other.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
const { startsWithVowel } = require('../helpers');
|
||||
const irregulars = require('../irregular-words');
|
||||
const EXTRAS = /[\s'-]/;
|
||||
|
||||
const getFirst = word => word.split(EXTRAS)[0].toLowerCase();
|
||||
|
||||
const xor = (a, b) => (a || b) && !(a && b);
|
||||
|
||||
/**
|
||||
* Try some variations on the word to determine whether it's irregular.
|
||||
* Specifically, try trimming s, then es, then ed because those are common
|
||||
* forms of plurals and past tense verbs (which can be used like adjectives).
|
||||
*/
|
||||
const checkForIrregulars = part => [ null, 's', 'es', 'ed' ].reduce((memo, ending) => memo || irregulars.check(part, ending), false);
|
||||
|
||||
exports.check = () => true;
|
||||
|
||||
exports.run = (word, opts) => {
|
||||
// Only check the first word. Also, if it's hyphenated, only
|
||||
// check the first part. Finally, if it's possessive, ignore
|
||||
// the possessive part.
|
||||
let first = getFirst(word);
|
||||
let isIrregular = checkForIrregulars(first);
|
||||
|
||||
/**
|
||||
* If it starts with a vowel and isn't irregular: "an"
|
||||
* If it starts with a vowel and IS irregular: "a"
|
||||
* If it starts with a consonant and isn't irregular: "a"
|
||||
* If it starts with a consonant and IS irregular: "an"
|
||||
*/
|
||||
let article = xor(startsWithVowel(word), isIrregular) ? 'an' : 'a';
|
||||
return article;
|
||||
};
|
||||
63
node_modules/indefinite/package.json
generated
vendored
Normal file
63
node_modules/indefinite/package.json
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "indefinite",
|
||||
"description": "Prefix a noun with an indefinite article - a or an - based on whether it begins with a vowel",
|
||||
"version": "2.5.2",
|
||||
"main": "lib/indefinite.js",
|
||||
"browser": "dist/indefinite.js",
|
||||
"scripts": {
|
||||
"test": "NODE_OPTIONS=--openssl-legacy-provider gulp",
|
||||
"travis": "gulp ci",
|
||||
"build": "webpack --mode production",
|
||||
"cover": "nyc --reporter=html --reporter=lcov --reporter=text-summary mocha --timeout=3000 --reporter=dot test/**/*.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/tandrewnichols/indefinite.git"
|
||||
},
|
||||
"keywords": [
|
||||
"article",
|
||||
"a",
|
||||
"an",
|
||||
"grammar",
|
||||
"noun"
|
||||
],
|
||||
"author": {
|
||||
"name": "Andrew Nichols",
|
||||
"email": "tandrewnichols@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/tandrewnichols/indefinite/issues"
|
||||
},
|
||||
"homepage": "https://github.com/tandrewnichols/indefinite",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.6",
|
||||
"@babel/preset-env": "^7.11.5",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"eslint-codeframe-formatter": "^1.0.2",
|
||||
"file-manifest": "^2.0.5",
|
||||
"gulp": "^5.0.0",
|
||||
"gulp-cli": "^3.0.0",
|
||||
"gulp-codeclimate-reporter": "github:tandrewnichols/gulp-codeclimate-reporter",
|
||||
"gulp-eslint": "^6.0.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"karma": "^6.3.14",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
"karma-firefox-launcher": "^1.3.0",
|
||||
"karma-mocha": "^2.0.1",
|
||||
"karma-safari-launcher": "^1.0.0",
|
||||
"karma-webpack": "^5.0.0",
|
||||
"mocha": "^10.1.0",
|
||||
"nyc": "^15.1.0",
|
||||
"opn": "^6.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"should": "^13.2.3",
|
||||
"terser-webpack-plugin": "^5.3.11",
|
||||
"webpack": "^5.90.3",
|
||||
"webpack-cli": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
}
|
||||
280
node_modules/indefinite/test/indefinite.js
generated
vendored
Normal file
280
node_modules/indefinite/test/indefinite.js
generated
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
require('should');
|
||||
|
||||
describe('indefinite', () => {
|
||||
const indefinite = require('../lib/indefinite');
|
||||
|
||||
context('a word that starts with a vowel', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('apple').should.equal('an apple');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a consonant', () => {
|
||||
it('should be prefixed with a', () => {
|
||||
indefinite('banana').should.equal('a banana');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a capital vowel', () => {
|
||||
it('should be maintain capitalization', () => {
|
||||
indefinite('Apple').should.equal('an Apple');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a capital consonant', () => {
|
||||
it('should maintain capitalization', () => {
|
||||
indefinite('Banana').should.equal('a Banana');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a capital that would be a irregular if it were an acronym', () => {
|
||||
it('should be prefixed with the regular article', () => {
|
||||
indefinite('Umbrella').should.equal('an Umbrella');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a vowel when capitalize is passed in', () => {
|
||||
it('should capitalize the article', () => {
|
||||
indefinite('apple', { capitalize: true }).should.equal('An apple');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a consonant when capitalize is passed in', () => {
|
||||
it('should capitalize the article', () => {
|
||||
indefinite('banana', { capitalize: true }).should.equal('A banana');
|
||||
});
|
||||
});
|
||||
|
||||
context('an acronym that starts with a regular vowel', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('IOU').should.equal('an IOU');
|
||||
});
|
||||
});
|
||||
|
||||
context('an acronym that starts with an irregular vowel', () => {
|
||||
it('should be prefixed with a', () => {
|
||||
indefinite('UFO').should.equal('a UFO');
|
||||
});
|
||||
});
|
||||
|
||||
context('an acronym that starts with a consonant', () => {
|
||||
it('should still be prefixed with a', () => {
|
||||
indefinite('CEO').should.equal('a CEO');
|
||||
});
|
||||
});
|
||||
|
||||
context('an acronym that starts with an irregular consonant', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('FFA prodigy').should.equal('an FFA prodigy');
|
||||
});
|
||||
});
|
||||
|
||||
context('an acronym that starts with U but with caseInsensitive passed in', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('UNCLE', { caseInsensitive: true }).should.equal('an UNCLE');
|
||||
});
|
||||
});
|
||||
|
||||
context('an irregular word beginning with a silent consonant', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('honor').should.equal('an honor');
|
||||
});
|
||||
});
|
||||
|
||||
context('an irregular word beginning with eu that makes a y- sound', () => {
|
||||
it('should be prefixed with a', () => {
|
||||
indefinite('euro').should.equal('a euro');
|
||||
});
|
||||
});
|
||||
|
||||
context('an irregular word beginning with a vowel that makes a consonant sound', () => {
|
||||
it('should be prefixed with a', () => {
|
||||
indefinite('ukelele').should.equal('a ukelele');
|
||||
});
|
||||
});
|
||||
|
||||
context('an irregular word when multiple words are passed in', () => {
|
||||
it('should be prefixed based on the first word only', () => {
|
||||
indefinite('ouija board').should.equal('a ouija board');
|
||||
});
|
||||
});
|
||||
|
||||
context('an irregular word that is hyphenated is passed in', () => {
|
||||
it('should be prefixed based on the first part of the word only', () => {
|
||||
indefinite('honor-bound').should.equal('an honor-bound');
|
||||
});
|
||||
});
|
||||
|
||||
context('a plural form of an irregular word is passed in', () => {
|
||||
it('should be prefixed based on the singular form', () => {
|
||||
indefinite('hours').should.equal('an hours');
|
||||
});
|
||||
});
|
||||
|
||||
context('an irregular plural form of an irregular word is passed in', () => {
|
||||
it('should be prefixed based on the singular form', () => {
|
||||
indefinite('heiresses').should.equal('an heiresses');
|
||||
});
|
||||
});
|
||||
|
||||
context('a past tense verb form of an irregular word is passed in', () => {
|
||||
it('should be prefixed based on the present tense', () => {
|
||||
indefinite('honored').should.equal('an honored');
|
||||
});
|
||||
});
|
||||
|
||||
context('a possessive form of an irregular word is passed in', () => {
|
||||
it('should be prefixed based on the non-possessive form', () => {
|
||||
indefinite('heir\'s').should.equal('an heir\'s');
|
||||
});
|
||||
});
|
||||
|
||||
context('a regular word that happens to have an ending we strip (s, es, ed)', () => {
|
||||
it('should ignore the ending', () => {
|
||||
indefinite('red rum').should.equal('a red rum');
|
||||
});
|
||||
});
|
||||
|
||||
context('an irregular word with some capitalization is passed', () => {
|
||||
it('should be treated case-insensitively', () => {
|
||||
indefinite('Hour').should.equal('an Hour');
|
||||
});
|
||||
});
|
||||
|
||||
context('articleOnly', () => {
|
||||
context('a word that starts with a vowel', () => {
|
||||
it('should return the article only', () => {
|
||||
indefinite('apple', { articleOnly: true }).should.equal('an');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a consonant', () => {
|
||||
it('should return the article only', () => {
|
||||
indefinite('pear', { articleOnly: true }).should.equal('a');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a vowel when capitalize is passed in', () => {
|
||||
it('should capitalize the article', () => {
|
||||
indefinite('apple', { articleOnly: true, capitalize: true }).should.equal('An');
|
||||
});
|
||||
});
|
||||
|
||||
context('a word that starts with a consonant when capitalize is passed in', () => {
|
||||
it('should capitalize the article', () => {
|
||||
indefinite('pear', { articleOnly: true, capitalize: true }).should.equal('A');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Numbers', () => {
|
||||
context('starting with 11', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('11').should.equal('an 11');
|
||||
indefinite('110').should.equal('a 110');
|
||||
indefinite('11000').should.equal('an 11000');
|
||||
indefinite('110000').should.equal('a 110000');
|
||||
indefinite('1100000').should.equal('a 1100000');
|
||||
indefinite('11000000').should.equal('an 11000000');
|
||||
indefinite('110000000').should.equal('a 110000000');
|
||||
indefinite('1100000000').should.equal('a 1100000000');
|
||||
indefinite('11000000000').should.equal('an 11000000000');
|
||||
indefinite('110000000000').should.equal('a 110000000000');
|
||||
indefinite('1100000000000').should.equal('a 1100000000000');
|
||||
indefinite('11000000000000').should.equal('an 11000000000000');
|
||||
indefinite('110000000000000').should.equal('a 110000000000000');
|
||||
indefinite('1100000000000000').should.equal('a 1100000000000000');
|
||||
indefinite('11000000000000000').should.equal('an 11000000000000000');
|
||||
});
|
||||
});
|
||||
|
||||
context('starting with 18', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('18').should.equal('an 18');
|
||||
indefinite('180').should.equal('a 180');
|
||||
indefinite('18000').should.equal('an 18000');
|
||||
indefinite('180000').should.equal('a 180000');
|
||||
indefinite('1800000').should.equal('a 1800000');
|
||||
indefinite('18000000').should.equal('an 18000000');
|
||||
indefinite('180000000').should.equal('a 180000000');
|
||||
indefinite('1800000000').should.equal('a 1800000000');
|
||||
indefinite('18000000000').should.equal('an 18000000000');
|
||||
indefinite('180000000000').should.equal('a 180000000000');
|
||||
indefinite('1800000000000').should.equal('a 1800000000000');
|
||||
indefinite('18000000000000').should.equal('an 18000000000000');
|
||||
indefinite('180000000000000').should.equal('a 180000000000000');
|
||||
indefinite('1800000000000000').should.equal('a 1800000000000000');
|
||||
indefinite('18000000000000000').should.equal('an 18000000000000000');
|
||||
});
|
||||
});
|
||||
|
||||
context('starting with 8', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('8').should.equal('an 8');
|
||||
indefinite('80').should.equal('an 80');
|
||||
indefinite('800').should.equal('an 800');
|
||||
indefinite('8000').should.equal('an 8000');
|
||||
indefinite('80000').should.equal('an 80000');
|
||||
indefinite('800000').should.equal('an 800000');
|
||||
indefinite('8000000').should.equal('an 8000000');
|
||||
indefinite('80000000').should.equal('an 80000000');
|
||||
indefinite('800000000').should.equal('an 800000000');
|
||||
});
|
||||
});
|
||||
|
||||
context('1100 and 1800 range', () => {
|
||||
context('with formal pronunciation', () => {
|
||||
it('should be prefixed with a', () => {
|
||||
indefinite('1100').should.equal('a 1100');
|
||||
indefinite('1800').should.equal('a 1800');
|
||||
});
|
||||
});
|
||||
|
||||
context('with colloquial pronunciation', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('1100', { numbers: 'colloquial' }).should.equal('an 1100');
|
||||
indefinite('1800', { numbers: 'colloquial' }).should.equal('an 1800');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('other numbers', () => {
|
||||
it('should be prefixed with a', () => {
|
||||
indefinite('17').should.equal('a 17');
|
||||
});
|
||||
});
|
||||
|
||||
context('with actual numbers', () => {
|
||||
it('should be prefixed the same as with strings', () => {
|
||||
indefinite(7).should.equal('a 7');
|
||||
indefinite(8).should.equal('an 8');
|
||||
});
|
||||
});
|
||||
|
||||
context('the letter u', () => {
|
||||
it('should be prefixed with a', () => {
|
||||
indefinite('u').should.equal('a u')
|
||||
});
|
||||
});
|
||||
|
||||
context('the letters f, h, l, m, n, r, s, and x', () => {
|
||||
it('should be prefixed with an', () => {
|
||||
indefinite('f').should.equal('an f')
|
||||
indefinite('h').should.equal('an h')
|
||||
indefinite('l').should.equal('an l')
|
||||
indefinite('m').should.equal('an m')
|
||||
indefinite('n').should.equal('an n')
|
||||
indefinite('r').should.equal('an r')
|
||||
indefinite('s').should.equal('an s')
|
||||
indefinite('x').should.equal('an x')
|
||||
});
|
||||
});
|
||||
|
||||
context('other letters', () => {
|
||||
it('should be prefixed as normal', () => {
|
||||
indefinite('a').should.equal('an a');
|
||||
indefinite('b').should.equal('a b');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
35
node_modules/indefinite/webpack.config.js
generated
vendored
Normal file
35
node_modules/indefinite/webpack.config.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
const webpack = require('webpack');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const package = require('./package');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
'indefinite': require.resolve(`./${package.main}`),
|
||||
'indefinite.min': require.resolve(`./${package.main}`)
|
||||
},
|
||||
output: {
|
||||
library: 'indefinite',
|
||||
libraryTarget: 'umd',
|
||||
path: `${__dirname}/dist`,
|
||||
filename: '[name].js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /lib.*\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
test: /\.min\.js$/
|
||||
})
|
||||
]
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user