├── .gitignore ├── demo.gif ├── .editorconfig ├── constants.js ├── package.json ├── LICENSE ├── api.js ├── cli ├── README.md └── print.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ 3 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdgluck/werd/HEAD/demo.gif -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | -------------------------------------------------------------------------------- /constants.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports.API = 'https://wordsapiv1.p.mashape.com/words' 4 | 5 | module.exports.METHODS = [ 6 | 'definitions', 'synonyms', 'antonyms', 'examples', 'typeOf', 'hasTypes', 7 | 'partOf', 'instanceOf', 'hasInstances', 'similarTo', 'also', 'syllables', 8 | 'entails', 'memberOf', 'hasMembers', 'substanceOf', 'hasSubstances', 9 | 'inCategory', 'hasCategories', 'usageOf', 'hasUsages', 'inRegion', 10 | 'regionOf', 'pertainsTo', 'rhymes', 'frequency', 'pronunciation', 'hasParts' 11 | ] 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "werd", 3 | "version": "0.2.7", 4 | "description": "Words API for JavaScript", 5 | "main": "api.js", 6 | "bin": { 7 | "werd": "./cli", 8 | "word": "./cli" 9 | }, 10 | "scripts": { 11 | "lint": "standard", 12 | "prepublish": "npm run lint" 13 | }, 14 | "author": "Sam Gluck ", 15 | "license": "MIT", 16 | "keywords": [ 17 | "word", 18 | "words", 19 | "api", 20 | "werd", 21 | "cli", 22 | "dictionary", 23 | "synonym", 24 | "antonym", 25 | "meaning", 26 | "definition" 27 | ], 28 | "devDependencies": { 29 | "babel-eslint": "^6.1.2", 30 | "standard": "^8.0.0-beta.5", 31 | "tape": "^4.6.0" 32 | }, 33 | "dependencies": { 34 | "axios": "^0.13.1", 35 | "chalk": "^1.1.3", 36 | "inquirer": "^1.1.2", 37 | "log-update": "^1.0.2", 38 | "meow": "^3.7.0", 39 | "node-localstorage": "^1.3.0", 40 | "ora": "^0.2.3", 41 | "os-homedir": "^1.0.1", 42 | "query-string": "^4.2.2" 43 | }, 44 | "standard": { 45 | "parser": "babel-eslint" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Sam Gluck 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /api.js: -------------------------------------------------------------------------------- 1 | /* global Promise:false, define:false, module:false, self:false */ 2 | 3 | 'use strict' 4 | 5 | if (typeof define === 'function' && define.amd) { 6 | define('werd', function () { return werd }) 7 | } else if (typeof module === 'object' && module.exports) { 8 | module.exports = werd 9 | } else { 10 | self.werd = werd 11 | } 12 | 13 | var axios = require('axios') 14 | var queryString = require('query-string') 15 | 16 | var constants = require('./constants') 17 | 18 | var API = constants.API 19 | var METHODS = constants.METHODS 20 | 21 | function request (url) { 22 | return axios.get(url).then(function (response) { 23 | if (String(response.status) !== '200') { 24 | return Promise.reject(Error(response.status + ' response: ' + response.body)) 25 | } 26 | return response.data 27 | }) 28 | } 29 | 30 | function werd (mashapeKey) { 31 | if (typeof mashapeKey !== 'string') { 32 | throw new Error('Expecting mashapeKey to be a string') 33 | } 34 | 35 | axios.defaults.headers['X-Mashape-Key'] = mashapeKey 36 | axios.defaults.headers['Accept'] = 'application/json' 37 | 38 | return api 39 | } 40 | 41 | function api (word) { 42 | if (typeof word !== 'string') { 43 | return Promise.reject(Error('Expecting word to be a string')) 44 | } 45 | return request([API, word].join('/')) 46 | } 47 | 48 | api.get = api 49 | 50 | api.search = function (options) { 51 | if (!options) { 52 | return Promise.reject(Error('Expecting options object')) 53 | } 54 | return request(API + '?' + queryString.stringify(options)) 55 | } 56 | 57 | api.random = function () { 58 | return request(API + '?random=true') 59 | } 60 | 61 | METHODS.forEach(function (wordDetailSlug) { 62 | api[wordDetailSlug] = function (word) { 63 | if (typeof word !== 'string') { 64 | return Promise.reject(Error('Expecting word to be a string')) 65 | } 66 | return request([API, word, wordDetailSlug].join('/')) 67 | } 68 | }) 69 | -------------------------------------------------------------------------------- /cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | 4 | const path = require('path') 5 | const ora = require('ora') 6 | const meow = require('meow') 7 | const chalk = require('chalk') 8 | const inquirer = require('inquirer') 9 | const logUpdate = require('log-update') 10 | const osHomedir = require('os-homedir') 11 | const LocalStorage = require('node-localstorage').LocalStorage 12 | 13 | const werd = require('./api') 14 | const print = require('./print') 15 | const constants = require('./constants') 16 | 17 | const profileDir = path.resolve(osHomedir(), '.werd') 18 | const storage = new LocalStorage(profileDir) 19 | 20 | const keyPrompt = { 21 | name: 'key', 22 | type: 'text', 23 | message: 'Enter your Mashape API key:' 24 | } 25 | 26 | const cli = meow(` 27 | Usage 28 | $ werd [] 29 | 30 | Inputs 31 | word, the word to query 32 | operation, the query operation (default: get) 33 | 34 | Examples 35 | $ werd chump 36 | $ werd program synonyms 37 | $ werd ocean syllables 38 | `) 39 | 40 | Promise 41 | .resolve(storage.getItem('mashapeApiKey')) 42 | .then((key) => { 43 | if (key) { 44 | return key 45 | } 46 | 47 | logUpdate() 48 | 49 | return inquirer 50 | .prompt([keyPrompt]) 51 | .then((answers) => answers.key) 52 | }) 53 | .then((key) => { 54 | const api = werd(key) 55 | const spinner = ora() 56 | 57 | storage.setItem('mashapeApiKey', key) 58 | logUpdate.clear() 59 | 60 | setInterval(() => logUpdate(spinner.frame()), 100) 61 | 62 | const word = cli.input[0] 63 | const isRandomOp = word === 'random' 64 | const method = isRandomOp ? api.random : cli.input[1] ? api[cli.input[1]] : api 65 | 66 | if (!method) { 67 | console.log(`Unknown operation "${cli.input[1]}"`) 68 | process.exit() 69 | } 70 | 71 | method(word) 72 | .then((result) => { 73 | logUpdate.clear() 74 | print[cli.input[1] || 'get'](isRandomOp ? result.word : cli.input[0], result) 75 | }) 76 | .catch((err) => { 77 | if (/404/.test(err)) logUpdate(`Word "${chalk.yellow(word)}" was not found.`) 78 | else logUpdate('A wild error appeared!\n' + err) 79 | }) 80 | .then(() => process.exit()) 81 | }) 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # werd 2 | 3 | > Words API for JavaScript 4 | 5 | Made with ❤ at [@outlandish](http://www.twitter.com/outlandish) 6 | 7 | npm version 8 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) 9 | 10 | An unofficial Words API library for JavaScript with a CLI. 11 | 12 | Learn ya'self some words on the command line! 13 | 14 | See [wordsapi.com](https://www.wordsapi.com/) for details on the Words API, "an API for the English language". 15 | 16 | werd demo 17 | 18 | ## Install 19 | 20 | __API__ 21 | 22 | ```sh 23 | npm install --save werd 24 | ``` 25 | 26 | __CLI__ 27 | 28 | ```sh 29 | npm install --global werd 30 | ``` 31 | 32 | ## Requirements 33 | 34 | - Mashape Words API key ([get one here](https://market.mashape.com/wordsapi/wordsapi/pricing)) 35 | - Node >= v4 for CLI 36 | 37 | ## Import 38 | 39 | ```js 40 | // ES6 41 | import werd from 'werd' 42 | ``` 43 | 44 | ```js 45 | // CommonJS 46 | var werd = require('werd') 47 | ``` 48 | 49 | ```html 50 | 51 | 52 | ``` 53 | 54 | ## API 55 | 56 | _Read the Words API documentation for more details:_ 57 | 58 | https://market.mashape.com/wordsapi/wordsapi 59 | 60 | ### `werd(apiKey) : api` 61 | 62 | Get word API instance using the given `apiKey`. 63 | 64 | - __apiKey__ {String} Mashape Words API key 65 | 66 | Returns the werd `api`. 67 | 68 | ### `api(word) : Promise` 69 | 70 | Get a word definition object. Also available as `api.get()`. 71 | 72 | - __word__ {String} The word 73 | 74 | Returns a Promise that resolves to the word definition object. 75 | 76 | ### `api.{operation}(word) : Promise` 77 | 78 | Get data for the given word respective to the chosen operation. 79 | 80 | - __word__ {String} The word 81 | 82 | Returns a Promise that resolves with the respective data. 83 | 84 | Available operations: 85 | 86 | ```js 87 | definitions, synonyms, antonyms, examples, typeOf, hasTypes, 88 | partOf, instanceOf, hasInstances, similarTo, also, syllables, 89 | entails, memberOf, hasMembers, substanceOf, hasSubstances, 90 | inCategory, hasCategories, usageOf, hasUsages, inRegion, 91 | regionOf, pertainsTo, rhymes, frequency, pronunciation, hasParts 92 | ``` 93 | 94 | ## CLI Usage 95 | 96 | You will be prompted for your Mashape API key the first time you use the CLI. 97 | 98 | ```sh 99 | $ werd|word --help 100 | 101 | Usage 102 | $ werd|word [] 103 | 104 | Inputs 105 | word, the word to query 106 | operation, the query operation (default: get) 107 | 108 | Examples 109 | $ word chump 110 | $ werd program synonyms 111 | $ werd ocean syllables 112 | ``` 113 | 114 | ## Contributing 115 | 116 | All pull requests and issues welcome! 117 | 118 | If you're not sure how, check out Kent C. Dodds' 119 | [great video tutorials on egghead.io](https://egghead.io/lessons/javascript-identifying-how-to-contribute-to-an-open-source-project-on-github)! 120 | 121 | ## Author & License 122 | 123 | `werd` was created by [Sam Gluck](https://twitter.com/sdgluck) and is released under the MIT license. 124 | -------------------------------------------------------------------------------- /print.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | 5 | const frequencyGlossary = { 6 | zipf: '1-7 scale of how common the word is in the English language', 7 | perMillion: 'number of times the word is likely to appear in a corpus of one million English words', 8 | diversity: '0-1 scale that shows the likelihood of a word appearing in an English document that is part of a corpus' 9 | } 10 | 11 | const listLoggers = { 12 | synonyms: 'Synonyms of WORD', 13 | antonyms: 'Antonyms of WORD', 14 | rhymes: 'Rhymes of WORD', 15 | examples: 'Examples of WORD', 16 | also: 'Words of which WORD is a part', 17 | entails: 'Words that are implied by WORD', 18 | hasCategories: 'Categories of WORD', 19 | hasInstances: 'Words that are examples of WORD', 20 | hasMembers: 'Words that belong to the group defined by WORD', 21 | hasParts: 'Words that are a parts of WORD', 22 | hasSubstances: 'Words that are substances of WORD', 23 | hasTypes: 'More specific examples of WORD', 24 | hasUsages: 'Words that are examples of the domain of WORD', 25 | inRegion: 'Geographical areas where WORD is used', 26 | inCategory: 'The domain category to which WORD belongs', 27 | typeOf: 'Words that are more general than WORD', 28 | instanceOf: 'Words that WORD is an example of', 29 | memberOf: 'Groups to which WORD belongs', 30 | partOf: 'The larger whole to which WORD belongs', 31 | pertainsTo: 'Words to which WORD is relevant', 32 | regionOf: 'Words used in the geographical area of WORD', 33 | similarTo: 'Words that are similar to WORD, but which are not synonyms', 34 | substancesOf: 'Substances to which WORD is a part of', 35 | usageOf: 'Words that WORD is a domain usage of' 36 | } 37 | 38 | function highlightValues (strings, values) { 39 | let i = 0 40 | return strings.reduce((heading, str) => { 41 | return heading + str + (values[i] ? chalk.yellow(values[i++]) : '') 42 | }, '') 43 | } 44 | 45 | function logHeading (strings) { 46 | const values = Array.from(arguments).slice(1) 47 | console.log(`\n ${highlightValues(strings, values)}\n`) 48 | } 49 | 50 | function logList (list) { 51 | if (list.length) { 52 | console.log('\t' + list.join('\n\t')) 53 | } else { 54 | console.log('\tNo data') 55 | } 56 | } 57 | 58 | function listFn (heading, propName) { 59 | return (word, data) => { 60 | console.log(`\n ${heading.replace('WORD', chalk.yellow(word))}\n`) 61 | logList(data[propName]) 62 | } 63 | } 64 | 65 | Object.assign(module.exports, Object.keys(listLoggers).reduce((obj, key) => { 66 | const heading = listLoggers[key] 67 | obj[key] = listFn(heading, key) 68 | return obj 69 | }, {})) 70 | 71 | module.exports.frequency = (word, data) => { 72 | logHeading`Frequency of ${chalk.yellow(data.word)}` 73 | console.log(`\t${chalk.yellow('zipf')}: ` + data.frequency.zipf || '?') 74 | console.log(`\t${chalk.yellow('perMillion')}: ` + data.frequency.perMillion || '?') 75 | console.log(`\t${chalk.yellow('diversity')}: ` + data.frequency.diversity || '?') 76 | 77 | logHeading`Glossary` 78 | Object.keys(frequencyGlossary).forEach(key => { 79 | console.log(`\t${chalk.yellow(key)}: ${frequencyGlossary[key]}`) 80 | }) 81 | } 82 | 83 | module.exports.pronunciation = (word, data) => { 84 | const results = data.pronunciation 85 | const keys = Object.keys(results) 86 | 87 | logHeading`Pronunciation of ${word}` 88 | keys.length && keys.forEach((key) => { 89 | console.log(`\t${chalk.yellow(key)}: ${results[key]}\n`) 90 | }) 91 | } 92 | 93 | module.exports.syllables = (word, data) => { 94 | logHeading`Syllables of ${word}` 95 | console.log(`\t${data.syllables.list.join(', ')}`) 96 | } 97 | 98 | module.exports.random = 99 | module.exports.get = 100 | module.exports.definitions = (word, data) => { 101 | const results = data.results || [] 102 | 103 | logHeading`${word}` 104 | 105 | results.length && console.log(results.map((result, i) => { 106 | return `\t${i + 1}. ${chalk.yellow(result.partOfSpeech)}, ${result.definition}\n\n` 107 | }).join('')) 108 | } 109 | --------------------------------------------------------------------------------