Skip to content
/ atob Public

Performant platform-agnostic ponyfills for `atob` and `btoa`.

License

Notifications You must be signed in to change notification settings

nberlette/atob

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@nick/atob

Lightweight, dependency-free, portable ponyfills for atob and btoa.


Install

# deno
deno add jsr:@nick/atob

# bun
bunx jsr add @nick/atob

# pnpm
pnpm dlx jsr add @nick/atob

# yarn
yarn dlx jsr add @nick/atob

# npm
npx -y jsr add @nick/atob

Usage

This package provides ponyfill exports for atob and btoa, as well as a ./shim entrypoint that will automatically polyfill the global scope with atob and/or btoa if they are not already supported.

Ponyfill

import { atob, btoa } from "@nick/atob";

const datauri = `data:image/svg+xml;base64,${btoa("<svg>...</svg>")}`;

const base64 = datauri.split(",")[1]!;

const decoded = atob(base64); // "<svg>...</svg>"
console.assert(decoded === "<svg>...</svg>"); // OK

Polyfill

While the primary focus of this package is providing a ponyfill for atob and btoa, some users might need a polyfill instead.

Therefore, I've also provided an automatic shim module that gracefully installs these functions on an as-needed basis, as well as a manual install module that allows you to choose when and if you want it to mutate the global scope.

Shim (automatic)

import "@nick/atob/shim"; // side-effect import

const bytes = "data:application/wasm;base64,AGFzbQEAAAABOwpgAn9/AX...";

const buf = Uint8Array.from(atob(bytes.split(",")[1]!), (b) => b.charCodeAt(0));

const module = new WebAssembly.Module(buf);
const instance = new WebAssembly.Instance(module);

Install (manual)

If you need explicit control over the polyfilling, install() can be used to gracefully install the functions on-demand.

import { install } from "@nick/atob/install";

if (typeof atob !== "function" || typeof btoa !== "function") {
  install(); // ta da!
}

console.assert(btoa("hello world") === "aGVsbG8gd29ybGQ="); // OK
console.assert(atob("aGVsbG8gd29ybGQ=") === "hello world"); // OK

Note

This is used internally by the ./shim entrypoint.


API

atob

Decodes a Base64-encoded string into a decoded string.

Signature

function atob(data: string): string;
Params

data The Base64-encoded string to decode.

Return

A decoded string.

Example

import { atob } from "@nick/atob";

const encoded = "aGVsbG8gd29ybGQ=";
const decoded = atob(encoded);

console.assert(decoded === "hello world"); // OK

References


btoa

Encodes a string into Base64.

Signature

function btoa(data: string): string;
Params

data The string to encode.

Return

A Base64-encoded string.

Example

import { btoa } from "@nick/atob";

const data = "hello world";
const encoded = btoa(data);

console.assert(encoded === "aGVsbG8gd29ybGQ=");

References


install

Gracefully polyfills the global atob and btoa functions if they are not already present in the environment.

Signature

function install(): Result;
Return
  • On success, returns a Success<Data> object containing the installed functions.
  • If the functions are already defined, returns a Skipped result.
  • If an error occurs during installation, returns a Failure result with the error.

Associated Types

  • Success<T> Represents a successful operation.

    interface Success<T> {
      readonly type: "success";
      readonly data: T;
    }
  • Skipped Indicates that the installation was skipped because atob and btoa are already present.

    interface Skipped {
      readonly type: "skipped";
      readonly info?: string;
    }
  • Failure Represents a failed installation with an error.

    interface Failure {
      readonly type: "failure";
      readonly error: unknown;
    }
  • Data Contains references to the installed polyfill functions.

    type Data =
      | { readonly atob: typeof atob }
      | { readonly btoa: typeof btoa }
      | { readonly atob: typeof atob; readonly btoa: typeof btoa };
  • Result Represents the union of all possible results of the installation process.

    type Result = Success<Data> | Skipped | Failure;

Example

import { install } from "@nick/atob/install";

if (typeof atob !== "function" || typeof btoa !== "function") {
  const result = install();
  if (result.type === "success") {
    console.log("atob and btoa installed successfully.");
  } else if (result.type === "skipped") {
    console.log("atob and btoa already installed.");
  } else {
    console.error("Failed to install atob and btoa:", result.error);
  }
}

console.assert(typeof atob === "function" && typeof atob === "function"); // OK
console.assert(btoa("hello world") === "aGVsbG8gd29ybGQ=");
console.assert(atob("aGVsbG8gd29ybGQ=") === "hello world");

Contributing

Contributions are always welcome! Before submitting a pull request, I kindly ask that you first open an issue and start a discussion regarding the feature or bug you would like to address. This helps contributions align with the goals and scope of the project, ensuring a smoother integration process.

For additional details, please refer to the contributing guidelines. Thanks!


MIT © Nicholas Berlette. All rights reserved.

Github · Issues · Docs · Contribute