indefinite
Advanced tools
Comparing version 2.0.1 to 2.0.2
@@ -71,3 +71,13 @@ window["indefinite"] = | ||
module.exports = function (noun) { | ||
var checkList = function checkList(word, ending) { | ||
if (ending) { | ||
// If the word ends in the ending, remove it. | ||
var regex = new RegExp(ending + '$'); | ||
word = word.replace(regex, ''); | ||
} | ||
return indefinite.irregularWords.indexOf(word) > -1; | ||
}; | ||
var indefinite = function indefinite(noun) { | ||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
@@ -77,12 +87,94 @@ | ||
var startsWithVowel = /[aeiou]/.test(noun.charAt(0).toLowerCase()); | ||
var article = !isAcronymWithU && startsWithVowel ? 'an ' : 'a '; | ||
var phrase = article + noun; | ||
// 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 part = noun.split(/[\s'-]/)[0].toLowerCase(); | ||
// 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 isIrregular = [null, 's', 'es', 'ed'].reduce(function (memo, ending) { | ||
return memo || checkList(part, ending); | ||
}, false); | ||
/** | ||
* If it's an acronym that starts with "u," the article should be "a" | ||
* If it starts with a vowel and isn't irregular, it should be "an" | ||
* If it starts with a vowel and IS irregular, it should be "a" | ||
* If it starts with a consonant and isn't irregular, it should be "a" | ||
* If it starts with a consonant and IS irregular, it should be "an" | ||
*/ | ||
var article = !isAcronymWithU && (startsWithVowel || isIrregular) && !(startsWithVowel && isIrregular) ? 'an' : 'a'; | ||
if (opts.capitalize) { | ||
return phrase.charAt(0).toUpperCase() + phrase.slice(1); | ||
} else { | ||
return phrase; | ||
article = '' + article.charAt(0).toUpperCase() + article.slice(1); | ||
} | ||
return article + ' ' + noun; | ||
}; | ||
/** | ||
* 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." | ||
*/ | ||
indefinite.irregularWords = [ | ||
// Nouns: eu like y | ||
'eunuch', 'eucalyptus', 'eugenics', 'eulogy', 'euphemism', 'euphony', 'euphoria', 'eureka', | ||
// Adjectives: eu like y | ||
'european', 'euphemistic', 'euphonic', 'euphoric', | ||
// Adverbs: eu like y | ||
'euphemistically', 'euphonically', 'euphorically', | ||
// Nouns: silent h | ||
'herb', 'hour', 'heir', 'heiress', 'honesty', 'honor', 'honour', | ||
// Adjectives: silent h | ||
'honest', 'honorous', | ||
// Adverbs: silent h | ||
'hourly', 'honestly', | ||
// 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', 'urology', 'urus', 'usage', 'use', 'usual', 'usurp', 'usury', 'utensil', 'uterus', 'utility', 'utopia', 'utricle', 'uvarovite', 'uvea', 'uvula', | ||
// Adjectives: u like y | ||
'ubiquitous', 'ugandan', 'ukrainian', 'unanimous', 'unicameral', 'unified', 'unique', 'unisex', 'universal', 'urinal', 'urological', 'useful', 'useless', 'usurious', 'usurped', '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']; | ||
module.exports = indefinite; | ||
/***/ }) | ||
/******/ ]); |
@@ -1,1 +0,1 @@ | ||
window.indefinite=function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t){e.exports=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=!t.caseInsensitive&&/^U[A-Z]+$/.test(e.split(" ")[0]),r=/[aeiou]/.test(e.charAt(0).toLowerCase()),o=!n&&r?"an ":"a ",i=o+e;return t.capitalize?i.charAt(0).toUpperCase()+i.slice(1):i}}]); | ||
window.indefinite=function(u){function e(i){if(r[i])return r[i].exports;var n=r[i]={i:i,l:!1,exports:{}};return u[i].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var r={};return e.m=u,e.c=r,e.d=function(u,r,i){e.o(u,r)||Object.defineProperty(u,r,{configurable:!1,enumerable:!0,get:i})},e.n=function(u){var r=u&&u.__esModule?function(){return u.default}:function(){return u};return e.d(r,"a",r),r},e.o=function(u,e){return Object.prototype.hasOwnProperty.call(u,e)},e.p="",e(e.s=0)}([function(u,e){var r=function(u,e){if(e){var r=new RegExp(e+"$");u=u.replace(r,"")}return i.irregularWords.indexOf(u)>-1},i=function(u){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=!e.caseInsensitive&&/^U[A-Z]+$/.test(u.split(" ")[0]),n=/[aeiou]/.test(u.charAt(0).toLowerCase()),t=u.split(/[\s'-]/)[0].toLowerCase(),o=[null,"s","es","ed"].reduce(function(u,e){return u||r(t,e)},!1),s=i||!n&&!o||n&&o?"a":"an";return e.capitalize&&(s=""+s.charAt(0).toUpperCase()+s.slice(1)),s+" "+u};i.irregularWords=["eunuch","eucalyptus","eugenics","eulogy","euphemism","euphony","euphoria","eureka","european","euphemistic","euphonic","euphoric","euphemistically","euphonically","euphorically","herb","hour","heir","heiress","honesty","honor","honour","honest","honorous","hourly","honestly","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","urology","urus","usage","use","usual","usurp","usury","utensil","uterus","utility","utopia","utricle","uvarovite","uvea","uvula","ubiquitous","ugandan","ukrainian","unanimous","unicameral","unified","unique","unisex","universal","urinal","urological","useful","useless","usurious","usurped","utilitarian","utopic","ubiquitously","unanimously","unicamerally","uniquely","universally","urologically","usefully","uselessly","usuriously","yttria","yggdrasil","ylem","yperite","ytterbia","ytterbium","yttrium","ytterbous","ytterbic","yttric"],u.exports=i}]); |
const gulp = require('gulp'); | ||
const open = require('gulp-open'); | ||
const open = require('opn'); | ||
gulp.task('open', () => { | ||
return gulp.src('./coverage/lcov-report/index.html', { read: false }) | ||
.pipe(open()); | ||
gulp.task('open', (done) => { | ||
open('coverage/lcov-report/index.html', { wait: false }).then(() => done(), done); | ||
}); | ||
@@ -1,11 +0,109 @@ | ||
module.exports = (noun, opts = {}) => { | ||
const checkList = (word, ending) => { | ||
if (ending) { | ||
// If the word ends in the ending, remove it. | ||
let regex = new RegExp(`${ending}$`); | ||
word = word.replace(regex, ''); | ||
} | ||
return indefinite.irregularWords.indexOf(word) > -1; | ||
}; | ||
const indefinite = (noun, opts = {}) => { | ||
let isAcronymWithU = opts.caseInsensitive ? false : /^U[A-Z]+$/.test(noun.split(' ')[0]); | ||
let startsWithVowel = /[aeiou]/.test(noun.charAt(0).toLowerCase()); | ||
let article = !isAcronymWithU && startsWithVowel ? 'an ' : 'a '; | ||
let phrase = article + noun; | ||
// 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 part = noun.split(/[\s'-]/)[0].toLowerCase(); | ||
// 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). | ||
let isIrregular = [ null, 's', 'es', 'ed' ].reduce((memo, ending) => { | ||
return memo || checkList(part, ending); | ||
}, false); | ||
/** | ||
* If it's an acronym that starts with "u," the article should be "a" | ||
* If it starts with a vowel and isn't irregular, it should be "an" | ||
* If it starts with a vowel and IS irregular, it should be "a" | ||
* If it starts with a consonant and isn't irregular, it should be "a" | ||
* If it starts with a consonant and IS irregular, it should be "an" | ||
*/ | ||
let article = (!isAcronymWithU && (startsWithVowel || isIrregular) && !(startsWithVowel && isIrregular)) ? 'an' : 'a'; | ||
if (opts.capitalize) { | ||
return phrase.charAt(0).toUpperCase() + phrase.slice(1); | ||
} else { | ||
return phrase; | ||
article = `${article.charAt(0).toUpperCase()}${article.slice(1)}`; | ||
} | ||
return `${article} ${noun}`; | ||
}; | ||
/** | ||
* 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." | ||
*/ | ||
indefinite.irregularWords = [ | ||
// Nouns: eu like y | ||
'eunuch', 'eucalyptus', 'eugenics', 'eulogy', 'euphemism', 'euphony', 'euphoria', 'eureka', | ||
// Adjectives: eu like y | ||
'european', 'euphemistic', 'euphonic', 'euphoric', | ||
// Adverbs: eu like y | ||
'euphemistically', 'euphonically', 'euphorically', | ||
// Nouns: silent h | ||
'herb', 'hour', 'heir', 'heiress', 'honesty', 'honor', 'honour', | ||
// Adjectives: silent h | ||
'honest', 'honorous', | ||
// Adverbs: silent h | ||
'hourly', 'honestly', | ||
// 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', 'urology', 'urus', 'usage', 'use', 'usual', 'usurp', | ||
'usury', 'utensil', 'uterus', 'utility', 'utopia', 'utricle', 'uvarovite', 'uvea', 'uvula', | ||
// Adjectives: u like y | ||
'ubiquitous', 'ugandan', 'ukrainian', 'unanimous', 'unicameral', 'unified', 'unique', 'unisex', | ||
'universal', 'urinal', 'urological', 'useful', 'useless', 'usurious', 'usurped', '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' | ||
]; | ||
module.exports = indefinite; |
{ | ||
"name": "indefinite", | ||
"description": "Prefix a noun with an indefinite article - a or an - based on whether it begins with a vowel", | ||
"version": "2.0.1", | ||
"version": "2.0.2", | ||
"main": "lib/indefinite.js", | ||
@@ -42,3 +42,2 @@ "scripts": { | ||
"gulp-eslint": "^4.0.0", | ||
"gulp-open": "^2.0.0", | ||
"gulp-rename": "^1.2.2", | ||
@@ -52,2 +51,3 @@ "karma": "^2.0.0", | ||
"nyc": "^11.4.1", | ||
"opn": "^5.1.0", | ||
"rimraf": "^2.6.2", | ||
@@ -54,0 +54,0 @@ "should": "^13.1.3", |
@@ -1,2 +0,2 @@ | ||
[![Build Status](https://travis-ci.org/tandrewnichols/indefinite.png)](https://travis-ci.org/tandrewnichols/indefinite) [![downloads](http://img.shields.io/npm/dm/indefinite.svg)](https://npmjs.org/package/indefinite) [![npm](http://img.shields.io/npm/v/indefinite.svg)](https://npmjs.org/package/indefinite) [![Code Climate](https://codeclimate.com/github/tandrewnichols/indefinite/badges/gpa.svg)](https://codeclimate.com/github/tandrewnichols/indefinite) [![Test Coverage](https://codeclimate.com/github/tandrewnichols/indefinite/badges/coverage.svg)](https://codeclimate.com/github/tandrewnichols/indefinite) [![dependencies](https://david-dm.org/tandrewnichols/indefinite.png)](https://david-dm.org/tandrewnichols/indefinite) ![Size](https://img.shields.io/badge/size-187b-brightgreen.svg) | ||
[![Build Status](https://travis-ci.org/tandrewnichols/indefinite.png)](https://travis-ci.org/tandrewnichols/indefinite) [![downloads](http://img.shields.io/npm/dm/indefinite.svg)](https://npmjs.org/package/indefinite) [![npm](http://img.shields.io/npm/v/indefinite.svg)](https://npmjs.org/package/indefinite) [![Code Climate](https://codeclimate.com/github/tandrewnichols/indefinite/badges/gpa.svg)](https://codeclimate.com/github/tandrewnichols/indefinite) [![Test Coverage](https://codeclimate.com/github/tandrewnichols/indefinite/badges/coverage.svg)](https://codeclimate.com/github/tandrewnichols/indefinite) [![dependencies](https://david-dm.org/tandrewnichols/indefinite.png)](https://david-dm.org/tandrewnichols/indefinite) ![Size](https://img.shields.io/badge/size-2kb-brightgreen.svg) | ||
@@ -13,4 +13,8 @@ # indefinite | ||
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. Additionally, 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. | ||
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, 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 | ||
@@ -24,2 +28,4 @@ | ||
console.log(a('UFO')); // 'a UFO' | ||
console.log(a('hour')); // 'an hour' | ||
console.log(a('ukelele')); // 'a ukelele' | ||
``` | ||
@@ -26,0 +32,0 @@ |
@@ -6,3 +6,3 @@ require('should'); | ||
context('a noun that starts with a vowel', () => { | ||
context('a word that starts with a vowel', () => { | ||
it('should be prefixed with an', () => { | ||
@@ -13,3 +13,3 @@ indefinite('apple').should.equal('an apple'); | ||
context('a noun that starts with a consonant', () => { | ||
context('a word that starts with a consonant', () => { | ||
it('should be prefixed with a', () => { | ||
@@ -20,3 +20,3 @@ indefinite('banana').should.equal('a banana'); | ||
context('a noun that starts with a capital vowel', () => { | ||
context('a word that starts with a capital vowel', () => { | ||
it('should be maintain capitalization', () => { | ||
@@ -27,3 +27,3 @@ indefinite('Apple').should.equal('an Apple'); | ||
context('a noun that starts with a capital consonant', () => { | ||
context('a word that starts with a capital consonant', () => { | ||
it('should maintain capitalization', () => { | ||
@@ -34,3 +34,3 @@ indefinite('Banana').should.equal('a Banana'); | ||
context('a noun that starts with a vowel when capitalize is passed in', () => { | ||
context('a word that starts with a vowel when capitalize is passed in', () => { | ||
it('should capitalize the article', () => { | ||
@@ -41,3 +41,3 @@ indefinite('apple', { capitalize: true }).should.equal('An apple'); | ||
context('a noun that starts with a consonant when capitalize is passed in', () => { | ||
context('a word that starts with a consonant when capitalize is passed in', () => { | ||
it('should capitalize the article', () => { | ||
@@ -71,2 +71,56 @@ indefinite('banana', { capitalize: true }).should.equal('A banana'); | ||
}) | ||
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 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('an irregular word with some capitalization is passed', () => { | ||
it('should be treated case-insensitively', () => { | ||
indefinite('Hour').should.equal('an Hour'); | ||
}) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
33807
594
46