@readme/data-urls
A lightweight, fully-typed utility for parsing and validating data: URLs in JavaScript and TypeScript.
Repository Health
Technical Analysis
@readme/data-urls is a small TypeScript library for parsing and validating data: URLs — the RFC 2397 URIs that embed inline content such as base64-encoded images directly inside a string. It started as a loose fork of the popular parse-data-url and valid-data-url packages, merging both into a single dependency-free module with modern TypeScript types and dual ESM/CommonJS builds.
The library exposes two functions: validate(), which checks whether a string is a well-formed data URL, and parse(), which breaks a valid data URL down into its media type, content type, any additional attributes (like name or charset), a base64 flag, and the raw payload data — plus a toBuffer() convenience method for turning that payload into a Node.js Buffer.
What You Get
- validate() - a single function that returns a boolean for whether a string is a well-formed data URL, per RFC 2397
- parse() - decomposes a valid data URL into mediaType, contentType, any additional key/value attributes, a base64 flag, and the raw data
- toBuffer() - a helper attached to every parsed result that decodes the payload into a Node.js Buffer using the correct base64 or utf8 encoding
- Dual ESM/CJS builds - published with both import and require entry points plus full TypeScript declaration files
Common Use Cases
- Validating user-submitted data URLs - reject malformed data: URIs before passing them to downstream image or file processing
- Extracting embedded images from API payloads - pull base64-encoded images out of data URLs returned by an API and write them to disk
- Parsing inline-asset data URLs - read the media type and payload out of data URLs embedded in HTML or CSS during a build step
- Decoding data URLs into buffers for storage - convert a parsed data URL’s payload directly into a Buffer for upload to a file store
Under The Hood
Architecture The entire library is a single module, src/index.ts, built around one exported regular expression (DATA_URL_REGEX) that both validate() and parse() share: validate() runs the regex as a boolean test, while parse() re-runs it to capture match groups and assembles a plain DataURL object from them, attaching a toBuffer() closure before returning. There are no internal layers, classes, or dependency injection — the whole surface area is two pure functions and one interface, so the only thing that could break with a core-abstraction change is the regex itself, which every other code path depends on directly.
Tech Stack The package is TypeScript-only, compiled and bundled with tsdown into dual ESM (index.mjs) and CommonJS (index.cjs) outputs with matching .d.mts/.d.cts declaration files, wired through a conditional exports map in package.json. Tests run under vitest with @vitest/coverage-v8 for coverage reporting, linting and formatting are handled by the Rust-based oxlint and oxfmt (invoked via a pretest lint gate), and @arethetypeswrong/core checks that the published type declarations resolve correctly across module systems. The package declares zero runtime dependencies and targets Node >=22.
Code Quality The test suite in test/index.test.ts is proportionally large for the codebase, covering both parse() and validate() with dozens of table-driven cases (it.each) spanning trailing whitespace, base64 vs. utf8 payloads, multi-attribute media types, and casing rules for name attributes. Error handling favors explicit sentinel returns — parse() returns false on invalid input rather than throwing — and the DataURL interface gives every parsed result a typed shape. A pretest script enforces lint and format checks before tests run, and CI runs on every push.
What Makes It Unique Rather than pulling in the two separate, unmaintained parse-data-url and valid-data-url packages, this library consolidates both concerns into one dependency-free, actively maintained TypeScript module with a unified API and modern dual-format packaging. It preserves a niche but useful behavioral detail from its predecessors — retaining the original casing of name= attributes for filesystem safety while lowercasing everything else in the media type.