Parsing and formatting APIs: Bun.semver, TOML, XML, markdown, color, Image
Bun provides parsing and formatting utilities: Bun.semver for semantic version parsing, Bun.TOML.parse() for TOML parsing, Bun.XML for XML processing, Bun.markdown for markdown parsing, Bun.color for color parsing/formatting, and Bun.Image for image processing.
Bun.color 'ansi-16' conversion algorithm
The 'ansi-16' format converts input to 24-bit RGB color space, then to 'ansi-256', then approximates to the nearest of the 16 ANSI colors supported by most terminals.
Bun.color 'ansi-256' conversion algorithm
The 'ansi-256' format approximates the input color to the nearest of the 256 ANSI colors using the algorithm that tmux uses.
Bun.color API signature
Bun.color(input, outputFormat?) parses, normalizes, and converts colors from user input to any of multiple output formats. The outputFormat parameter is optional.
Bun.color '{rgba}' object format
The '{rgba}' format returns an object with properties: r (0-255), g (0-255), b (0-255), a (0-1 decimal). The alpha channel is a decimal number between 0 and 1.
Bun.color '{rgb}' object format
The '{rgb}' format returns an object with properties: r (0-255), g (0-255), b (0-255). It does not include the alpha channel.
Bun.color '[rgb]' array format
The '[rgb]' array format returns [r, g, b] where all values are 0-255 integers. It does not include the alpha channel.
Bun.color 'css' format compactness
The 'css' format outputs valid CSS for stylesheets, inline styles, CSS variables, or CSS-in-JS, returning the most compact string representation of the color.
Bun.color 'number' format for databases
The 'number' format outputs the color as a 24-bit number, which is a compact representation suitable for databases and configuration.
Bun.color use cases
Bun.color is used to: validate and normalize colors for database persistence (with 'number' being most database-friendly), convert colors to different formats, color terminal output beyond the basic 16 colors (using 'ansi' for auto-detection or specific formats like 'ansi-16', 'ansi-256', or 'ansi-16m'), format colors for CSS injection into HTML, and extract r, g, b, and a color components as JavaScript objects or numbers from CSS color strings.
Bun.color as built-in alternative
Bun.color is a built-in alternative to npm packages 'color' and 'tinycolor2', with full support for parsing CSS color strings and zero dependencies.
Bun.color CSS parsing
Bun.color uses Bun's CSS parser to parse, normalize, and convert colors.
Bun.color example CSS output
Bun.color('red', 'css') returns 'red'. All these inputs produce 'red': 0xff0000, '#f00', '#ff0000', 'rgb(255, 0, 0)', 'rgba(255, 0, 0, 1)', 'hsl(0, 100%, 50%)', 'hsla(0, 100%, 50%, 1)', {r: 255, g: 0, b: 0}, {r: 255, g: 0, b: 0, a: 1}, [255, 0, 0], [255, 0, 0, 255].
Bun.color example ANSI output
Bun.color('red', 'ansi') returns '\u001b[38;2;255;0;0m'. All these inputs produce the same output: 0xff0000, '#f00', '#ff0000', 'rgb(255, 0, 0)', 'rgba(255, 0, 0, 1)', 'hsl(0, 100%, 50%)', 'hsla(0, 100%, 50%, 1)', {r: 255, g: 0, b: 0}, {r: 255, g: 0, b: 0, a: 1}, [255, 0, 0], [255, 0, 0, 255].
Bun.color input formats
Bun.color accepts: standard CSS color names like 'red', numbers like 0xff0000, hex strings like '#f00', RGB strings like 'rgb(255, 0, 0)', RGBA strings like 'rgba(255, 0, 0, 1)', HSL strings like 'hsl(0, 100%, 50%)', HSLA strings like 'hsla(0, 100%, 50%, 1)', RGB objects like {r: 255, g: 0, b: 0}, RGBA objects like {r: 255, g: 0, b: 0, a: 1}, RGB arrays like [255, 0, 0], RGBA arrays like [255, 0, 0, 255], LAB strings like 'lab(50% 50 50)', and anything else that CSS can parse as a single color value.
Bun.color example ANSI-256 output
Bun.color('red', 'ansi-256') returns '\u001b[38;5;196m'. All these inputs produce the same output: 0xff0000, '#f00', '#ff0000'.
Bun.color example ANSI-16 output
Bun.color('red', 'ansi-16') returns '\u001b[91m'. All these inputs produce the same output: 0xff0000, '#f00', '#ff0000'.
Bun.color example number output
Bun.color('red', 'number') returns 16711680. These inputs produce the same output: 0xff0000, {r: 255, g: 0, b: 0}, [255, 0, 0], 'rgb(255, 0, 0)', 'rgba(255, 0, 0, 1)', 'hsl(0, 100%, 50%)', 'hsla(0, 100%, 50%, 1)'.
Bun.color output formats
Bun.color supports these output formats: 'css' (returns CSS color name like 'red'), 'ansi' (ANSI escape codes like '\x1b[38;2;255;0;0m'), 'ansi-16' (basic 16 color ANSI like '\x1b[91m'), 'ansi-256' (256 color approximation like '\x1b[38;5;196m'), 'ansi-16m' (24-bit ANSI like '\x1b[38;2;255;0;0m'), 'number' (24-bit integer like 0x1a2b3c), 'rgb' (CSS string like 'rgb(255, 99, 71)'), 'rgba' (CSS string like 'rgba(255, 99, 71, 0.5)'), 'hsl' (CSS string like 'hsl(120, 50%, 50%)'), 'hex' (lowercase hex like '#1a2b3c'), 'HEX' (uppercase hex like '#1A2B3C'), '{rgb}' (object {r: 255, g: 99, b: 71}), '{rgba}' (object {r: 255, g: 99, b: 71, a: 1}), '[rgb]' (array [255, 99, 71]), '[rgba]' (array [255, 99, 71, 255]).
Bun.color example [rgb] array output
Bun.color('red', '[rgb]') returns [255, 0, 0]. Bun.color('hsl(0, 0%, 50%)', '[rgb]') returns [128, 128, 128]. These inputs produce [255, 0, 0]: 0xff0000, {r: 255, g: 0, b: 0}, [255, 0, 0].
Bun.color example HEX uppercase output
Bun.color('red', 'HEX') returns '#FF0000'. Bun.color('hsl(0, 0%, 50%)', 'HEX') returns '#808080'. These inputs produce '#FF0000': 0xff0000, {r: 255, g: 0, b: 0}, [255, 0, 0].
Bun.color 'ansi' format auto-detection
The 'ansi' format detects the color depth of stdout from environment variables and automatically picks 'ansi-16m', 'ansi-256', or 'ansi-16' accordingly. If stdout doesn't support any form of ANSI color, it returns an empty string.
Bun.color return value on parse failure
If the input to Bun.color is unknown or fails to parse, the function returns null.
HTMLRewriter input type examples
Example showing different input types for HTMLRewriter: rewriter.transform(new Response("<div>content</div>")); rewriter.transform("<div>content</div>"); rewriter.transform(new TextEncoder().encode("<div>content</div>").buffer); rewriter.transform(new Response(new Blob(["<div>content</div>"]))); rewriter.transform(new Response(Bun.file("index.html")));
HTMLRewriter overview and input types
HTMLRewriter transforms HTML documents using CSS selectors. It is based on Cloudflare's lol-html. It accepts Response, string, ArrayBuffer, Blob (wrapped in Response), and File (wrapped in Response) as input types. The Cloudflare Workers implementation only supports Response objects.
HTMLRewriter.on() method with element handlers
The on(selector, handlers) method registers handlers for HTML elements matching a CSS selector. Handlers can define element(element), text(text), and comments(comment) functions that run for each matching element during parsing. Handlers can be asynchronous and return a Promise, pausing transformation until the Promise settles. Handlers still run one at a time in document order.
HTMLRewriter element attribute methods
Element attribute methods in HTMLRewriter: setAttribute(name, value) sets an attribute, getAttribute(name) retrieves an attribute value, hasAttribute(name) checks if an attribute exists, and removeAttribute(name) removes an attribute. All methods return the element instance for chaining.
HTMLRewriter element content manipulation methods
Element content methods: setInnerContent(content) sets inner content and escapes HTML by default; setInnerContent(content, { html: true }) parses HTML; before(content) inserts before the element; after(content) inserts after the element; prepend(content) inserts as first child; append(content) appends as last child. All support { html: true } option. All methods return the element for chaining.
HTMLRewriter element removal methods
Element removal in HTMLRewriter: remove() removes the element and all its contents; removeAndKeepContent() removes only the element tags but keeps the content inside.
HTMLRewriter element properties
HTMLRewriter element properties: tagName returns the lowercase tag name; namespaceURI returns the element's namespace URI; selfClosing is a boolean indicating if the element is self-closing (e.g. <div />); canHaveContent is a boolean indicating if the element can contain content (false for void elements like <br>); removed is a boolean indicating if the element was removed.
HTMLRewriter element attributes iteration
HTMLRewriter elements support iterating over attributes using: for (const [name, value] of el.attributes) { /* ... */ }
HTMLRewriter onEndTag method
The onEndTag(callback) method on elements handles the end tag. The callback receives an endTag object with methods: before(content) inserts before the end tag, after(content) inserts after the end tag, remove() removes the end tag, and a name property containing the tag name in lowercase.
HTMLRewriter text node operations
Text nodes in HTMLRewriter have: text property for the text content, lastInTextNode boolean indicating if this is the last chunk, removed boolean indicating if text was removed. Methods: before(content) inserts before text, after(content) inserts after text, replace(content) replaces the text, remove() removes the text. All support { html: true } option and return the text instance for chaining.
HTMLRewriter comment operations
Comment nodes in HTMLRewriter have: text property for comment content (readable and writable), removed boolean indicating if comment was removed. Methods: before(content), after(content), replace(content), remove(). All support { html: true } option and return the comment instance for chaining.
HTMLRewriter.onDocument() method
The onDocument(handlers) method registers handlers for document-level events. Handlers can define: doctype(doctype) with properties name, publicId, systemId; text(text) for text nodes; comments(comment) for comments; end(end) called at document end with end.append(content, options) to append content.
HTMLRewriter CSS selector support
HTMLRewriter supports CSS selectors: tag selectors (p), class selectors (p.red), ID selectors (h1#header), attribute selectors (p[data-test], p[data-test="one"], p[data-test="one" i] case-insensitive, p[data-test="one" s] case-sensitive, p[data-test~="two"] word match, p[data-test^="a"] starts with, p[data-test$="1"] ends with, p[data-test*="b"] contains, p[data-test|="a"] dash-separated), combinators (div span descendant, div > span direct child), pseudo-classes (p:nth-child(2), p:first-child, p:nth-of-type(2), p:first-of-type, p:not(:first-child)), and universal selector (*).
HTMLRewriter async handler behavior with string and ArrayBuffer
When transform(string) or transform(ArrayBuffer) is called with an async handler that requires the event loop (timers, I/O, fetch), it throws TypeError immediately. A handler whose Promise settles within a microtask checkpoint (no event loop needed, including process.nextTick and already-resolved Promises) still works with transform(string). Pass a Response to transform() when handlers might await real work.
HTMLRewriter transform() error handling
For string/ArrayBuffer input, transform() throws synchronously for: invalid selector syntax, invalid input types, body already used errors, and errors from content handlers. For Response input, transform() returns immediately and errors surface on the output body instead, including handler errors, rejected Promises, malformed input, stream errors, and memory allocation failures. Detached Promise rejections go to process-global unhandledRejection.
HTMLRewriter Response transformation behavior
When transforming a Response, the status code, headers, and other response properties are preserved. The body is transformed while maintaining streaming capabilities. Content-encoding like gzip is handled automatically. The original response body is marked as used after transformation. Headers are cloned to the new response.
HTMLRewriter basic rickroll example
Example showing HTMLRewriter usage: const rewriter = new HTMLRewriter().on("img", { element(img) { img.setAttribute("src", "https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg"); img.before('<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">', { html: true }); img.after("</a>", { html: true }); img.setAttribute("alt", "Definitely not a rickroll"); } }); const html = `<html><body><img src="/cat.jpg"><img src="dog.png"><img src="https://example.com/bird.webp"></body></html>`; const result = rewriter.transform(html);
HTMLRewriter async element handler example
Example of async element handler: rewriter.on("div", { async element(element) { const fragment = await fetch("https://example.com/fragment").then(r => r.text()); element.setInnerContent(fragment, { html: true }); } });
HTMLRewriter error handling example with Response
Example of error handling with Response: try { const output = await rewriter.transform(new Response(html)).text(); } catch (error) { console.error("a handler failed:", error); }
HTMLRewriter async handler microtask limitation
Example showing TypeError when async handler needs event loop with string input: new HTMLRewriter().on("div", { async element(element) { await Bun.sleep(1000); } }).transform("<div></div>"); throws: TypeError: HTMLRewriter.transform() cannot synchronously return a string because a content handler returned a Promise that did not resolve within a microtask. Pass a Response instead and await its body
Bun.JSON5.stringify() - convert JavaScript value to JSON5 string
Bun.JSON5.stringify() converts a JavaScript value to a JSON5 string. It accepts a second parameter (replacer, typically null) and a third parameter for space (indentation). The space parameter can be a number (spaces count) or a string (indent character). Unlike JSON.stringify, it preserves special numeric values like Infinity and NaN.
JSON5 supported features in Bun
Bun's JSON5 parser supports: comments (single-line // and multi-line /* */), trailing commas in objects and arrays, unquoted keys (valid ECMAScript 5.1 identifiers), single-quoted strings in addition to double-quoted, multi-line strings using backslash line continuations, hex numbers (0xFF), leading and trailing decimal points (.5 and 5.), Infinity and NaN (positive and negative), and explicit plus sign (+42).
JSON5 parser conformance in Bun
Bun's JSON5 parser is written in Rust and passes 100% of the official JSON5 test suite.
Bun.JSON5.parse() example with JSON5 features
Example showing Bun.JSON5.parse() with JSON5 features:
```ts
import { JSON5 } from "bun";
const data = JSON5.parse(`{
// JSON5 supports comments
name: 'my-app',
version: '1.0.0',
debug: true,
// trailing commas are allowed
tags: ['web', 'api',],
}`);
console.log(data);
// {
// name: "my-app",
// version: "1.0.0",
// debug: true,
// tags: ["web", "api"]
// }
```
Bun.JSON5.stringify() example with pretty printing
Example showing Bun.JSON5.stringify() with space parameter for pretty printing:
```ts
import { JSON5 } from "bun";
const pretty = JSON5.stringify(
{
name: "my-app",
debug: true,
tags: ["web", "api"],
},
null,
2,
);
console.log(pretty);
// {
// name: 'my-app',
// debug: true,
// tags: [
// 'web',
// 'api',
// ],
// }
```
The space argument can also be a string like "\t" for tab indentation.
JSON5.parse() error handling
Bun.JSON5.parse() throws a SyntaxError if the input is invalid JSON5. Wrap calls in try-catch to handle parsing errors.
JSON5.stringify() special value handling
Unlike JSON.stringify, JSON5.stringify preserves special numeric values. It outputs Infinity, -Infinity, and NaN as-is in the JSON5 string.
Bun.JSON5.parse() - parse JSON5 string to JavaScript value
Bun.JSON5.parse() parses a JSON5 string into a JavaScript value. It is imported from the 'bun' module. If the input is invalid JSON5, it throws a SyntaxError.
Bun.JSONL.parseChunk() error recovery
Unlike parse(), parseChunk() does not throw on invalid JSON. Instead, it returns the error in the error property, along with any values that were successfully parsed before the error. The read property indicates the position up to the last successful parse.
Bun.JSONL.parse() basic usage
Bun.JSONL.parse() parses a complete JSONL (newline-delimited JSON) input and returns an array of all parsed values. Each line in the input must be a separate JSON value. The input can be a string or a Uint8Array. When Uint8Array input is used, Bun automatically skips a UTF-8 BOM at the start of the buffer.
Bun.JSONL.parse() error handling
If the input contains invalid JSON and no values were successfully parsed, Bun.JSONL.parse() throws a SyntaxError. If at least one value was parsed before the error, the parsed values are returned without throwing.
Bun.JSONL.parse() with Uint8Array
Bun.JSONL.parse() accepts Uint8Array as input in addition to strings. Example: const buffer = new TextEncoder().encode('{"a":1}\n{"b":2}\n'); const results = Bun.JSONL.parse(buffer); // [{ a: 1 }, { b: 2 }]
Bun.JSONL.parseChunk() for streaming
Bun.JSONL.parseChunk() parses as many complete JSON values as it can from input and reports how far it got, enabling incremental parsing from network streams or other sources. It returns an object with properties: values (any[]), read (number of bytes or characters consumed), done (boolean indicating if entire input consumed), and error (SyntaxError or null).
Bun.JSONL.parseChunk() return object properties
The parseChunk() method returns an object with four properties: 'values' (type: any[], description: Array of successfully parsed JSON values), 'read' (type: number, description: Number of bytes for Uint8Array or characters for strings consumed), 'done' (type: boolean, description: true if entire input consumed with no remaining data), 'error' (type: SyntaxError | null, description: Parse error or null if no error occurred).
Bun.JSONL.parseChunk() with byte offsets
When input is a Uint8Array, parseChunk() accepts optional start and end byte offset parameters: Bun.JSONL.parseChunk(buf, start) or Bun.JSONL.parseChunk(buf, start, end). The read value returned is always a byte offset into the original buffer, suitable for use with TypedArray.subarray() for zero-copy streaming.
JSONL supported value types
Each line in JSONL input can be any valid JSON value, not just objects. This includes primitives (numbers, strings, booleans, null) and collections (arrays, objects).
Bun.JSONL.parse() example with multiple records
Example showing parsing multiple records: import { JSONL } from "bun"; const input = '{"id":1,"name":"Alice"}\n{"id":2,"name":"Bob"}\n{"id":3,"name":"Charlie"}\n'; const records = JSONL.parse(input); // [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }, { id: 3, name: "Charlie" }]