UNPKG

@nurliman/base85

Version:

Browser and Node.js-compatible Base85 encoder/decoder.

1 lines 8.75 kB
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/decode.ts","../src/encode.ts"],"sourcesContent":["/**\n * `@nurliman/base85` is a Base85 encoder and decoder that compatible for Node.js and browser.\n *\n * ## Usage\n *\n * Import the package into your project:\n *\n * ```ts\n * import { encodeBase85, decodeBase85 } from \"@nurliman/base85\";\n *\n * const encoded = encodeBase85(\"your string\");\n * const decoded = decodeBase85(encoded);\n * ```\n *\n * using default import:\n *\n * ```ts\n * import base85 from \"@nurliman/base85\";\n *\n * const encoded = base85.encode(\"your string\");\n * const decoded = base85.decode(encoded);\n * ```\n *\n * using require:\n *\n * ```ts\n * const { encodeBase85, decodeBase85 } = require(\"@nurliman/base85\");\n *\n * const encoded = encodeBase85(\"your string\");\n * const decoded = decodeBase85(encoded);\n * ```\n *\n * Please replace `'your string'` with the string you want to encode and decode.\n *\n * ### EncodeOptions\n *\n * `EncodeOptions` is an object that can be passed to the encode function to customize its behavior. It has the following properties:\n *\n * - `wrap`: If true, the encoded string will be wrapped in `<~` and `~>`. Defaults to `true`.\n *\n * Here's an example of how to use it:\n *\n * ```ts\n * import base85 from \"@nurliman/base85\";\n *\n * const result = base85.encode(\"Hello World!\");\n * console.log(result);\n * // <~87cURD]i,\"Ebo80~>\n *\n * const result = base85.encode(\"Hello World!\", {\n * wrap: false, // Set this to false if you don't want the output to be wrapped\n * });\n * console.log(result);\n * // 87cURD]i,\"Ebo80\n * ```\n *\n * ### Decode\n *\n * ```ts\n * import base85 from \"@nurliman/base85\";\n *\n * const result = base85.decode('<~87cURD]i,\"Ebo80~>');\n * console.log(result);\n * // Hello World!\n *\n * // it also works without the wrapping characters\n * const result = base85.decode('87cURD]i,\"Ebo80');\n * console.log(result);\n * // Hello World!\n * ```\n * @module\n */\n\nimport { decodeBase85 } from \"./decode.ts\";\nimport { encodeBase85 } from \"./encode.ts\";\nexport type * from \"./encode.ts\";\nexport { encodeBase85, decodeBase85 };\n\n/**\n * Base85 encoder and decoder\n */\nconst base85 = {\n encode: encodeBase85,\n decode: decodeBase85,\n};\n\nexport default base85;\n","export function charCodeArrayToString(charCodes: number[]): string {\n let output = \"\";\n for (let i = 0; i < charCodes.length; i++) {\n output += String.fromCharCode(charCodes[i]);\n }\n return output;\n}\n","import { charCodeArrayToString } from \"./utils.ts\";\n\n/**\n * Decodes a string from ASCII85\n *\n * ```ts\n * import base85 from \"@nurliman/base85\";\n *\n * base85.decode('<~87cURD]i,\"Ebo80~>');\n * // output: Hello World!\n *\n * // it also works without the wrapping characters\n * base85.decode('87cURD]i,\"Ebo80');\n * // output: Hello World!\n * ```\n */\nexport function decodeBase85(input: string): string {\n // Define constants and variables\n const ASCII_OFFSET = 33;\n const BASE85_BLOCK_SIZE = 5;\n const BYTE_MASK = 255;\n\n // Check if input string is wrapped with \"<~\" and \"~>\", remove them if true\n input = input.replace(/^<~/g, \"\").replace(/~>$/g, \"\");\n\n if (!input) return \"\";\n\n // Remove all whitespace characters and replace \"z\" with \"!!!!!\"\n input = input.replace(/\\s/g, \"\").replace(\"z\", \"!!!!!\");\n\n // Calculate the number of padding characters needed to make the input length a multiple of 5\n const paddingLength = input.length % BASE85_BLOCK_SIZE || BASE85_BLOCK_SIZE;\n const paddingCharacters = \"uuuuu\".slice(paddingLength);\n\n // Add the padding characters to the input\n input += paddingCharacters;\n\n // Initialize the array to hold the decoded bytes\n const decodedBytes: number[] = [];\n\n // Loop over the input string in chunks of 5 characters\n for (let chunkStart = 0; input.length > chunkStart; chunkStart += 5) {\n // Decode the current chunk and add the decoded bytes to the array\n const decodedChunk =\n 52200625 * (input.charCodeAt(chunkStart) - ASCII_OFFSET) +\n 614125 * (input.charCodeAt(chunkStart + 1) - ASCII_OFFSET) +\n 7225 * (input.charCodeAt(chunkStart + 2) - ASCII_OFFSET) +\n 85 * (input.charCodeAt(chunkStart + 3) - ASCII_OFFSET) +\n (input.charCodeAt(chunkStart + 4) - ASCII_OFFSET);\n decodedBytes.push(\n BYTE_MASK & (decodedChunk >> 24),\n BYTE_MASK & (decodedChunk >> 16),\n BYTE_MASK & (decodedChunk >> 8),\n BYTE_MASK & decodedChunk,\n );\n }\n\n // Remove the padding bytes from the end of the array\n if (paddingCharacters.length > 0) {\n decodedBytes.splice(-paddingCharacters.length);\n }\n\n // Convert the array of decoded bytes to a string and return it\n return charCodeArrayToString(decodedBytes);\n}\n","import { charCodeArrayToString } from \"./utils.ts\";\n\n/**\n * `EncodeOptions` is an object that can be passed to the encode function to customize its behavior.\n */\nexport type EncodeOptions = {\n /**\n * If true, the encoded string will be wrapped in `<~` and `~>`.\n * @default true\n */\n wrap?: boolean;\n};\n\n/**\n * Encodes a string to ASCII85\n *\n * @param input The string to encode\n * @param {Object} options Options for encoding\n * @param {boolean} [options.wrap=true] If true, the encoded string will be wrapped in `<~` and `~>`. default is `true`\n * @returns {string} The encoded string\n *\n * ```ts\n * import base85 from \"@nurliman/base85\";\n *\n * base85.encode(\"Hello World!\");\n * // output: <~87cURD]i,\"Ebo80~>\n *\n * base85.encode(\"Hello World!\", { wrap: false });\n * // output: 87cURD]i,\"Ebo80\n * ```\n */\nexport function encodeBase85(input: string, { wrap = true }: EncodeOptions = {}): string {\n if (!input) return wrap ? \"<~~>\" : \"\";\n\n const paddingLength = input.length % 4 || 4;\n const paddingCharacters = \"\\x00\\x00\\x00\\x00\".slice(paddingLength);\n input += paddingCharacters;\n\n const encodedArray = [];\n\n for (let index = 0; index < input.length; index += 4) {\n let charCodeSum =\n (input.charCodeAt(index) << 24) +\n (input.charCodeAt(index + 1) << 16) +\n (input.charCodeAt(index + 2) << 8) +\n input.charCodeAt(index + 3);\n\n if (charCodeSum !== 0) {\n const encodedChars = [];\n for (let j = 0; j < 5; j++) {\n const encodedChar = charCodeSum % 85;\n charCodeSum = (charCodeSum - encodedChar) / 85;\n encodedChars.unshift(encodedChar + 33);\n }\n encodedArray.push(...encodedChars);\n } else {\n encodedArray.push(122);\n }\n }\n\n // Remove padding from the end of the encoded array\n if (paddingCharacters.length > 0) {\n encodedArray.splice(-paddingCharacters.length);\n }\n\n const encodedString = charCodeArrayToString(encodedArray);\n const output = wrap ? `<~${encodedString}~>` : encodedString;\n\n return output;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,SAAS,sBAAsB,WAA6B;AACjE,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,cAAU,OAAO,aAAa,UAAU,CAAC,CAAC;AAAA,EAC5C;AACA,SAAO;AACT;;;ACUO,SAAS,aAAa,OAAuB;AAElD,QAAM,eAAe;AACrB,QAAM,oBAAoB;AAC1B,QAAM,YAAY;AAGlB,UAAQ,MAAM,QAAQ,QAAQ,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAEpD,MAAI,CAAC,MAAO,QAAO;AAGnB,UAAQ,MAAM,QAAQ,OAAO,EAAE,EAAE,QAAQ,KAAK,OAAO;AAGrD,QAAM,gBAAgB,MAAM,SAAS,qBAAqB;AAC1D,QAAM,oBAAoB,QAAQ,MAAM,aAAa;AAGrD,WAAS;AAGT,QAAM,eAAyB,CAAC;AAGhC,WAAS,aAAa,GAAG,MAAM,SAAS,YAAY,cAAc,GAAG;AAEnE,UAAM,eACJ,YAAY,MAAM,WAAW,UAAU,IAAI,gBAC3C,UAAU,MAAM,WAAW,aAAa,CAAC,IAAI,gBAC7C,QAAQ,MAAM,WAAW,aAAa,CAAC,IAAI,gBAC3C,MAAM,MAAM,WAAW,aAAa,CAAC,IAAI,iBACxC,MAAM,WAAW,aAAa,CAAC,IAAI;AACtC,iBAAa;AAAA,MACX,YAAa,gBAAgB;AAAA,MAC7B,YAAa,gBAAgB;AAAA,MAC7B,YAAa,gBAAgB;AAAA,MAC7B,YAAY;AAAA,IACd;AAAA,EACF;AAGA,MAAI,kBAAkB,SAAS,GAAG;AAChC,iBAAa,OAAO,CAAC,kBAAkB,MAAM;AAAA,EAC/C;AAGA,SAAO,sBAAsB,YAAY;AAC3C;;;ACjCO,SAAS,aAAa,OAAe,EAAE,OAAO,KAAK,IAAmB,CAAC,GAAW;AACvF,MAAI,CAAC,MAAO,QAAO,OAAO,SAAS;AAEnC,QAAM,gBAAgB,MAAM,SAAS,KAAK;AAC1C,QAAM,oBAAoB,WAAmB,MAAM,aAAa;AAChE,WAAS;AAET,QAAM,eAAe,CAAC;AAEtB,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,QAAI,eACD,MAAM,WAAW,KAAK,KAAK,OAC3B,MAAM,WAAW,QAAQ,CAAC,KAAK,OAC/B,MAAM,WAAW,QAAQ,CAAC,KAAK,KAChC,MAAM,WAAW,QAAQ,CAAC;AAE5B,QAAI,gBAAgB,GAAG;AACrB,YAAM,eAAe,CAAC;AACtB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,cAAM,cAAc,cAAc;AAClC,uBAAe,cAAc,eAAe;AAC5C,qBAAa,QAAQ,cAAc,EAAE;AAAA,MACvC;AACA,mBAAa,KAAK,GAAG,YAAY;AAAA,IACnC,OAAO;AACL,mBAAa,KAAK,GAAG;AAAA,IACvB;AAAA,EACF;AAGA,MAAI,kBAAkB,SAAS,GAAG;AAChC,iBAAa,OAAO,CAAC,kBAAkB,MAAM;AAAA,EAC/C;AAEA,QAAM,gBAAgB,sBAAsB,YAAY;AACxD,QAAM,SAAS,OAAO,KAAK,aAAa,OAAO;AAE/C,SAAO;AACT;;;AHYA,IAAM,SAAS;AAAA,EACb,QAAQ;AAAA,EACR,QAAQ;AACV;AAEA,IAAO,cAAQ;","names":[]}