# 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
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.
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
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.
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);
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.
Decodes a Base64-encoded string into a decoded string.
function atob(data: string): string;
data
The Base64-encoded string to decode.
A decoded string.
import { atob } from "@nick/atob";
const encoded = "aGVsbG8gd29ybGQ=";
const decoded = atob(encoded);
console.assert(decoded === "hello world"); // OK
Encodes a string into Base64.
function btoa(data: string): string;
data
The string to encode.
A Base64-encoded string.
import { btoa } from "@nick/atob";
const data = "hello world";
const encoded = btoa(data);
console.assert(encoded === "aGVsbG8gd29ybGQ=");
Gracefully polyfills the global atob
and btoa
functions if they are not
already present in the environment.
function install(): Result;
- 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.
-
Success<T>
Represents a successful operation.interface Success<T> { readonly type: "success"; readonly data: T; }
-
Skipped
Indicates that the installation was skipped becauseatob
andbtoa
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;
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");
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!