+487
| /** | ||
| * Library for translating to/from the phonetic alphabet. | ||
| * | ||
| * @module phony | ||
| * @version 1.2.1 | ||
| * @copyright Alasdair Mercer 2015 | ||
| * @license MIT | ||
| */ | ||
| (function(factory) { | ||
| 'use strict'; | ||
| /** | ||
| * The root object that has been determined for the current environment (browser, server, <code>WebWorker</code>). | ||
| * | ||
| * @access private | ||
| * @type {*} | ||
| */ | ||
| var root = (typeof self === 'object' && self.self === self && self) || | ||
| (typeof global === 'object' && global.global === global && global); | ||
| if (typeof define === 'function' && define.amd) { | ||
| // Defines for AMD but also exports to root for those expecting global phony | ||
| define(function() { | ||
| root.phony = factory(root); | ||
| return root.phony; | ||
| }); | ||
| } else if (typeof module !== 'undefined' && module.exports) { | ||
| // Supports Node.js and the CommonJS patterns | ||
| exports = module.exports = factory(root); | ||
| } else { | ||
| // Falls back on browser support | ||
| root.phony = factory(root); | ||
| } | ||
| }(function(root) { | ||
| 'use strict'; | ||
| /** | ||
| * A phonetic alphabet configuration. | ||
| * | ||
| * @typedef {Object} PhoneticAlphabet | ||
| * @property {Object.<String, String>} characters - The map of characters and their phonetic counterparts. | ||
| * @property {String} [fallback] - The name of the fallback alphabet. | ||
| */ | ||
| /** | ||
| * Options to be passed to the primary {@linkcode phony} methods. | ||
| * | ||
| * @typedef {Object} PhonyOptions | ||
| * @property {String} [alphabet="itu"] - The default name of the alphabet to be used for the translation. | ||
| * @property {Boolean} [cache=true] - Whether a cache should be used for built alphabets to to improve performance. | ||
| * This cache can be disabled and/or cleared to avoid when modifying alphabets. | ||
| * @property {String} [letterSplitter=" "] - The default string to be used to split alphabetic letters (may be passed | ||
| * to <code>RegExp</code> constructor). | ||
| * @property {String} [wordSplitter="space"] - The default string to be used to split words (may be passed to | ||
| * <code>RegExp</code> constructor). | ||
| */ | ||
| /** | ||
| * The main <code>phony</code> object to be exported. | ||
| * | ||
| * @access public | ||
| * @type {Object} | ||
| * @alias module:phony | ||
| */ | ||
| var phony = {}; | ||
| /** | ||
| * The previous value of the <code>phony</code> variable. | ||
| * | ||
| * @access private | ||
| * @type {*} | ||
| */ | ||
| var previousPhony = root.phony; | ||
| /** | ||
| * A cache of built alphabets that can be used to improve performance and avoid unnecessary rebuilds of the same | ||
| * alphabets. | ||
| * <p/> | ||
| * This cache can be cleared at any time by using {@linkcode phony.clearCache} or bypassed on a case-by-case basis | ||
| * via the <code>cache</code> option. | ||
| * | ||
| * @access private | ||
| * @type {Object.<String, Object<String, String>>} | ||
| */ | ||
| var alphabetCache = {}; | ||
| /** | ||
| * Populates the specified <code>target</code> mapping with key/value pairs extracted from the character mapping from | ||
| * the named alphabet those from the fallback chain, where applicable. | ||
| * <p/> | ||
| * The key/value pairs are determined by the return value of the <code>iterator</code> provided, which should provide | ||
| * a simple two-element array where the first element will be used as the key and the second as the value. However, | ||
| * that key/value pair will only be set on <code>target</code> if a previous alphabet hasn't already set the same | ||
| * key. | ||
| * | ||
| * @param {Object.<String, String>} target - the mapping to be populated | ||
| * @param {String} name - the name of the alphabet to be built | ||
| * @param {String} method - the name of the method responsible for building this alphabet (used for caching purposes) | ||
| * @param {Boolean} cache - <code>true</code> to check and use a previously built and cached alphabet or caching this | ||
| * one after building it if not previously cached; otherwise <code>false</code> | ||
| * @param {Function} iterator - iterator which will be passed a character and phonetic mapping and needs to return a | ||
| * two-element array for the key/value mapping to be set on <code>target</code> | ||
| * @returns {Object.<String, String>} The populated <code>target</code>. | ||
| * @access private | ||
| */ | ||
| function buildAlphabet(target, name, method, cache, iterator) { | ||
| var alphabet = phony.alphabets[name]; | ||
| if (!alphabet) { | ||
| return target; | ||
| } | ||
| var cacheHash = name + ':' + method; | ||
| if (cache && alphabetCache[cacheHash]) { | ||
| return alphabetCache[cacheHash]; | ||
| } | ||
| each(alphabet.characters, function(character, phonetic) { | ||
| var keyValue = iterator(character, phonetic); | ||
| var key = keyValue[0]; | ||
| var value = keyValue[1]; | ||
| if (!target.hasOwnProperty(key)) { | ||
| target[key] = value; | ||
| } | ||
| }); | ||
| buildAlphabet(target, alphabet.fallback, method, false, iterator); | ||
| if (cache) { | ||
| alphabetCache[cacheHash] = target; | ||
| } | ||
| return target; | ||
| } | ||
| /** | ||
| * Iterates over a given <code>object</code>. | ||
| * <p/> | ||
| * If <code>object</code> is an array, each element is yielded in turn to the specified <code>iterator</code> | ||
| * function; otherwise this is done for the key/value mapping of the hash. | ||
| * | ||
| * @param {Array|Object} [object] - the object or array to be iterated over | ||
| * @param {Function} iterator - the iterator function to be passed index/element if <code>object</code> is an array | ||
| * or key/value if it is a hash | ||
| * @returns {Array|Object} The specified <code>object</code>. | ||
| * @access private | ||
| */ | ||
| function each(object, iterator) { | ||
| if (!object) { | ||
| return object; | ||
| } | ||
| var key; | ||
| var index; | ||
| var length = object.length; | ||
| if (length === +length) { | ||
| for (index = 0; index < length; index++) { | ||
| iterator(object[index], index, object); | ||
| } | ||
| } else { | ||
| for (key in object) { | ||
| if (object.hasOwnProperty(key)) { | ||
| iterator(key, object[key], object); | ||
| } | ||
| } | ||
| } | ||
| return object; | ||
| } | ||
| /** | ||
| * Returns the given <code>options</code> with all of the <code>defaults</code> applied. | ||
| * <p/> | ||
| * This function <i>will change</i> the specified <code>options</code>. | ||
| * | ||
| * @param {PhonyOptions} [options={}] - the options to be extended | ||
| * @param {PhonyOptions} defaults - the default options | ||
| * @returns {PhonyOptions} The specified <code>options</code> with modifications. | ||
| * @access private | ||
| */ | ||
| function getOptions(options, defaults) { | ||
| options = options || {}; | ||
| for (var key in defaults) { | ||
| if (typeof options[key] === 'undefined') { | ||
| options[key] = defaults[key]; | ||
| } | ||
| } | ||
| options.alphabet = options.alphabet.toLocaleLowerCase(); | ||
| options.wordSplitter = options.wordSplitter.toLocaleLowerCase(); | ||
| return options; | ||
| } | ||
| /** | ||
| * Prepares a given string to simplify translation. | ||
| * | ||
| * @param {String} str - the string to prepare | ||
| * @param {String} [transformer] - the name of a <code>String.prototype</code> method to be used to transform | ||
| * <code>str</code> prior to preparation | ||
| * @param {String} wordSplitter - the string used to split words (will be passed to <code>RegExp</code> constructor) | ||
| * @param {String} letterSplitter - the string used to split alphabetic letters | ||
| * @returns {Array.<Array.<String>>} A multi-dimensional array of words and their alphabetic letters contained | ||
| * within. | ||
| * @access private | ||
| */ | ||
| function prepare(str, transformer, wordSplitter, letterSplitter) { | ||
| if (typeof str !== 'string') { | ||
| throw new TypeError('Invalid value type: ' + typeof str); | ||
| } | ||
| if (transformer && typeof str[transformer] === 'function') { | ||
| str = str[transformer](); | ||
| } | ||
| var rWordSplitter = new RegExp(wordSplitter + '|[\\n\\r]+', 'gi'); | ||
| var result = str.trim().split(rWordSplitter); | ||
| each(result, function(word, i) { | ||
| result[i] = word.split(letterSplitter); | ||
| }); | ||
| return result; | ||
| } | ||
| /** | ||
| * Transforms a given string in to title case. | ||
| * | ||
| * @param {String} str - the string to be transformed | ||
| * @returns {String} <code>str</code> in title case form. | ||
| * @access private | ||
| */ | ||
| function toTitleCase(str) { | ||
| return str[0].toLocaleUpperCase() + str.substring(1).toLocaleLowerCase(); | ||
| } | ||
| /** | ||
| * The current version of {@linkcode phony}. | ||
| * | ||
| * @access public | ||
| * @static | ||
| * @constant | ||
| * @type {String} | ||
| */ | ||
| phony.VERSION = '1.2.1'; | ||
| /** | ||
| * The configurations for the initially supported phonetic alphabets. | ||
| * | ||
| * @access public | ||
| * @static | ||
| * @type {Object.<String, PhoneticAlphabet>} | ||
| * @property {PhoneticAlphabet} ansi - The American National Standards Institute (ANSI) phonetic alphabet | ||
| * configuration. | ||
| * @property {PhoneticAlphabet} faa - The Federal Aviation Administration (FAA) phonetic alphabet configuration. | ||
| * @property {PhoneticAlphabet} icao - The International Civil Aviation Organization (ICAO) phonetic alphabet | ||
| * configuration. | ||
| * @property {PhoneticAlphabet} itu - The International Telecommunication Union (ITU) phonetic alphabet | ||
| * configuration. | ||
| */ | ||
| phony.alphabets = { | ||
| ansi: { | ||
| fallback: 'itu', | ||
| characters: { | ||
| 'A': 'alpha', | ||
| 'J': 'juliet' | ||
| } | ||
| }, | ||
| faa: { | ||
| fallback: 'itu', | ||
| characters: { | ||
| '0': 'zero', | ||
| '1': 'one', | ||
| '2': 'two', | ||
| '3': 'three', | ||
| '4': 'four', | ||
| '5': 'five', | ||
| '6': 'six', | ||
| '7': 'seven', | ||
| '8': 'eight', | ||
| '9': 'nine' | ||
| } | ||
| }, | ||
| icao: { | ||
| fallback: 'faa', | ||
| characters: { | ||
| '9': 'niner' | ||
| } | ||
| }, | ||
| itu: { | ||
| characters: { | ||
| 'A': 'alfa', | ||
| 'B': 'bravo', | ||
| 'C': 'charlie', | ||
| 'D': 'delta', | ||
| 'E': 'echo', | ||
| 'F': 'foxtrot', | ||
| 'G': 'golf', | ||
| 'H': 'hotel', | ||
| 'I': 'india', | ||
| 'J': 'juliett', | ||
| 'K': 'kilo', | ||
| 'L': 'lima', | ||
| 'M': 'mike', | ||
| 'N': 'november', | ||
| 'O': 'oscar', | ||
| 'P': 'papa', | ||
| 'Q': 'quebec', | ||
| 'R': 'romeo', | ||
| 'S': 'sierra', | ||
| 'T': 'tango', | ||
| 'U': 'uniform', | ||
| 'V': 'victor', | ||
| 'W': 'whiskey', | ||
| 'X': 'x-ray', | ||
| 'Y': 'yankee', | ||
| 'Z': 'zulu', | ||
| '0': 'nadazero', | ||
| '1': 'unaone', | ||
| '2': 'bissotwo', | ||
| '3': 'terrathree', | ||
| '4': 'kartefour', | ||
| '5': 'pantafive', | ||
| '6': 'soxisix', | ||
| '7': 'setteseven', | ||
| '8': 'oktoeight', | ||
| '9': 'novenine', | ||
| '.': 'stop', | ||
| '-': 'dash' | ||
| } | ||
| } | ||
| }; | ||
| /** | ||
| * The default values to be used when options are not specified or incomplete. | ||
| * | ||
| * @access public | ||
| * @static | ||
| * @type {PhonyOptions} | ||
| */ | ||
| phony.defaults = { | ||
| alphabet: 'itu', | ||
| cache: true, | ||
| letterSplitter: ' ', | ||
| wordSplitter: 'space' | ||
| }; | ||
| /** | ||
| * Clears any previously cached built alphabets. | ||
| * <p/> | ||
| * This can be useful for when modifications have been made to the alphabet mapping. | ||
| * | ||
| * @returns {Object} A reference to this {@linkcode phony} for chaining. | ||
| * @access public | ||
| * @static | ||
| */ | ||
| phony.clearCache = function() { | ||
| alphabetCache = {}; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Translates the <code>message</code> provided <i>from</i> the phonetic alphabet. | ||
| * <p/> | ||
| * The message may not be translated correctly if the some of the options used to translate the message originally | ||
| * are not the same as those in <code>options</code>. | ||
| * | ||
| * @param {String} [message=""] - the string to be translated from the phonetic alphabet | ||
| * @param {PhonyOptions} [options={}] - the options to be used | ||
| * @returns {String} The translation from the specified phonetic alphabet <code>message</code>. | ||
| * @access public | ||
| * @static | ||
| */ | ||
| phony.from = function(message, options) { | ||
| message = message || ''; | ||
| options = getOptions(options, phony.defaults); | ||
| var result = ''; | ||
| var value = prepare(message, 'toLocaleLowerCase', options.wordSplitter, options.letterSplitter); | ||
| // Ensures message was prepared successfully and that a valid alphabet was specified | ||
| if (!value || !phony.alphabets[options.alphabet]) { | ||
| return result; | ||
| } | ||
| var alphabet = buildAlphabet({}, options.alphabet, 'from', options.cache, function(character, phonetic) { | ||
| return [phonetic, character]; | ||
| }); | ||
| // Iterates over each word | ||
| each(value, function(word, i) { | ||
| // Inserts space between each word | ||
| if (i > 0) { | ||
| result += ' '; | ||
| } | ||
| // Iterates over each phonetic representation in the word | ||
| each(word, function(phonetic) { | ||
| // Reverse engineers character from phonetic representation | ||
| var character = alphabet[phonetic]; | ||
| // Checks if character is supported | ||
| if (typeof character === 'string') { | ||
| result += character; | ||
| } | ||
| }); | ||
| }); | ||
| return result; | ||
| }; | ||
| /** | ||
| * Translates the <code>message</code> provided <i>to</i> the phonetic alphabet. | ||
| * | ||
| * @param {String} [message=""] - the string to be translated to the phonetic alphabet | ||
| * @param {PhonyOptions} [options={}] - the options to be used | ||
| * @returns {String} The phonetic alphabet translation of the specified <code>message</code>. | ||
| * @access public | ||
| * @static | ||
| */ | ||
| phony.to = function(message, options) { | ||
| message = message || ''; | ||
| options = getOptions(options, phony.defaults); | ||
| var letterSplitter = options.letterSplitter; | ||
| var result = ''; | ||
| var value = prepare(message, 'toLocaleUpperCase', '\\s+', ''); | ||
| var wordSplitter = letterSplitter + toTitleCase(options.wordSplitter) + letterSplitter; | ||
| // Ensures message was prepared successfully and that a valid alphabet was specified | ||
| if (!value || !phony.alphabets[options.alphabet]) { | ||
| return result; | ||
| } | ||
| var alphabet = buildAlphabet({}, options.alphabet, 'to', options.cache, function(character, phonetic) { | ||
| return [character, phonetic]; | ||
| }); | ||
| // Iterates over each word | ||
| each(value, function(word, i) { | ||
| // Inserts wordSplitter option between each word | ||
| if (i > 0) { | ||
| result += wordSplitter; | ||
| } | ||
| // Iterates over each character in the word | ||
| each(word, function(character, j) { | ||
| // Reverse engineers character from phonetic representation | ||
| var phonetic = alphabet[character]; | ||
| // Checks if phonetic representation is supported | ||
| if (typeof phonetic === 'string') { | ||
| // Inserts letterSplitter option between each character | ||
| if (j > 0) { | ||
| result += letterSplitter; | ||
| } | ||
| result += toTitleCase(phonetic); | ||
| } | ||
| }); | ||
| }); | ||
| return result; | ||
| }; | ||
| /** | ||
| * Runs phony in <i>no conflict</i> mode, returning the <code>phony</code> global variable to it's previous owner, if | ||
| * any. | ||
| * | ||
| * @returns {Object} A reference to this {@linkcode phony}. | ||
| * @access public | ||
| * @static | ||
| */ | ||
| phony.noConflict = function() { | ||
| root.phony = previousPhony; | ||
| return this; | ||
| }; | ||
| return phony; | ||
| })); |
+13
-0
@@ -0,1 +1,11 @@ | ||
| ## Version 1.2.1, 2015.06.14 | ||
| * [#9](https://github.com/neocotic/phony.js/issues/9): Improve performance of core functions | ||
| * [#9](https://github.com/neocotic/phony.js/issues/9): Add new `cache` option (enabled by default) to core functions to bypass alphabet caching | ||
| * [#9](https://github.com/neocotic/phony.js/issues/9): Add new `phony.clearCache` function to purge alphabet cache at any time | ||
| * [#15](https://github.com/neocotic/phony.js/issues/15): Remove copy of source file from `dist` directory | ||
| * [#16](https://github.com/neocotic/phony.js/issues/16): Switch badges in `README.md` to use [Shields.io][10] | ||
| * [#17](https://github.com/neocotic/phony.js/issues/17): Switch from [Code Climate][11] to [Coveralls][12] for code coverage | ||
| * Rename `src` directory to `lib` | ||
| ## Version 1.2.0, 2015.06.06 | ||
@@ -35,1 +45,4 @@ | ||
| [9]: http://editorconfig.org | ||
| [10]: http://shields.io | ||
| [11]: https://codeclimate.com | ||
| [12]: https://coveralls.io |
+5
-5
| { | ||
| "name": "node-phony", | ||
| "version": "1.2.0", | ||
| "version": "1.2.1", | ||
| "description": "Library for translating to/from the phonetic alphabet", | ||
@@ -34,3 +34,2 @@ "homepage": "http://neocotic.com/phony.js", | ||
| "devDependencies": { | ||
| "codeclimate-test-reporter": "^0.0.4", | ||
| "expect.js": "^0.3.1", | ||
@@ -44,3 +43,4 @@ "grunt": "^0.4.5", | ||
| "grunt-contrib-watch": "^0.6.1", | ||
| "grunt-eslint": "^13.0.0", | ||
| "grunt-coveralls": "^1.0.0", | ||
| "grunt-eslint": "^14.0.0", | ||
| "grunt-jsdoc": "^0.6.7", | ||
@@ -52,5 +52,5 @@ "grunt-mocha-test": "^0.12.7", | ||
| }, | ||
| "main": "src/phony.js", | ||
| "main": "lib/phony.js", | ||
| "scripts": { | ||
| "codeclimate": "codeclimate < coverage/lcov.info", | ||
| "coveralls": "grunt coveralls", | ||
| "test": "grunt test" | ||
@@ -57,0 +57,0 @@ }, |
+35
-15
@@ -16,7 +16,7 @@ ``` | ||
| [][1] | ||
| [][10] | ||
| [][11] | ||
| [][4] | ||
| [][5] | ||
| [][1] | ||
| [][10] | ||
| [][4] | ||
| [][9] | ||
| [][5] | ||
@@ -44,7 +44,8 @@ ## Install | ||
| | Option | Description | Default | | ||
| | -------------- | -------------------------------------------------------- | --------- | | ||
| | alphabet | Name of the alphabet to be used to translate the message | `"itu"` | | ||
| | letterSplitter | Sequence of characters to split letters | `" "` | | ||
| | wordSplitter | Sequence of characters to split words | `"space"` | | ||
| | Option | Description | Default | | ||
| | -------------- | ------------------------------------------------------------ | --------- | | ||
| | alphabet | Name of the alphabet to be used to translate the message | `"itu"` | | ||
| | cache | Whether to cache built alphabets when calling `from` or `to` | `true` | | ||
| | letterSplitter | Sequence of characters to split letters | `" "` | | ||
| | wordSplitter | Sequence of characters to split words | `"space"` | | ||
@@ -110,2 +111,20 @@ It's important to note that the same options should be used in order for bidirectional translations to work. Some of | ||
| #### `clearCache()` | ||
| Clears any previously built alphabets that may have been cached by `phony.from` and/or `phony.to`. This can be useful | ||
| when making modifications to alphabets and having them picked up. | ||
| ``` javascript | ||
| phony.to('SOS'); | ||
| //=> "Sierra Oscar Sierra" | ||
| phony.alphabets.itu.characters['O'] = 'Oompa'; | ||
| phony.clearCache(); | ||
| phony.to('SOS'); | ||
| //=> "Sierra Oompa Sierra" | ||
| ``` | ||
| The cache can also be bypassed by using the `cache` option. | ||
| #### `defaults` | ||
@@ -126,2 +145,3 @@ | ||
| #### `noConflict()` | ||
| Returns `phony` in a no-conflict state, reallocating the `phony` global variable name to its previous owner, where | ||
@@ -142,2 +162,3 @@ possible. | ||
| #### `VERSION` | ||
| The current version of `phony`. | ||
@@ -147,3 +168,3 @@ | ||
| phony.VERSION; | ||
| //=> "1.2.0" | ||
| //=> "1.2.1" | ||
| ``` | ||
@@ -173,4 +194,4 @@ | ||
| [3]: https://en.wikipedia.org/wiki/NATO_phonetic_alphabet | ||
| [4]: https://gemnasium.com/neocotic/phony.js | ||
| [5]: http://gruntjs.com | ||
| [4]: https://david-dm.org/neocotic/phony.js | ||
| [5]: https://github.com/neocotic/phony.js | ||
| [6]: https://github.com/neocotic/phony.js/issues | ||
@@ -180,3 +201,2 @@ [7]: https://github.com/neocotic/phony.js/blob/master/AUTHORS.md | ||
| [9]: https://github.com/neocotic/phony.js/blob/master/LICENSE.md | ||
| [10]: https://codeclimate.com/github/neocotic/phony.js | ||
| [11]: https://codeclimate.com/github/neocotic/phony.js/coverage | ||
| [10]: https://coveralls.io/r/neocotic/phony.js |
| languages: | ||
| JavaScript: true |
-454
| /** | ||
| * Library for translating to/from the phonetic alphabet. | ||
| * | ||
| * @module phony | ||
| * @version 1.2.0 | ||
| * @copyright Alasdair Mercer 2015 | ||
| * @license MIT | ||
| */ | ||
| (function(factory) { | ||
| 'use strict'; | ||
| /** | ||
| * The root object that has been determined for the current environment (browser, server, <code>WebWorker</code>). | ||
| * | ||
| * @access private | ||
| * @type {*} | ||
| */ | ||
| var root = (typeof self === 'object' && self.self === self && self) || | ||
| (typeof global === 'object' && global.global === global && global); | ||
| if (typeof define === 'function' && define.amd) { | ||
| // Defines for AMD but also exports to root for those expecting global phony | ||
| define(function() { | ||
| root.phony = factory(root); | ||
| return root.phony; | ||
| }); | ||
| } else if (typeof module !== 'undefined' && module.exports) { | ||
| // Supports Node.js and the CommonJS patterns | ||
| exports = module.exports = factory(root); | ||
| } else { | ||
| // Falls back on browser support | ||
| root.phony = factory(root); | ||
| } | ||
| }(function(root) { | ||
| 'use strict'; | ||
| /** | ||
| * A phonetic alphabet configuration. | ||
| * | ||
| * @typedef {Object} PhoneticAlphabet | ||
| * @property {Object.<String, String>} characters - The map of characters and their phonetic counterparts. | ||
| * @property {String} [fallback] - The name of the fallback alphabet. | ||
| */ | ||
| /** | ||
| * Options to be passed to the primary {@linkcode phony} methods. | ||
| * | ||
| * @typedef {Object} PhonyOptions | ||
| * @property {String} [alphabet="itu"] - The default name of the alphabet to be used for the translation. | ||
| * @property {String} [letterSplitter=" "] - The default string to be used to split alphabetic letters (may be passed | ||
| * to <code>RegExp</code> constructor). | ||
| * @property {String} [wordSplitter="space"] - The default string to be used to split words (may be passed to | ||
| * <code>RegExp</code> constructor). | ||
| */ | ||
| /** | ||
| * The main <code>phony</code> object to be exported. | ||
| * | ||
| * @access public | ||
| * @type {Object} | ||
| * @alias module:phony | ||
| */ | ||
| var phony = {}; | ||
| /** | ||
| * The previous value of the <code>phony</code> variable. | ||
| * | ||
| * @access private | ||
| * @type {*} | ||
| */ | ||
| var previousPhony = root.phony; | ||
| /** | ||
| * Iterates over a given <code>object</code>. | ||
| * <p/> | ||
| * If <code>object</code> is an array, each element is yielded in turn to the specified <code>iterator</code> | ||
| * function; otherwise this is done for the key/value mapping of the hash. | ||
| * | ||
| * @param {Array|Object} [object] - the object or array to be iterated over | ||
| * @param {Function} iterator - the iterator function to be passed index/element if <code>object</code> is an array | ||
| * or key/value if it is a hash | ||
| * @returns {Array|Object} The specified <code>object</code>. | ||
| * @access private | ||
| */ | ||
| function each(object, iterator) { | ||
| if (!object) { | ||
| return object; | ||
| } | ||
| var key; | ||
| var index; | ||
| var length = object.length; | ||
| if (length === +length) { | ||
| for (index = 0; index < length; index++) { | ||
| iterator(object[index], index, object); | ||
| } | ||
| } else { | ||
| for (key in object) { | ||
| if (object.hasOwnProperty(key)) { | ||
| iterator(key, object[key], object); | ||
| } | ||
| } | ||
| } | ||
| return object; | ||
| } | ||
| /** | ||
| * Returns the character mapped to the specified <code>phonetic</code> from the alphabet with the given | ||
| * <code>name</code>, where possible. | ||
| * <p/> | ||
| * If the named alphabet does not contain a mapping for <code>phonetic</code> but has a fallback alphabet configured, | ||
| * then that alphabet will be checked. | ||
| * | ||
| * @param {String} name - the name of the alphabet | ||
| * @param {String} phonetic - the phonetic string whose alphabet character mapping is to be returned | ||
| * @returns {String} The character mapped to <code>phonetic</code> for the named alphabet or it's configured | ||
| * fallback. | ||
| * @access private | ||
| */ | ||
| function getAlphabetCharacter(name, phonetic) { | ||
| var alphabet = phony.alphabets[name]; | ||
| var character; | ||
| if (alphabet) { | ||
| each(alphabet.characters, function(ch, ph) { | ||
| if (ph === phonetic) { | ||
| character = ch; | ||
| } | ||
| }); | ||
| if (typeof character === 'undefined' && typeof alphabet.fallback !== 'undefined') { | ||
| character = getAlphabetCharacter(alphabet.fallback, phonetic); | ||
| } | ||
| } | ||
| return character; | ||
| } | ||
| /** | ||
| * Returns the phonetic mapped to the specified <code>character</code> from the alphabet with the given | ||
| * <code>name</code>, where possible. | ||
| * <p/> | ||
| * If the named alphabet does not contain a mapping for <code>character</code> but has a fallback alphabet | ||
| * configured, then that alphabet will be checked. | ||
| * | ||
| * @param {String} name - the name of the alphabet | ||
| * @param {String} character - the character whose alphabet phonetic mapping is to be returned | ||
| * @returns {String} The phonetic mapped to <code>character</code> for the named alphabet or it's configured | ||
| * fallback. | ||
| * @access private | ||
| */ | ||
| function getAlphabetPhonetic(name, character) { | ||
| var alphabet = phony.alphabets[name]; | ||
| var phonetic = alphabet.characters && alphabet.characters[character]; | ||
| if (typeof phonetic === 'undefined' && alphabet && typeof alphabet.fallback !== 'undefined') { | ||
| phonetic = getAlphabetPhonetic(alphabet.fallback, character); | ||
| } | ||
| return phonetic; | ||
| } | ||
| /** | ||
| * Returns the given <code>options</code> with all of the <code>defaults</code> applied. | ||
| * <p/> | ||
| * This function <i>will change</i> the specified <code>options</code>. | ||
| * | ||
| * @param {PhonyOptions} [options={}] - the options to be extended | ||
| * @param {PhonyOptions} defaults - the default options | ||
| * @returns {PhonyOptions} The specified <code>options</code> with modifications. | ||
| * @access private | ||
| */ | ||
| function getOptions(options, defaults) { | ||
| options = options || {}; | ||
| for (var key in defaults) { | ||
| if (typeof options[key] === 'undefined') { | ||
| options[key] = defaults[key]; | ||
| } | ||
| } | ||
| options.alphabet = options.alphabet.toLocaleLowerCase(); | ||
| options.wordSplitter = options.wordSplitter.toLocaleLowerCase(); | ||
| return options; | ||
| } | ||
| /** | ||
| * Prepares a given string to simplify translation. | ||
| * | ||
| * @param {String} str - the string to prepare | ||
| * @param {String} [transformer] - the name of a <code>String.prototype</code> method to be used to transform | ||
| * <code>str</code> prior to preparation | ||
| * @param {String} wordSplitter - the string used to split words (will be passed to <code>RegExp</code> constructor) | ||
| * @param {String} letterSplitter - the string used to split alphabetic letters | ||
| * @returns {Array.<Array.<String>>} A multi-dimensional array of words and their alphabetic letters contained | ||
| * within. | ||
| * @access private | ||
| */ | ||
| function prepare(str, transformer, wordSplitter, letterSplitter) { | ||
| if (typeof str !== 'string') { | ||
| throw new TypeError('Invalid value type: ' + typeof str); | ||
| } | ||
| if (transformer && typeof str[transformer] === 'function') { | ||
| str = str[transformer](); | ||
| } | ||
| var rWordSplitter = new RegExp(wordSplitter + '|[\\n\\r]+', 'gi'); | ||
| var result = str.trim().split(rWordSplitter); | ||
| each(result, function(word, i) { | ||
| result[i] = word.split(letterSplitter); | ||
| }); | ||
| return result; | ||
| } | ||
| /** | ||
| * Transforms a given string in to title case. | ||
| * | ||
| * @param {String} str - the string to be transformed | ||
| * @returns {String} <code>str</code> in title case form. | ||
| * @access private | ||
| */ | ||
| function toTitleCase(str) { | ||
| return str[0].toLocaleUpperCase() + str.substring(1).toLocaleLowerCase(); | ||
| } | ||
| /** | ||
| * The current version of {@linkcode phony}. | ||
| * | ||
| * @access public | ||
| * @static | ||
| * @constant | ||
| * @type {String} | ||
| */ | ||
| phony.VERSION = '1.2.0'; | ||
| /** | ||
| * The configurations for the initially supported phonetic alphabets. | ||
| * | ||
| * @access public | ||
| * @static | ||
| * @type {Object.<String, PhoneticAlphabet>} | ||
| * @property {PhoneticAlphabet} ansi - The American National Standards Institute (ANSI) phonetic alphabet | ||
| * configuration. | ||
| * @property {PhoneticAlphabet} faa - The Federal Aviation Administration (FAA) phonetic alphabet configuration. | ||
| * @property {PhoneticAlphabet} icao - The International Civil Aviation Organization (ICAO) phonetic alphabet | ||
| * configuration. | ||
| * @property {PhoneticAlphabet} itu - The International Telecommunication Union (ITU) phonetic alphabet | ||
| * configuration. | ||
| */ | ||
| phony.alphabets = { | ||
| ansi: { | ||
| fallback: 'itu', | ||
| characters: { | ||
| 'A': 'alpha', | ||
| 'J': 'juliet' | ||
| } | ||
| }, | ||
| faa: { | ||
| fallback: 'itu', | ||
| characters: { | ||
| '0': 'zero', | ||
| '1': 'one', | ||
| '2': 'two', | ||
| '3': 'three', | ||
| '4': 'four', | ||
| '5': 'five', | ||
| '6': 'six', | ||
| '7': 'seven', | ||
| '8': 'eight', | ||
| '9': 'nine' | ||
| } | ||
| }, | ||
| icao: { | ||
| fallback: 'faa', | ||
| characters: { | ||
| '9': 'niner' | ||
| } | ||
| }, | ||
| itu: { | ||
| characters: { | ||
| 'A': 'alfa', | ||
| 'B': 'bravo', | ||
| 'C': 'charlie', | ||
| 'D': 'delta', | ||
| 'E': 'echo', | ||
| 'F': 'foxtrot', | ||
| 'G': 'golf', | ||
| 'H': 'hotel', | ||
| 'I': 'india', | ||
| 'J': 'juliett', | ||
| 'K': 'kilo', | ||
| 'L': 'lima', | ||
| 'M': 'mike', | ||
| 'N': 'november', | ||
| 'O': 'oscar', | ||
| 'P': 'papa', | ||
| 'Q': 'quebec', | ||
| 'R': 'romeo', | ||
| 'S': 'sierra', | ||
| 'T': 'tango', | ||
| 'U': 'uniform', | ||
| 'V': 'victor', | ||
| 'W': 'whiskey', | ||
| 'X': 'x-ray', | ||
| 'Y': 'yankee', | ||
| 'Z': 'zulu', | ||
| '0': 'nadazero', | ||
| '1': 'unaone', | ||
| '2': 'bissotwo', | ||
| '3': 'terrathree', | ||
| '4': 'kartefour', | ||
| '5': 'pantafive', | ||
| '6': 'soxisix', | ||
| '7': 'setteseven', | ||
| '8': 'oktoeight', | ||
| '9': 'novenine', | ||
| '.': 'stop', | ||
| '-': 'dash' | ||
| } | ||
| } | ||
| }; | ||
| /** | ||
| * The default values to be used when options are not specified or incomplete. | ||
| * | ||
| * @access public | ||
| * @static | ||
| * @type {PhonyOptions} | ||
| */ | ||
| phony.defaults = { | ||
| alphabet: 'itu', | ||
| letterSplitter: ' ', | ||
| wordSplitter: 'space' | ||
| }; | ||
| /** | ||
| * Translates the <code>message</code> provided <i>from</i> the phonetic alphabet. | ||
| * <p/> | ||
| * The message may not be translated correctly if the some of the options used to translate the message originally | ||
| * are not the same as those in <code>options</code>. | ||
| * | ||
| * @param {String} [message=""] - the string to be translated from the phonetic alphabet | ||
| * @param {PhonyOptions} [options={}] - the options to be used | ||
| * @returns {String} The translation from the specified phonetic alphabet <code>message</code>. | ||
| * @access public | ||
| * @static | ||
| */ | ||
| phony.from = function(message, options) { | ||
| message = message || ''; | ||
| options = getOptions(options, phony.defaults); | ||
| var result = ''; | ||
| var value = prepare(message, 'toLocaleLowerCase', options.wordSplitter, options.letterSplitter); | ||
| // Ensures message was prepared successfully and that a valid alphabet was specified | ||
| if (!value || !phony.alphabets[options.alphabet]) { | ||
| return result; | ||
| } | ||
| // Iterates over each word | ||
| each(value, function(word, i) { | ||
| // Inserts space between each word | ||
| if (i > 0) { | ||
| result += ' '; | ||
| } | ||
| // Iterates over each phonetic representation in the word | ||
| each(word, function(phonetic) { | ||
| // Reverse engineers character from phonetic representation | ||
| var character = getAlphabetCharacter(options.alphabet, phonetic); | ||
| // Checks if character is supported | ||
| if (typeof character === 'string') { | ||
| result += character; | ||
| } | ||
| }); | ||
| }); | ||
| return result; | ||
| }; | ||
| /** | ||
| * Translates the <code>message</code> provided <i>to</i> the phonetic alphabet. | ||
| * | ||
| * @param {String} [message=""] - the string to be translated to the phonetic alphabet | ||
| * @param {PhonyOptions} [options={}] - the options to be used | ||
| * @returns {String} The phonetic alphabet translation of the specified <code>message</code>. | ||
| * @access public | ||
| * @static | ||
| */ | ||
| phony.to = function(message, options) { | ||
| message = message || ''; | ||
| options = getOptions(options, phony.defaults); | ||
| var letterSplitter = options.letterSplitter; | ||
| var result = ''; | ||
| var value = prepare(message, 'toLocaleUpperCase', '\\s+', ''); | ||
| var wordSplitter = letterSplitter + toTitleCase(options.wordSplitter) + letterSplitter; | ||
| // Ensures message was prepared successfully and that a valid alphabet was specified | ||
| if (!value || !phony.alphabets[options.alphabet]) { | ||
| return result; | ||
| } | ||
| // Iterates over each word | ||
| each(value, function(word, i) { | ||
| // Inserts wordSplitter option between each word | ||
| if (i > 0) { | ||
| result += wordSplitter; | ||
| } | ||
| // Iterates over each character in the word | ||
| each(word, function(character, j) { | ||
| // Reverse engineers character from phonetic representation | ||
| var phonetic = getAlphabetPhonetic(options.alphabet, character); | ||
| // Checks if phonetic representation is supported | ||
| if (typeof phonetic === 'string') { | ||
| // Inserts letterSplitter option between each character | ||
| if (j > 0) { | ||
| result += letterSplitter; | ||
| } | ||
| result += toTitleCase(phonetic); | ||
| } | ||
| }); | ||
| }); | ||
| return result; | ||
| }; | ||
| /** | ||
| * Runs phony in <i>no conflict</i> mode, returning the <code>phony</code> global variable to it's previous owner, if | ||
| * any. | ||
| * | ||
| * @returns {Object} A reference to this {@linkcode phony}. | ||
| * @access public | ||
| * @static | ||
| */ | ||
| phony.noConflict = function() { | ||
| root.phony = previousPhony; | ||
| return this; | ||
| }; | ||
| return phony; | ||
| })); |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
155418
1.69%1944
1.36%195
11.43%0
-100%15
-6.25%2
100%