[
  {
    "path": ".gitignore",
    "content": "TODO.txt\nnode_modules/\n"
  },
  {
    "path": ".npmignore",
    "content": ""
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014 Gabriel Martin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# Hipku\n\nA tiny javascript library to encode IPv6 and IPv4 addresses as haiku.\n\nFor full documentation and a working demo, check out https://gabrielbrady.com/projects/hipku\n\n## Installation\n\nInstall with `npm install hipku`. `index.js` can also be used directly in the browser.\n\n## Usage\n\nTo encode `127.0.0.1` or `::1` call `Hipku.encode('127.0.0.1')` or `Hipku.encode('::1')`. IPv4 addresses must have octets separated by a `.` period character and IPv6 addresses must have hextets separated by a `:` colon character.\n\nWhen decoding a hipku, such as:\n\n    The weary red dove\n    fights in the empty tundra.\n    Jasmine petals dance.\n\nthe lines can be separated either by the newline character `\\n` or by a space. Both will produce the same result.\n\n    Hipku.decode('The weary red dove\\nfights in the empty tundra.\\nJasmine petals dance.');\n\n    > \"254.53.93.114\"\n\n    Hipku.decode('The weary red dove fights in the empty tundra. Jasmine petals dance.');\n\n    > \"254.53.93.114\"\n\n### Node.js\n\n    var hipku = require('hipku');\n\n    hipku.encode('127.0.0.1');\n\n    hipku.decode('The weary red dove fights in the empty tundra. Jasmine petals dance.');\n"
  },
  {
    "path": "index.js",
    "content": "/*\n** Hipku version 0.0.2\n** Copyright (c) Gabriel Martin 2014\n** All rights reserved\n** Available under the MIT license\n** http://gabrielmartin.net/projects/hipku\n*/\n;\nvar Hipku = (function() {\n/*\n** ##############\n** Public Methods\n** ##############\n*/\n\n/*\n** Object holds all public methods and is returned by the module\n*/\nvar publicMethods = {};\n\n/*\n** Public method to encode IP Addresses as haiku\n*/\nvar encode = function(ip) {\n  var ipv6, decimalOctetArray, factoredOctetArray, encodedWordArray,\n    haikuText;\n\n  ipv6 = ipIsIpv6(ip);\n  decimalOctetArray = splitIp(ip, ipv6);\n  factoredOctetArray = factorOctets(decimalOctetArray, ipv6);\n  encodedWordArray = encodeWords(factoredOctetArray, ipv6);\n  haikuText = writeHaiku(encodedWordArray, ipv6);\n\n  return haikuText;\n};\n\n/*\n** Public method to decode haiku into IP Addresses\n*/\nvar decode = function(haiku) {\n  var wordArray, ipv6, factorArray, octetArray, ipString;\n\n  wordArray = splitHaiku(haiku);\n  ipv6 = haikuIsIpv6(wordArray);\n  factorArray = getFactors(wordArray, ipv6);\n  octetArray = getOctets(factorArray, ipv6);\n  ipString = getIpString(octetArray, ipv6);\n\n  return ipString;\n};\n\n/*\n** Attach the public methods to the return object\n*/\npublicMethods.encode = encode;\npublicMethods.decode = decode;\n\n/*\n** #############################\n** Helper functions for encoding\n** #############################\n*/\n\nfunction ipIsIpv6(ip) {\n  if (ip.indexOf(':') != -1) { return true; }\n  else if (ip.indexOf('.') != -1) { return false; }\n  else {\n    throw new Error('Formatting error in IP Address input.' +\n      ' ' + 'Contains neither \":\" or \".\"');\n  }\n}\n\nfunction splitIp(ip, ipv6) {\n  var octetArray, separator, v6Base, numOctets, decimalOctetArray;\n\n  octetArray = [];\n  decimalOctetArray = [];\n  v6Base = 16;\n\n  if (ipv6) {\n    separator = ':';\n    numOctets = 8;\n  } else {\n    separator = '.';\n    numOctets = 4;\n  }\n\n  /*\n  ** Remove newline and space characters\n  */\n  ip = ip.replace(/[\\n\\ ]/g, '');\n  octetArray = ip.split(separator);\n\n  /*\n  ** If IPv6 address is in abbreviated format, we need to replace missing octets with 0\n  */\n  if (octetArray.length < numOctets) {\n    if (ipv6) {\n      var numMissingOctets = (numOctets - octetArray.length);\n\n      octetArray = padOctets(octetArray, numMissingOctets);\n    } else {\n      throw new Error('Formatting error in IP Address input.' +\n      ' ' + 'IPv4 address has fewer than 4 octets.');\n    }\n  }\n\n  /*\n  ** Conter IPv6 addresses from hex to decimal\n  */\n  if (ipv6) {\n    for (var i = 0; i < octetArray.length; i++) {\n      decimalOctetArray[i] = parseInt(octetArray[i], v6Base);\n    }\n  } else {\n    decimalOctetArray = octetArray;\n  }\n\n  return decimalOctetArray;\n}\n\n/*\n** If IPv6 is abbreviated, pad with appropriate number of 0 octets\n*/\nfunction padOctets(octetArray, numMissingOctets) {\n  var paddedOctet, aLength;\n\n  paddedOctet = 0;\n  aLength = octetArray.length;\n\n  /*\n  ** If the first or last octets are blank, zero them\n  */\n  if (octetArray[0] === '') {\n    octetArray[0] = paddedOctet;\n  }\n  if (octetArray[aLength - 1] === '') {\n    octetArray[aLength - 1] = paddedOctet;\n  }\n\n  /*\n  ** Check the rest of the array for blank octets and pad as needed\n  */\n  for (var i = 0; i < aLength; i++) {\n    if (octetArray[i] === '') {\n      octetArray[i] = paddedOctet;\n\n      for (var j = 0; j < numMissingOctets; j++) {\n        octetArray.splice(i, 0, paddedOctet);\n      }\n    }\n  }\n\n  return octetArray;\n}\n\n/*\n** Convert each decimal octet into a factor of the divisor (16 or 256)\n** and a remainder\n*/\nfunction factorOctets(octetArray, ipv6) {\n  var divisor, factoredOctetArray;\n\n  factoredOctetArray = [];\n\n  if (ipv6) {\n    divisor = 256;\n  } else {\n    divisor = 16;\n  }\n\n  for (var i = 0; i < octetArray.length; i++) {\n    var octetValue, factor1, factor2;\n\n    octetValue = octetArray[i];\n\n    factor1 = octetArray[i] % divisor;\n    octetValue = octetValue - factor1;\n    factor2 = octetValue / divisor;\n\n    factoredOctetArray.push(factor2);\n    factoredOctetArray.push(factor1);\n  }\n\n  return factoredOctetArray;\n}\n\nfunction encodeWords(factorArray, ipv6) {\n  var key, encodedWordArray;\n\n  encodedWordArray = [];\n  key = getKey(ipv6);\n\n  for (var i = 0; i < factorArray.length; i++) {\n    var dict;\n\n    dict = key[i];\n    encodedWordArray[i] = dict[factorArray[i]];\n  }\n\n  return encodedWordArray;\n}\n\n\n/*\n** Return an array of dictionaries representing the correct word\n** order for the haiku\n*/\nfunction getKey(ipv6) {\n  var key;\n\n  if (ipv6) {\n    key = [ adjectives,\n      nouns,\n      adjectives,\n      nouns,\n      verbs,\n      adjectives,\n      adjectives,\n      adjectives,\n      adjectives,\n      adjectives,\n      nouns,\n      adjectives,\n      nouns,\n      verbs,\n      adjectives,\n      nouns ];\n  } else {\n    key = [ animalAdjectives,\n      animalColors,\n      animalNouns,\n      animalVerbs,\n      natureAdjectives,\n      natureNouns,\n      plantNouns,\n      plantVerbs ];\n  }\n\n  return key;\n}\n\nfunction writeHaiku(wordArray, ipv6) {\n  var octet, schemaResults, schema, nonWords, haiku;\n\n  octet = 'OCTET'; // String to place in schema to show word slots\n  schemaResults = getSchema(ipv6, octet);\n  schema = schemaResults[0];\n  nonWords = schemaResults[1];\n\n  /*\n  ** Replace each instance of 'octet' in the schema with a word from\n  ** the encoded word array\n  */\n  for (var i = 0; i < wordArray.length; i++) {\n    for (var j = 0; j < schema.length; j++) {\n      if (schema[j] === octet) {\n        schema[j] = wordArray[i];\n        break;\n      }\n    }\n  }\n\n  /*\n  ** Capitalize appropriate words\n  */\n  schema = capitalizeHaiku(schema);\n  haiku = schema.join('');\n\n  return haiku;\n}\n\nfunction getSchema(ipv6, octet) {\n  var schema, newLine, period, space, nonWords;\n\n  schema = [];\n  newLine = '\\n';\n  period = '.';\n  space = ' ';\n  nonWords = [newLine, period, space];\n\n  if (ipv6) {\n      schema = [octet,\n      octet,\n      'and',\n      octet,\n      octet,\n      newLine,\n      octet,\n      octet,\n      octet,\n      octet,\n      octet,\n      octet,\n      octet,\n      period,\n      newLine,\n      octet,\n      octet,\n      octet,\n      octet,\n      octet,\n      period,\n      newLine];\n  } else {\n      schema = ['The',\n      octet,\n      octet,\n      octet,\n      newLine,\n      octet,\n      'in the',\n      octet,\n      octet,\n      period,\n      newLine,\n      octet,\n      octet,\n      period,\n      newLine];\n  }\n\n  /*\n  ** Add spaces before words except the first word\n  */\n  for (var i = 1; i < schema.length; i++) {\n      var insertSpace = true;\n\n      /*\n      ** If the next entry is a nonWord, don't add a space\n      */\n      for (var j = 0; j < nonWords.length; j++) {\n        if (schema[i] === nonWords[j]) {\n            insertSpace = false;\n        }\n      }\n\n      /*\n      ** If the previous entry is a newLine, don't add a space\n      */\n      if (schema[i - 1] === newLine) {\n          insertSpace = false;\n      }\n\n      if (insertSpace) {\n          schema.splice(i, 0, space);\n          i = i + 1;\n      }\n  }\n\n  return [schema, nonWords];\n}\n\nfunction capitalizeHaiku(haikuArray) {\n  var period = '.';\n\n  /*\n  ** Always capitalize the first word\n  */\n  haikuArray[0] = capitalizeWord(haikuArray[0]);\n\n  for (var i = 1; i < haikuArray.length; i++) {\n\n    if (haikuArray[i] === period && i + 2 < haikuArray.length) {\n      /*\n      ** If the current entry is a period then the next entry will be\n      ** a newLine or a space, so check two positions ahead and\n      ** capitalize that entry, so long as it's a word\n      */\n      haikuArray[i + 2] = capitalizeWord(haikuArray[i + 2]);\n    }\n  }\n\n  return haikuArray;\n}\n\nfunction capitalizeWord(word) {\n  word = word.substring(0,1).toUpperCase() +\n    word.substring(1, word.length);\n\n  return word;\n}\n\n/*\n** #############################\n** Helper functions for decoding\n** #############################\n*/\n\nfunction splitHaiku(haiku) {\n  var wordArray;\n\n  haiku = haiku.toLowerCase();\n\n  /*\n  ** Replace newline characters with spaces\n  */\n  haiku = haiku.replace(/\\n/g, ' ');\n\n  /*\n  ** Remove anything that's not a letter, a space or a dash\n  */\n  haiku = haiku.replace(/[^a-z\\ -]/g, '');\n  wordArray = haiku.split(' ');\n\n  /*\n  ** Remove any blank entries\n  */\n  for (var i = 0; i < wordArray.length; i++) {\n    if (wordArray[i] === '') {\n      wordArray.splice(i, 1);\n    }\n  }\n\n  return wordArray;\n}\n\nfunction haikuIsIpv6(wordArray) {\n  var ipv6, key, dict;\n\n  key = getKey(false);\n  dict = key[0];\n  ipv6 = true;\n\n  /*\n  ** Compare each word in the haiku against each word in the first\n  ** dictionary defined in the IPv4 key. If there's a match, the\n  ** current haiku is IPv4. If not, IPv6.\n  */\n  for (var i = 0; i < wordArray.length; i++) {\n    var currentWord = wordArray[i];\n\n    for (var j = 0; j < dict.length; j++) {\n      if (currentWord === dict[j]) {\n          ipv6 = false;\n          break;\n      }\n    }\n\n    if (ipv6 === false) {\n      break;\n    }\n  }\n\n  return ipv6;\n}\n\n/*\n** Return an array of factors and remainders for each encoded\n** octet-value\n*/\nfunction getFactors(wordArray, ipv6) {\n  var key, factorArray, wordArrayPosition;\n\n  key = getKey(ipv6);\n  factorArray = [];\n  wordArrayPosition = 0;\n\n  /*\n  ** Get the first dictionary from the key. Check the first entry in\n  ** the encoded word array to see if it's in that dictionary. If it\n  ** is, store the dictionary offset and move onto the next dictionary\n  ** and the next word in the encoded words array. If there isn't a\n  ** match, keep the same dictionary but check the next word in the\n  ** array. Keep going till we have an offset for each dictionary in\n  ** the key.\n  */\n  for (var i = 0; i < key.length; i++) {\n    var result, factor, newPosition;\n\n    result = [];\n    result = getFactorFromWord(key[i], key.length,\n                wordArray, wordArrayPosition);\n    factor = result[0];\n    newPosition = result[1];\n    wordArrayPosition = newPosition;\n\n    factorArray.push(factor);\n  }\n\n  return factorArray;\n}\n\nfunction getFactorFromWord(dict, maxLength, words, position) {\n  var factor = null;\n\n  for (var j = 0; j < dict.length; j++) {\n    var dictEntryLength, wordToCheck;\n\n    /*\n    ** Get the number of words in the dictionary entry\n    */\n    dictEntryLength = dict[j].split(' ').length;\n\n    /*\n    ** build a string to compare against the dictionary entry\n    ** by joining the appropriate number of wordArray entries\n    */\n    wordToCheck =\n      words.slice(position, position + dictEntryLength);\n    wordToCheck = wordToCheck.join(' ');\n\n    if (dict[j] === wordToCheck) {\n      factor = j;\n\n      /*\n      ** If the dictionary entry word count is greater than one,\n      ** increment the position counter by the difference to\n      ** avoid rechecking words we've already checkced\n      */\n      position = position + (dictEntryLength - 1);\n      break;\n    }\n  }\n\n  position = position + 1;\n\n  if (factor === null) {\n    if (position >= maxLength) {\n      /*\n      ** We've reached the entry of the haiku and still not matched\n      ** all necessary dictionaries, so throw an error\n      */\n      throw new Error('Decoding error: one or more dictionary words' +\n                       'missing from input haiku');\n    } else {\n      /*\n      ** Couldn't find the current word in the current dictionary,\n      ** try the next word\n      */\n      return getFactorFromWord(dict, maxLength, words, position);\n    }\n  } else {\n    /*\n    ** Found the word - return the dictionary offset and the new\n    ** word array position\n    */\n    return [factor, position];\n  }\n}\n\nfunction getOctets(factorArray, ipv6) {\n  var octetArray, multiplier;\n\n  octetArray = [];\n  if (ipv6) {\n    multiplier = 256;\n  } else {\n    multiplier = 16;\n  }\n\n  for (var i = 0; i < factorArray.length; i = i + 2) {\n    var factor1, factor2, octet;\n\n    factor1 = factorArray[i];\n    factor2 = factorArray[i + 1];\n    octet = (factor1 * multiplier) + factor2;\n\n    if (ipv6) {\n      octet = octet.toString(16);\n    }\n\n    octetArray.push(octet);\n  }\n\n  return octetArray;\n}\n\nfunction getIpString(octetArray, ipv6) {\n  var ipString, separator;\n\n  ipString = '';\n\n  if (ipv6) {\n    separator = ':';\n  } else {\n    separator = '.';\n  }\n\n  for (var i = 0; i < octetArray.length; i++) {\n    if (i > 0) {\n      ipString += separator;\n    }\n    ipString += octetArray[i];\n  }\n\n  return ipString;\n}\n\n/*\n** ############\n** Dictionaries\n** ############\n*/\n\nvar adjectives, nouns, verbs, animalAdjectives, animalColors,\nanimalNouns, animalVerbs, natureAdjectives, natureNouns,\nplantNouns, plantVerbs;\n\n/*\n** IPv4 dictionaries\n*/\n\nanimalAdjectives = ['agile',\n  'bashful',\n  'clever',\n  'clumsy',\n  'drowsy',\n  'fearful',\n  'graceful',\n  'hungry',\n  'lonely',\n  'morose',\n  'placid',\n  'ruthless',\n  'silent',\n  'thoughtful',\n  'vapid',\n  'weary'];\n\nanimalColors = ['beige',\n  'black',\n  'blue',\n  'bright',\n  'bronze',\n  'brown',\n  'dark',\n  'drab',\n  'green',\n  'gold',\n  'grey',\n  'jade',\n  'pale',\n  'pink',\n  'red',\n  'white'];\n\nanimalNouns = ['ape',\n  'bear',\n  'crow',\n  'dove',\n  'frog',\n  'goat',\n  'hawk',\n  'lamb',\n  'mouse',\n  'newt',\n  'owl',\n  'pig',\n  'rat',\n  'snake',\n  'toad',\n  'wolf'];\n\nanimalVerbs = ['aches',\n  'basks',\n  'cries',\n  'dives',\n  'eats',\n  'fights',\n  'groans',\n  'hunts',\n  'jumps',\n  'lies',\n  'prowls',\n  'runs',\n  'sleeps',\n  'thrives',\n  'wakes',\n  'yawns'];\n\nnatureAdjectives = ['ancient',\n  'barren',\n  'blazing',\n  'crowded',\n  'distant',\n  'empty',\n  'foggy',\n  'fragrant',\n  'frozen',\n  'moonlit',\n  'peaceful',\n  'quiet',\n  'rugged',\n  'serene',\n  'sunlit',\n  'wind-swept'];\n\nnatureNouns = ['canyon',\n  'clearing',\n  'desert',\n  'foothills',\n  'forest',\n  'grasslands',\n  'jungle',\n  'meadow',\n  'mountains',\n  'prairie',\n  'river',\n  'rockpool',\n  'sand-dune',\n  'tundra',\n  'valley',\n  'wetlands'];\n\nplantNouns = ['autumn colors',\n  'cherry blossoms',\n  'chrysanthemums',\n  'crabapple blooms',\n  'the dry palm fronds',\n  'fat horse chestnuts',\n  'forget-me-nots',\n  'jasmine petals',\n  'lotus flowers',\n  'ripe blackberries',\n  'the maple seeds',\n  'the pine needles',\n  'tiger lillies',\n  'water lillies',\n  'willow branches',\n  'yellowwood leaves'];\n\nplantVerbs = ['blow',\n  'crunch',\n  'dance',\n  'drift',\n  'drop',\n  'fall',\n  'grow',\n  'pile',\n  'rest',\n  'roll',\n  'show',\n  'spin',\n  'stir',\n  'sway',\n  'turn',\n  'twist'];\n\n/*\n** IPv6 dictionaries\n*/\n\nadjectives = ['ace',\n  'apt',\n  'arched',\n  'ash',\n  'bad',\n  'bare',\n  'beige',\n  'big',\n  'black',\n  'bland',\n  'bleak',\n  'blond',\n  'blue',\n  'blunt',\n  'blush',\n  'bold',\n  'bone',\n  'both',\n  'bound',\n  'brash',\n  'brass',\n  'brave',\n  'brief',\n  'brisk',\n  'broad',\n  'bronze',\n  'brushed',\n  'burned',\n  'calm',\n  'ceil',\n  'chaste',\n  'cheap',\n  'chilled',\n  'clean',\n  'coarse',\n  'cold',\n  'cool',\n  'corn',\n  'crass',\n  'crazed',\n  'cream',\n  'crisp',\n  'crude',\n  'cruel',\n  'cursed',\n  'cute',\n  'daft',\n  'damp',\n  'dark',\n  'dead',\n  'deaf',\n  'dear',\n  'deep',\n  'dense',\n  'dim',\n  'drab',\n  'dry',\n  'dull',\n  'faint',\n  'fair',\n  'fake',\n  'false',\n  'famed',\n  'far',\n  'fast',\n  'fat',\n  'fierce',\n  'fine',\n  'firm',\n  'flat',\n  'flawed',\n  'fond',\n  'foul',\n  'frail',\n  'free',\n  'fresh',\n  'full',\n  'fun',\n  'glum',\n  'good',\n  'grave',\n  'gray',\n  'great',\n  'green',\n  'grey',\n  'grim',\n  'gruff',\n  'hard',\n  'harsh',\n  'high',\n  'hoarse',\n  'hot',\n  'huge',\n  'hurt',\n  'ill',\n  'jade',\n  'jet',\n  'jinxed',\n  'keen',\n  'kind',\n  'lame',\n  'lank',\n  'large',\n  'last',\n  'late',\n  'lean',\n  'lewd',\n  'light',\n  'limp',\n  'live',\n  'loath',\n  'lone',\n  'long',\n  'loose',\n  'lost',\n  'louche',\n  'loud',\n  'low',\n  'lush',\n  'mad',\n  'male',\n  'masked',\n  'mean',\n  'meek',\n  'mild',\n  'mint',\n  'moist',\n  'mute',\n  'near',\n  'neat',\n  'new',\n  'nice',\n  'nude',\n  'numb',\n  'odd',\n  'old',\n  'pained',\n  'pale',\n  'peach',\n  'pear',\n  'peeved',\n  'pink',\n  'piqued',\n  'plain',\n  'plum',\n  'plump',\n  'plush',\n  'poor',\n  'posed',\n  'posh',\n  'prim',\n  'prime',\n  'prompt',\n  'prone',\n  'proud',\n  'prune',\n  'puce',\n  'pure',\n  'quaint',\n  'quartz',\n  'quick',\n  'rare',\n  'raw',\n  'real',\n  'red',\n  'rich',\n  'ripe',\n  'rough',\n  'rude',\n  'rushed',\n  'rust',\n  'sad',\n  'safe',\n  'sage',\n  'sane',\n  'scorched',\n  'shaped',\n  'sharp',\n  'sheared',\n  'short',\n  'shrewd',\n  'shrill',\n  'shrunk',\n  'shy',\n  'sick',\n  'skilled',\n  'slain',\n  'slick',\n  'slight',\n  'slim',\n  'slow',\n  'small',\n  'smart',\n  'smooth',\n  'smug',\n  'snide',\n  'snug',\n  'soft',\n  'sore',\n  'sought',\n  'sour',\n  'spare',\n  'sparse',\n  'spent',\n  'spoilt',\n  'spry',\n  'squat',\n  'staid',\n  'stale',\n  'stark',\n  'staunch',\n  'steep',\n  'stiff',\n  'strange',\n  'straw',\n  'stretched',\n  'strict',\n  'striped',\n  'strong',\n  'suave',\n  'sure',\n  'svelte',\n  'swank',\n  'sweet',\n  'swift',\n  'tall',\n  'tame',\n  'tan',\n  'tart',\n  'taut',\n  'teal',\n  'terse',\n  'thick',\n  'thin',\n  'tight',\n  'tiny',\n  'tired',\n  'toothed',\n  'torn',\n  'tough',\n  'trim',\n  'trussed',\n  'twin',\n  'used',\n  'vague',\n  'vain',\n  'vast',\n  'veiled',\n  'vexed',\n  'vile',\n  'warm',\n  'weak',\n  'webbed',\n  'wrong',\n  'wry',\n  'young'];\n\nnouns = ['ants',\n  'apes',\n  'asps',\n  'balls',\n  'barb',\n  'barbs',\n  'bass',\n  'bats',\n  'beads',\n  'beaks',\n  'bears',\n  'bees',\n  'bells',\n  'belts',\n  'birds',\n  'blades',\n  'blobs',\n  'blooms',\n  'boars',\n  'boats',\n  'bolts',\n  'books',\n  'bowls',\n  'boys',\n  'bream',\n  'brides',\n  'broods',\n  'brooms',\n  'brutes',\n  'bucks',\n  'bulbs',\n  'bulls',\n  'burls',\n  'cakes',\n  'calves',\n  'capes',\n  'cats',\n  'char',\n  'chests',\n  'choirs',\n  'clams',\n  'clans',\n  'clouds',\n  'clowns',\n  'cod',\n  'coins',\n  'colts',\n  'cones',\n  'cords',\n  'cows',\n  'crabs',\n  'cranes',\n  'crows',\n  'cults',\n  'czars',\n  'darts',\n  'dates',\n  'deer',\n  'dholes',\n  'dice',\n  'discs',\n  'does',\n  'dogs',\n  'doors',\n  'dopes',\n  'doves',\n  'drakes',\n  'dreams',\n  'drones',\n  'ducks',\n  'dunes',\n  'eels',\n  'eggs',\n  'elk',\n  'elks',\n  'elms',\n  'elves',\n  'ewes',\n  'eyes',\n  'faces',\n  'facts',\n  'fawns',\n  'feet',\n  'ferns',\n  'fish',\n  'fists',\n  'flames',\n  'fleas',\n  'flocks',\n  'flutes',\n  'foals',\n  'foes',\n  'fools',\n  'fowl',\n  'frogs',\n  'fruits',\n  'gangs',\n  'gar',\n  'geese',\n  'gems',\n  'germs',\n  'ghosts',\n  'gnomes',\n  'goats',\n  'grapes',\n  'grooms',\n  'grouse',\n  'grubs',\n  'guards',\n  'gulls',\n  'hands',\n  'hares',\n  'hawks',\n  'heads',\n  'hearts',\n  'hens',\n  'herbs',\n  'hills',\n  'hogs',\n  'holes',\n  'hordes',\n  'ide',\n  'jars',\n  'jays',\n  'kids',\n  'kings',\n  'kites',\n  'lads',\n  'lakes',\n  'lambs',\n  'larks',\n  'lice',\n  'lights',\n  'limbs',\n  'looms',\n  'loons',\n  'mares',\n  'masks',\n  'mice',\n  'mimes',\n  'minks',\n  'mists',\n  'mites',\n  'mobs',\n  'molds',\n  'moles',\n  'moons',\n  'moths',\n  'newts',\n  'nymphs',\n  'orbs',\n  'orcs',\n  'owls',\n  'pearls',\n  'pears',\n  'peas',\n  'perch',\n  'pigs',\n  'pikes',\n  'pines',\n  'plains',\n  'plants',\n  'plums',\n  'pools',\n  'prawns',\n  'prunes',\n  'pugs',\n  'punks',\n  'quail',\n  'quails',\n  'queens',\n  'quills',\n  'rafts',\n  'rains',\n  'rams',\n  'rats',\n  'rays',\n  'ribs',\n  'rocks',\n  'rooks',\n  'ruffs',\n  'runes',\n  'sands',\n  'seals',\n  'seas',\n  'seeds',\n  'serfs',\n  'shards',\n  'sharks',\n  'sheep',\n  'shells',\n  'ships',\n  'shoals',\n  'shrews',\n  'shrimp',\n  'skate',\n  'skies',\n  'skunks',\n  'sloths',\n  'slugs',\n  'smew',\n  'smiles',\n  'snails',\n  'snakes',\n  'snipes',\n  'sole',\n  'songs',\n  'spades',\n  'sprats',\n  'sprouts',\n  'squabs',\n  'squads',\n  'squares',\n  'squid',\n  'stars',\n  'stoats',\n  'stones',\n  'storks',\n  'strays',\n  'suns',\n  'swans',\n  'swarms',\n  'swells',\n  'swifts',\n  'tars',\n  'teams',\n  'teeth',\n  'terns',\n  'thorns',\n  'threads',\n  'thrones',\n  'ticks',\n  'toads',\n  'tools',\n  'trees',\n  'tribes',\n  'trolls',\n  'trout',\n  'tunes',\n  'tusks',\n  'veins',\n  'verbs',\n  'vines',\n  'voles',\n  'wasps',\n  'waves',\n  'wells',\n  'whales',\n  'whelks',\n  'whiffs',\n  'winds',\n  'wolves',\n  'worms',\n  'wraiths',\n  'wrens',\n  'yaks'];\n\nverbs = ['aid',\n  'arm',\n  'awe',\n  'axe',\n  'bag',\n  'bait',\n  'bare',\n  'bash',\n  'bathe',\n  'beat',\n  'bid',\n  'bilk',\n  'blame',\n  'bleach',\n  'bleed',\n  'bless',\n  'bluff',\n  'blur',\n  'boast',\n  'boost',\n  'boot',\n  'bore',\n  'botch',\n  'breed',\n  'brew',\n  'bribe',\n  'brief',\n  'brine',\n  'broil',\n  'browse',\n  'bruise',\n  'build',\n  'burn',\n  'burst',\n  'call',\n  'calm',\n  'carve',\n  'chafe',\n  'chant',\n  'charge',\n  'chart',\n  'cheat',\n  'check',\n  'cheer',\n  'chill',\n  'choke',\n  'chomp',\n  'choose',\n  'churn',\n  'cite',\n  'clamp',\n  'clap',\n  'clasp',\n  'claw',\n  'clean',\n  'cleanse',\n  'clip',\n  'cloak',\n  'clone',\n  'clutch',\n  'coax',\n  'crack',\n  'crave',\n  'crunch',\n  'cry',\n  'cull',\n  'cure',\n  'curse',\n  'cuss',\n  'dare',\n  'daze',\n  'dent',\n  'dig',\n  'ding',\n  'doubt',\n  'dowse',\n  'drag',\n  'drain',\n  'drape',\n  'draw',\n  'dread',\n  'dredge',\n  'drill',\n  'drink',\n  'drip',\n  'drive',\n  'drop',\n  'drown',\n  'dry',\n  'dump',\n  'eat',\n  'etch',\n  'face',\n  'fail',\n  'fault',\n  'fear',\n  'feed',\n  'feel',\n  'fetch',\n  'fight',\n  'find',\n  'fix',\n  'flap',\n  'flay',\n  'flee',\n  'fling',\n  'flip',\n  'float',\n  'foil',\n  'forge',\n  'free',\n  'freeze',\n  'frisk',\n  'gain',\n  'glimpse',\n  'gnaw',\n  'goad',\n  'gouge',\n  'grab',\n  'grasp',\n  'graze',\n  'grieve',\n  'grip',\n  'groom',\n  'guard',\n  'guards',\n  'guide',\n  'gulp',\n  'gush',\n  'halt',\n  'harm',\n  'hate',\n  'haul',\n  'haunt',\n  'have',\n  'heal',\n  'hear',\n  'help',\n  'herd',\n  'hex',\n  'hire',\n  'hit',\n  'hoist',\n  'hound',\n  'hug',\n  'hurl',\n  'irk',\n  'jab',\n  'jeer',\n  'join',\n  'jolt',\n  'keep',\n  'kick',\n  'kill',\n  'kiss',\n  'lash',\n  'leash',\n  'leave',\n  'lift',\n  'like',\n  'love',\n  'lug',\n  'lure',\n  'maim',\n  'make',\n  'mask',\n  'meet',\n  'melt',\n  'mend',\n  'miss',\n  'mould',\n  'move',\n  'nab',\n  'name',\n  'need',\n  'oust',\n  'paint',\n  'paw',\n  'pay',\n  'peck',\n  'peeve',\n  'pelt',\n  'please',\n  'pluck',\n  'poach',\n  'poll',\n  'praise',\n  'prick',\n  'print',\n  'probe',\n  'prod',\n  'prompt',\n  'punch',\n  'quash',\n  'quell',\n  'quote',\n  'raid',\n  'raise',\n  'raze',\n  'ride',\n  'roast',\n  'rouse',\n  'rule',\n  'scald',\n  'scalp',\n  'scar',\n  'scathe',\n  'score',\n  'scorn',\n  'scour',\n  'scuff',\n  'sear',\n  'see',\n  'seek',\n  'seize',\n  'send',\n  'sense',\n  'serve',\n  'shake',\n  'shear',\n  'shift',\n  'shoot',\n  'shun',\n  'slap',\n  'slay',\n  'slice',\n  'smack',\n  'smash',\n  'smell',\n  'smite',\n  'snare',\n  'snatch',\n  'sniff',\n  'snub',\n  'soak',\n  'spare',\n  'splash',\n  'split',\n  'spook',\n  'spray',\n  'squash',\n  'squeeze',\n  'stab',\n  'stain',\n  'starve',\n  'steal',\n  'steer',\n  'sting',\n  'strike',\n  'stun',\n  'tag',\n  'tame',\n  'taste',\n  'taunt',\n  'teach',\n  'tend'];\n\nif (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {\n  module.exports = publicMethods;\n} else {\n  return publicMethods;\n}\n\n})();\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"hipku\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Encode any IP address as a haiku\",\n  \"main\": \"index.js\",\n  \"devDependencies\": {\n    \"jasmine-node\": \">=1.14.5\"\n  },\n  \"scripts\": {\n    \"test\": \"jasmine-node test/spec\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/gabemart/hipku.git\"\n  },\n  \"keywords\": [\n    \"poetry\",\n    \"ipv4\",\n    \"ipv6\",\n    \"haiku\"\n  ],\n  \"author\": {\n    \"name\": \"Gabriel Martin\"\n  },\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/gabemart/hipku/issues\"\n  },\n  \"homepage\": \"http://gabrielmartin.net/projects/hipku\"\n}\n"
  },
  {
    "path": "test/spec/allVersions.spec.js",
    "content": "/*\n** Test that when you take an IP address, encode it, and then decode it\n** again, it matches the original address. These tests are applicable to\n** all versions of Hipku, regardless of changes to the dictionaries or\n** schema.\n*/\n\nvar Hipku = require('../../index.js');\n\ndescribe(\"All versions of Hipku\", function() {\n  \n  it(\"should symmetrically encode and decode IPv4 addresses\", function() {   \n    expect(\n      Hipku.decode(Hipku.encode('0.0.0.0'))\n    ).toBe('0.0.0.0');\n\n    expect(\n      Hipku.decode(Hipku.encode('127.0.0.1'))\n    ).toBe('127.0.0.1');\n    \n    expect(\n      Hipku.decode(Hipku.encode('82.158.98.2'))\n    ).toBe('82.158.98.2');    \n    \n    expect(\n      Hipku.decode(Hipku.encode('255.255.255.255'))\n    ).toBe('255.255.255.255');  \n  });\n  \n  it(\"should symmetrically encode and decode IPv6 addresses\", function() { \n\n    expect(\n      Hipku.decode(Hipku.encode('0:0:0:0:0:0:0:0'))\n    ).toBe('0:0:0:0:0:0:0:0');\n\n    expect(\n      Hipku.decode(Hipku.encode('2c8f:27aa:61fd:56ec:7ebe:d03a:1f50:475f'))\n    ).toBe('2c8f:27aa:61fd:56ec:7ebe:d03a:1f50:475f');\n\n    expect(\n      Hipku.decode(Hipku.encode('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'))\n    ).toBe('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff');       \n  });\n  \n  it(\"should correctly expand the abbreviated IPv6 format\", function() {\n  \n    var fullAddress = '0:0:0:0:0:0:0:0';\n    \n    expect(\n      Hipku.decode(Hipku.encode('::0'))\n    ).toBe(fullAddress);\n    \n    expect(\n      Hipku.decode(Hipku.encode('0::'))\n    ).toBe(fullAddress);    \n\n    expect(\n      Hipku.decode(Hipku.encode('0::0'))\n    ).toBe(fullAddress);\n    \n    expect(\n      Hipku.decode(Hipku.encode('0:0::0:0'))\n    ).toBe(fullAddress);\n  \n  });\n  \n});"
  },
  {
    "path": "test/spec/currentVersion.spec.js",
    "content": "/*\n** Test that a series of encoded test IPs match haiku for the current \n** set of dictionaries and schema, and that a series of decoded test\n** haiku match IPs for the current dictionaries and schema. These tests\n** must be updated whenever the dictionaries or schema are changed.\n*/\n\nvar Hipku = require('../../index.js');\n\ndescribe(\"The current version of Hipku\", function() {\n\n  var Ipv4HipkuIpPairs, Ipv6HipkuIpPairs;\n\n  beforeEach(function() {\n    Ipv4HipkuIpPairs = [\n      ['0.0.0.0', 'The agile beige ape\\naches in the ancient canyon.\\nAutumn colors blow.\\n'],\n      ['127.0.0.1', 'The hungry white ape\\naches in the ancient canyon.\\nAutumn colors crunch.\\n'],\n      ['82.158.98.2', 'The fearful blue newt\\nwakes in the foggy desert.\\nAutumn colors dance.\\n'],\n      ['255.255.255.255', 'The weary white wolf\\nyawns in the wind-swept wetlands.\\nYellowwood leaves twist.\\n']\n    ];  \n    \n    Ipv6HipkuIpPairs = [\n      ['0:0:0:0:0:0:0:0',\n        'Ace ants and ace ants\\naid ace ace ace ace ace ants.\\nAce ants aid ace ants.\\n'],\n      ['2c8f:27aa:61fd:56ec:7ebe:d03a:1f50:475f',\n        'Cursed mobs and crazed queens\\nfeel wrong gruff tired moist slow sprats.\\nFaint bulls dread fond fruits.\\n'],\n      ['ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',\n        'Young yaks and young yaks\\ntend young young young young young yaks.\\nYoung yaks tend young yaks.\\n']\n    ];\n  });\n  \n  afterEach(function() {\n    Ipv4HipkuIpPairs = null;\n    Ipv6HipkuIpPairs = null;\n  });\n\n  it(\"should correctly encode a series of test IPv4 addresses\", function() {\n    for (var i = 0; i < Ipv4HipkuIpPairs.length; i++) {\n      expect(\n        Hipku.encode(Ipv4HipkuIpPairs[i][0])\n      ).toBe(Ipv4HipkuIpPairs[i][1]); \n    }             \n  });\n\n  it(\"should correctly decode a series of test IPv4 hipku\", function() {\n    for (var i = 0; i < Ipv4HipkuIpPairs.length; i++) {\n      expect(\n        Hipku.decode(Ipv4HipkuIpPairs[i][1])\n      ).toBe(Ipv4HipkuIpPairs[i][0]); \n    }    \n  });\n\n  it(\"should correctly encode a series of test IPv6 addresses\", function() {\n    for (var i = 0; i < Ipv6HipkuIpPairs.length; i++) {\n      expect(\n        Hipku.encode(Ipv6HipkuIpPairs[i][0])\n      ).toBe(Ipv6HipkuIpPairs[i][1]); \n    }            \n  });\n\n  it(\"should correctly decode a series of test IPv6 hipku\", function() {\n    for (var i = 0; i < Ipv6HipkuIpPairs.length; i++) {\n      expect(\n        Hipku.decode(Ipv6HipkuIpPairs[i][1])\n      ).toBe(Ipv6HipkuIpPairs[i][0]); \n    }   \n  });    \n\n});"
  }
]