├── .gitignore ├── LICENSE ├── README.md ├── bin └── morse.js ├── map.js ├── morse.js ├── package.json ├── test ├── array.js ├── basic.js └── dichotomic.js └── tree.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Cam Pedersen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #morse 2 | 3 | A simple Morse code library for node 4 | 5 | ![Samuel F.B. Morse](http://i.imgur.com/HHHTQ.jpg) 6 | 7 | ## install 8 | 9 | For use as a CLI: 10 | 11 | npm install -g morse 12 | 13 | For use as a library: 14 | 15 | npm install morse 16 | 17 | ## example usage as a CLI 18 | 19 | ```` 20 | $ morse -h 21 | Usage: morse [options] string 22 | 23 | Options: 24 | -d, --decode Decode a string of Morse code [boolean] 25 | -h, --help Show this text 26 | 27 | $ morse hello > hello.txt 28 | $ morse -d "`cat hello.txt`" 29 | HELLO 30 | ```` 31 | 32 | ## example usage as a library 33 | 34 | ````javascript 35 | var morse = require('morse'); 36 | 37 | var encoded = morse.encode('Hello, world.'); 38 | // .... . .-.. .-.. --- --..-- ....... .-- --- .-. .-.. -.. .-.-.- 39 | 40 | morse.decode(encoded); 41 | // HELLO, WORLD. 42 | ```` 43 | 44 | ````javascript 45 | var encoded = morse.encode([ 'hello', 'world' ]); 46 | // [ '.... . .-.. .-.. ---', '.-- --- .-. .-.. -..' ] 47 | 48 | morse.decode(encoded); 49 | // [ 'HELLO', 'WORLD' ] 50 | ```` 51 | 52 | ## methods 53 | 54 | ### morse.encode(obj) 55 | 56 | Encodes and returns a given string or array 57 | 58 | ### morse.decode(obj, dichotomic) 59 | 60 | Decodes and returns a string or array 61 | 62 | `dichotomic` defaults to false. If passed true, it will use a tree-based approach to decode the string or array. If false, a basic iteration of the map is used. 63 | 64 | The dichotomic approach looks like this: 65 | 66 | ![](http://i.imgur.com/Y1bnV.png) 67 | 68 | The implementation does not include spaces right now, so it fails its test. However, it is otherwise accurate. 69 | 70 | ````javascript 71 | morse.decode( 72 | morse.encode('Hello, world.'), 73 | true 74 | ); 75 | // HELLO,5WORLD. 76 | ```` 77 | 78 | ## attributes 79 | 80 | ### morse.map 81 | 82 | An object containing `letter: morse` translations contained in `map.js` 83 | 84 | ### morse.tree 85 | 86 | A tree-modeled object contained in `tree.js` 87 | 88 | ## license 89 | 90 | MIT 91 | -------------------------------------------------------------------------------- /bin/morse.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var morse = require('../'); 3 | var optimist = require('optimist'); 4 | var argv = optimist 5 | .usage('Usage: $0 [options] string') 6 | .boolean('d') 7 | .alias('d', 'decode') 8 | .describe('d', 'Decode a string of Morse code') 9 | .alias('h', 'help') 10 | .describe('h', 'Show this text') 11 | .argv; 12 | 13 | if (argv.h || !argv._.length) { 14 | optimist.showHelp(); 15 | process.exit(); 16 | } 17 | 18 | var str = argv._.join(' '); 19 | if (argv.d) { 20 | console.log(morse.decode(str)); 21 | } else { 22 | console.log(morse.encode(str)); 23 | } 24 | -------------------------------------------------------------------------------- /map.js: -------------------------------------------------------------------------------- 1 | // copied from http://freenet.msp.mn.us/people/calguire/morse.html 2 | module.exports = { 3 | 'A': '.-', 4 | 'B': '-...', 5 | 'C': '-.-.', 6 | 'D': '-..', 7 | 'E': '.', 8 | 'F': '..-.', 9 | 'G': '--.', 10 | 'H': '....', 11 | 'I': '..', 12 | 'J': '.---', 13 | 'K': '-.-', 14 | 'L': '.-..', 15 | 'M': '--', 16 | 'N': '-.', 17 | 'O': '---', 18 | 'P': '.--.', 19 | 'Q': '--.-', 20 | 'R': '.-.', 21 | 'S': '...', 22 | 'T': '-', 23 | 'U': '..-', 24 | 'V': '...-', 25 | 'W': '.--', 26 | 'X': '-..-', 27 | 'Y': '-.--', 28 | 'Z': '--..', 29 | 'Á': '.--.-', // A with acute accent 30 | 'Ä': '.-.-', // A with diaeresis 31 | 'É': '..-..', // E with acute accent 32 | 'Ñ': '--.--', // N with tilde 33 | 'Ö': '---.', // O with diaeresis 34 | 'Ü': '..--', // U with diaeresis 35 | '1': '.----', 36 | '2': '..---', 37 | '3': '...--', 38 | '4': '....-', 39 | '5': '.....', 40 | '6': '-....', 41 | '7': '--...', 42 | '8': '---..', 43 | '9': '----.', 44 | '0': '-----', 45 | ',': '--..--', // comma 46 | '.': '.-.-.-', // period 47 | '?': '..--..', // question mark 48 | ';': '-.-.-', // semicolon 49 | ':': '---...', // colon 50 | '/': '-..-.', // slash 51 | '-': '-....-', // dash 52 | "'": '.----.', // apostrophe 53 | '()': '-.--.-', // parenthesis 54 | '_': '..--.-', // underline 55 | '@': '.--.-.', // at symbol from http://www.learnmorsecode.com/ 56 | ' ': '.......' 57 | }; 58 | -------------------------------------------------------------------------------- /morse.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | encode: encode, 3 | decode: decode, 4 | map: map, 5 | tree: tree 6 | }; 7 | 8 | var map = require('./map'); 9 | var tree = require('./tree'); 10 | 11 | function encode (obj) { 12 | return maybeRecurse(obj, encodeMorseString); 13 | 14 | function encodeMorseString (str) { 15 | var ret = str.split(''); 16 | for (var j in ret) { 17 | ret[j] = map[ret[j].toUpperCase()] || '?'; 18 | } 19 | return ret.join(' '); 20 | } 21 | } 22 | 23 | function decode (obj, dichotomic) { 24 | return maybeRecurse(obj, decodeMorseString); 25 | 26 | function decodeMorseString (str) { 27 | var ret = str.split(' '); 28 | for (var i in ret) { 29 | if (!dichotomic) { 30 | ret[i] = decodeCharacterByMap(ret[i]); 31 | } else { 32 | ret[i] = decodeCharacterByDichotomy(ret[i]); 33 | } 34 | } 35 | return ret.join(''); 36 | } 37 | } 38 | 39 | function maybeRecurse (obj, func) { 40 | if (!obj.pop) { 41 | return func(obj); 42 | } 43 | 44 | var clone = []; 45 | var i = 0; 46 | for (; i < obj.length; i++) { 47 | clone[i] = func(obj[i]); 48 | } 49 | return clone; 50 | } 51 | 52 | function decodeCharacterByMap (char) { 53 | for (var i in map) { 54 | if (map[i] == char) { 55 | return i; 56 | } 57 | } 58 | return ' '; 59 | } 60 | 61 | function decodeCharacterByDichotomy (char) { 62 | var sub = char.split(''); 63 | return traverseNodeWithCharacters(tree, sub); 64 | 65 | function traverseNodeWithCharacters (node, chars) { 66 | var cur = chars.shift(); 67 | if (!node[cur]) { 68 | return node.stop || '?'; 69 | } 70 | return traverseNodeWithCharacters(node[cur], chars); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Cam Pedersen (http://campedersen.com/)", 3 | "name": "morse", 4 | "description": "Morse code for mad scientists", 5 | "version": "0.1.0", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/ecto/morse.git" 9 | }, 10 | "bin": { 11 | "morse": "bin/morse.js" 12 | }, 13 | "main": "morse.js", 14 | "dependencies": { 15 | "optimist": "*" 16 | }, 17 | "devDependencies": {}, 18 | "optionalDependencies": {}, 19 | "engines": { 20 | "node": "*" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/array.js: -------------------------------------------------------------------------------- 1 | var morse = require('../'); 2 | 3 | var arr = [ 4 | 'hello', 5 | 'world' 6 | ]; 7 | console.log(arr); 8 | 9 | var encoded = morse.encode(arr); 10 | console.log(encoded); 11 | 12 | var decoded = morse.decode(encoded); 13 | console.log(decoded); 14 | 15 | var expected = [ 16 | 'HELLO', 17 | 'WORLD' 18 | ]; 19 | 20 | console.log(expected[1] == decoded[1] ? 'pass' : 'fail'); 21 | -------------------------------------------------------------------------------- /test/basic.js: -------------------------------------------------------------------------------- 1 | var morse = require('../'); 2 | 3 | var str = 'Hello, world.'; 4 | console.log(str); 5 | 6 | var encoded = morse.encode(str); 7 | console.log(encoded); 8 | 9 | var decoded = morse.decode(encoded); 10 | console.log(decoded); 11 | 12 | console.log(str.toUpperCase() == decoded ? 'pass' : 'fail'); 13 | -------------------------------------------------------------------------------- /test/dichotomic.js: -------------------------------------------------------------------------------- 1 | var morse = require('../'); 2 | 3 | var str = 'Hello, world.'; 4 | console.log(str); 5 | 6 | var encoded = morse.encode(str); 7 | console.log(encoded); 8 | 9 | var decoded = morse.decode(encoded, true); 10 | console.log(decoded); 11 | 12 | console.log(str.toUpperCase() == decoded ? 'pass' : 'fail'); 13 | -------------------------------------------------------------------------------- /tree.js: -------------------------------------------------------------------------------- 1 | // might be the dumbest idea I've ever had 2 | module.exports = { 3 | '.': { 4 | stop: 'E', 5 | '.': { 6 | stop: 'I', 7 | '.': { 8 | stop: 'S', 9 | '.': { 10 | stop: 'H', 11 | '.': { 12 | stop: '5' 13 | }, 14 | '-': { 15 | stop: '4' 16 | } 17 | }, 18 | '-': { 19 | stop: 'V', 20 | '.': { 21 | stop: 'Ś' 22 | }, 23 | '-': { 24 | stop: '3' 25 | } 26 | } 27 | }, 28 | '-': { 29 | stop: 'U', 30 | '.': { 31 | stop: 'F', 32 | // note lack of - 33 | '.': { 34 | stop: 'É' 35 | } 36 | }, 37 | '_': { 38 | stop: 'Ü', 39 | '.': { 40 | stop: 'Ð', 41 | '.': { 42 | stop: '?' 43 | }, 44 | '-': { 45 | stop: '_' 46 | } 47 | }, 48 | '-': { 49 | stop: '2' 50 | } 51 | } 52 | } 53 | }, 54 | '-': { 55 | stop: 'A', 56 | '.': { 57 | stop: 'R', 58 | '.': { 59 | stop: 'L', 60 | // note lack of . 61 | '-': { 62 | stop: 'È', 63 | '.': { 64 | stop: '"' 65 | } 66 | } 67 | }, 68 | '-': { 69 | stop: 'Ä', 70 | // note lack of - 71 | '.': { 72 | stop: '+', 73 | // note lack of . 74 | '-': { 75 | stop: '.' 76 | } 77 | } 78 | } 79 | }, 80 | '-': { 81 | stop: 'W', 82 | '.': { 83 | stop: 'P', 84 | // '.': {}, 85 | // TODO can't replicate character -_- 86 | '-': { 87 | stop: 'À', 88 | // note lack of - 89 | '.': { 90 | stop: '@' 91 | } 92 | } 93 | }, 94 | '-': { 95 | stop: 'J', 96 | '.': { 97 | stop: 'Ĵ' 98 | }, 99 | '-': { 100 | stop: '1', 101 | // note lack of - 102 | '.': { 103 | stop: "'" 104 | } 105 | } 106 | } 107 | } 108 | } 109 | }, 110 | '-': { 111 | stop: 'T', 112 | '.': { 113 | stop: 'N', 114 | '.': { 115 | stop: 'D', 116 | '.': { 117 | stop: 'B', 118 | '.': { 119 | stop: '6', 120 | // notive lack of . 121 | '-': { 122 | stop: '-' 123 | } 124 | }, 125 | '-': { 126 | stop: '=' 127 | } 128 | }, 129 | '-': { 130 | stop: 'X', 131 | // notice lack of - 132 | '.': { 133 | stop: '/' 134 | } 135 | } 136 | }, 137 | '-': { 138 | stop: 'K', 139 | '.': { 140 | stop: 'C', 141 | '.': { 142 | stop: 'Ç' 143 | }, 144 | '-': { 145 | // notice lack of stop 146 | '.': { 147 | stop: ';' 148 | }, 149 | '-': { 150 | stop: '!' 151 | } 152 | } 153 | }, 154 | '-': { 155 | stop: 'Y', 156 | // notice lack of - 157 | '.': { 158 | stop: 'Ĥ', 159 | // notice lack of . 160 | '-': { 161 | stop: '()' 162 | } 163 | } 164 | } 165 | } 166 | }, 167 | '-': { 168 | stop: 'M', 169 | '.': { 170 | stop: 'G', 171 | '.': { 172 | stop: 'Z', 173 | '.': { 174 | stop: '7' 175 | }, 176 | '-': { 177 | // note lack of stop 178 | // note lack of . 179 | '-': { 180 | stop: ',' 181 | } 182 | } 183 | }, 184 | '-': { 185 | stop: 'Q', 186 | '.': { 187 | stop: 'Ĝ' 188 | }, 189 | '-': { 190 | stop: 'Ñ' 191 | } 192 | } 193 | }, 194 | '-': { 195 | stop: 'O', 196 | '.': { 197 | stop: 'Ö', 198 | // note lack of - 199 | '.': { 200 | stop: '8', 201 | // note lack of - 202 | '.': { 203 | stop: ':' 204 | } 205 | } 206 | }, 207 | '-': { 208 | stop: 'CH', // is there a digraph for this? 209 | '.': { 210 | stop: '9' 211 | }, 212 | '-': { 213 | stop: '0' 214 | } 215 | } 216 | } 217 | } 218 | } 219 | }; 220 | --------------------------------------------------------------------------------