/** * Bun.js runtime APIs * * @example * * ```js * import {file} from 'bun'; * * // Log the file to the console * const input = await file('/path/to/file.txt').text(); * console.log(input); * ``` * * This module aliases `globalThis.Bun`. */ declare module "bun" { type PathLike = string | NodeJS.TypedArray | ArrayBufferLike | URL; type ArrayBufferView = | NodeJS.TypedArray | DataView; type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; type XMLHttpRequestBodyInit = Blob | BufferSource | FormData | URLSearchParams | string; type ReadableStreamController = ReadableStreamDefaultController; type ReadableStreamDefaultReadResult = | ReadableStreamDefaultReadValueResult | ReadableStreamDefaultReadDoneResult; type ReadableStreamReader = ReadableStreamDefaultReader; type Transferable = ArrayBuffer | MessagePort; type MessageEventSource = Bun.__internal.UseLibDomIfAvailable<"MessageEventSource", undefined>; type Encoding = "utf-8" | "windows-1252" | "utf-16"; type UncaughtExceptionOrigin = "uncaughtException" | "unhandledRejection"; type MultipleResolveType = "resolve" | "reject"; type BeforeExitListener = (code: number) => void; type DisconnectListener = () => void; type ExitListener = (code: number) => void; type RejectionHandledListener = (promise: Promise) => void; type FormDataEntryValue = File | string; type WarningListener = (warning: Error) => void; type MessageListener = (message: unknown, sendHandle: unknown) => void; type SignalsListener = (signal: NodeJS.Signals) => void; type BlobPart = string | Blob | BufferSource; type TimerHandler = (...args: any[]) => void; type DOMHighResTimeStamp = number; type EventListenerOrEventListenerObject = EventListener | EventListenerObject; type BlobOrStringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike | Blob; type MaybePromise = T | Promise; namespace __internal { type LibDomIsLoaded = typeof globalThis extends { onabort: any } ? true : false; /** * Helper type for avoiding conflicts in types. * * Uses the lib.dom.d.ts definition if it exists, otherwise defines it locally. * * This is to avoid type conflicts between lib.dom.d.ts and \@types/bun. * * Unfortunately some symbols cannot be defined when both Bun types and lib.dom.d.ts types are loaded, * and since we can't redeclare the symbol in a way that satisfies both, we need to fallback * to the type that lib.dom.d.ts provides. */ type UseLibDomIfAvailable = // `onabort` is defined in lib.dom.d.ts, so we can check to see if lib dom is loaded by checking if `onabort` is defined LibDomIsLoaded extends true ? typeof globalThis extends { [K in GlobalThisKeyName]: infer T } // if it is loaded, infer it from `globalThis` and use that value ? T : Otherwise // Not defined in lib dom (or anywhere else), so no conflict. We can safely use our own definition : Otherwise; // Lib dom not loaded anyway, so no conflict. We can safely use our own definition /** * Like Omit, but correctly distributes over unions. Most useful for removing * properties from union options objects, like {@link Bun.SQL.Options} * * @example * ```ts * type X = Bun.DistributedOmit<{type?: 'a', url?: string} | {type?: 'b', flag?: boolean}, "url"> * // `{type?: 'a'} | {type?: 'b', flag?: boolean}` (Omit applied to each union item instead of entire type) * * type X = Omit<{type?: 'a', url?: string} | {type?: 'b', flag?: boolean}, "url">; * // `{type?: "a" | "b" | undefined}` (Missing `flag` property and no longer a union) * ``` */ type DistributedOmit = T extends T ? Omit : never; type KeysInBoth = Extract; type MergeInner = Omit> & Omit> & { [Key in KeysInBoth]: A[Key] | B[Key]; }; type Merge = MergeInner & MergeInner; type DistributedMerge = T extends T ? Merge> : never; type Without = A & { [Key in Exclude]?: never; }; type XOR = Without | Without; } interface ErrorEventInit extends EventInit { colno?: number; error?: any; filename?: string; lineno?: number; message?: string; } interface CloseEventInit extends EventInit { code?: number; reason?: string; wasClean?: boolean; } interface MessageEventInit extends EventInit { data?: T; lastEventId?: string; origin?: string; source?: Bun.MessageEventSource | null; } interface EventInit { bubbles?: boolean; cancelable?: boolean; composed?: boolean; } interface EventListenerOptions { capture?: boolean; } interface CustomEventInit extends Bun.EventInit { detail?: T; } /** A message received by a target object. */ interface BunMessageEvent extends Event { /** Returns the data of the message. */ readonly data: T; /** Returns the last event ID string, for server-sent events. */ readonly lastEventId: string; /** Returns the origin of the message, for server-sent events and cross-document messaging. */ readonly origin: string; /** Returns the MessagePort array sent with the message, for cross-document messaging and channel messaging. */ readonly ports: readonly MessagePort[]; // ReadonlyArray; readonly source: Bun.MessageEventSource | null; } type MessageEvent = Bun.__internal.UseLibDomIfAvailable<"MessageEvent", BunMessageEvent>; interface ReadableStreamDefaultReadManyResult { done: boolean; /** Number of bytes */ size: number; value: T[]; } interface EventSourceEventMap { error: Event; message: MessageEvent; open: Event; } interface AddEventListenerOptions extends EventListenerOptions { /** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */ once?: boolean; /** When `true`, serves as a hint that the listener will not call the `Event` object's `preventDefault()` method. Default: false. */ passive?: boolean; signal?: AbortSignal; } interface EventListener { (evt: Event): void; } interface EventListenerObject { handleEvent(object: Event): void; } interface FetchEvent extends Event { readonly request: Request; readonly url: string; waitUntil(promise: Promise): void; respondWith(response: Response | Promise): void; } interface EventMap { fetch: FetchEvent; message: MessageEvent; messageerror: MessageEvent; // exit: Event; } interface StructuredSerializeOptions { transfer?: Bun.Transferable[]; } interface EventSource extends EventTarget { new (url: string | URL, eventSourceInitDict?: EventSourceInit): EventSource; onerror: ((this: EventSource, ev: Event) => any) | null; onmessage: ((this: EventSource, ev: MessageEvent) => any) | null; onopen: ((this: EventSource, ev: Event) => any) | null; /** Returns the state of this EventSource object's connection. It can have the values described below. */ readonly readyState: number; /** Returns the URL providing the event stream. */ readonly url: string; /** Returns true if the credentials mode for connection requests to the URL providing the event stream is set to "include", and false otherwise. * * Not supported in Bun */ readonly withCredentials: boolean; /** Aborts any instances of the fetch algorithm started for this EventSource object, and sets the readyState attribute to CLOSED. */ close(): void; readonly CLOSED: 2; readonly CONNECTING: 0; readonly OPEN: 1; addEventListener( type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions, ): void; addEventListener( type: string, listener: (this: EventSource, event: MessageEvent) => any, options?: boolean | AddEventListenerOptions, ): void; addEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions, ): void; removeEventListener( type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | EventListenerOptions, ): void; removeEventListener( type: string, listener: (this: EventSource, event: MessageEvent) => any, options?: boolean | EventListenerOptions, ): void; removeEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions, ): void; /** * Keep the event loop alive while connection is open or reconnecting * * Not available in browsers */ ref(): void; /** * Do not keep the event loop alive while connection is open or reconnecting * * Not available in browsers */ unref(): void; } interface TransformerFlushCallback { (controller: TransformStreamDefaultController): void | PromiseLike; } interface TransformerStartCallback { (controller: TransformStreamDefaultController): any; } interface TransformerTransformCallback { (chunk: I, controller: TransformStreamDefaultController): void | PromiseLike; } interface UnderlyingSinkAbortCallback { (reason?: any): void | PromiseLike; } interface UnderlyingSinkCloseCallback { (): void | PromiseLike; } interface UnderlyingSinkStartCallback { (controller: WritableStreamDefaultController): any; } interface UnderlyingSinkWriteCallback { (chunk: W, controller: WritableStreamDefaultController): void | PromiseLike; } interface UnderlyingSourceCancelCallback { (reason?: any): void | PromiseLike; } interface UnderlyingSink { abort?: UnderlyingSinkAbortCallback; close?: UnderlyingSinkCloseCallback; start?: UnderlyingSinkStartCallback; type?: undefined | "default" | "bytes"; write?: UnderlyingSinkWriteCallback; } interface UnderlyingSource { cancel?: UnderlyingSourceCancelCallback; pull?: UnderlyingSourcePullCallback; start?: UnderlyingSourceStartCallback; /** * Mode "bytes" is not currently supported. */ type?: undefined; } interface DirectUnderlyingSource { cancel?: UnderlyingSourceCancelCallback; pull: (controller: ReadableStreamDirectController) => void | PromiseLike; type: "direct"; } interface UnderlyingSourcePullCallback { (controller: ReadableStreamController): void | PromiseLike; } interface UnderlyingSourceStartCallback { (controller: ReadableStreamController): any; } interface GenericTransformStream { readonly readable: ReadableStream; readonly writable: WritableStream; } interface AbstractWorkerEventMap { error: ErrorEvent; } interface WorkerEventMap extends AbstractWorkerEventMap { message: MessageEvent; messageerror: MessageEvent; close: CloseEvent; open: Event; } type WorkerType = "classic" | "module"; interface AbstractWorker { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ServiceWorker/error_event) */ onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null; addEventListener( type: K, listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, options?: boolean | AddEventListenerOptions, ): void; addEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions, ): void; removeEventListener( type: K, listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, options?: boolean | EventListenerOptions, ): void; removeEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions, ): void; } /** * Bun's Web Worker constructor supports some extra options on top of the API browsers have. */ interface WorkerOptions { /** * A string specifying an identifying name for the DedicatedWorkerGlobalScope representing the scope of * the worker, which is mainly useful for debugging purposes. */ name?: string; /** * Use less memory, but make the worker slower. * * Internally, this sets the heap size configuration in JavaScriptCore to be * the small heap instead of the large heap. */ smol?: boolean; /** * When `true`, the worker will keep the parent thread alive until the worker is terminated or `unref`'d. * When `false`, the worker will not keep the parent thread alive. * * By default, this is `false`. */ ref?: boolean; /** * In Bun, this does nothing. */ type?: Bun.WorkerType | undefined; /** * List of arguments which would be stringified and appended to * `Bun.argv` / `process.argv` in the worker. This is mostly similar to the `data` * but the values will be available on the global `Bun.argv` as if they * were passed as CLI options to the script. */ argv?: any[] | undefined; /** If `true` and the first argument is a string, interpret the first argument to the constructor as a script that is executed once the worker is online. */ // eval?: boolean | undefined; /** * If set, specifies the initial value of process.env inside the Worker thread. As a special value, worker.SHARE_ENV may be used to specify that the parent thread and the child thread should share their environment variables; in that case, changes to one thread's process.env object affect the other thread as well. Default: process.env. */ env?: Record | (typeof import("node:worker_threads"))["SHARE_ENV"] | undefined; /** * In Bun, this does nothing. */ credentials?: import("undici-types").RequestCredentials | undefined; /** * @default true */ // trackUnmanagedFds?: boolean; // resourceLimits?: import("worker_threads").ResourceLimits; /** * An array of module specifiers to preload in the worker. * * These modules load before the worker's entry point is executed. * * Equivalent to passing the `--preload` CLI argument, but only for this Worker. */ preload?: string[] | string | undefined; } interface Worker extends EventTarget, AbstractWorker { /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/message_event) */ onmessage: ((this: Worker, ev: MessageEvent) => any) | null; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/messageerror_event) */ onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null; /** * Clones message and transmits it to worker's global environment. transfer can be passed as a list of objects that are to be transferred rather than cloned. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/postMessage) */ postMessage(message: any, transfer: Transferable[]): void; postMessage(message: any, options?: StructuredSerializeOptions): void; /** * Aborts worker's associated global environment. * * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/terminate) */ terminate(): void; addEventListener( type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, options?: boolean | AddEventListenerOptions, ): void; addEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions, ): void; removeEventListener( type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, options?: boolean | EventListenerOptions, ): void; removeEventListener( type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions, ): void; /** * Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does _not_ let the program exit if it's the only active handle left (the default * behavior). If the worker is `ref()`ed, calling `ref()` again has * no effect. * @since v10.5.0 */ ref(): void; /** * Calling `unref()` on a worker allows the thread to exit if this is the only * active handle in the event system. If the worker is already `unref()`ed calling`unref()` again has no effect. * @since v10.5.0 */ unref(): void; /** * An integer identifier for the referenced thread. Inside the worker thread, * it is available as `require('node:worker_threads').threadId`. * This value is unique for each `Worker` instance inside a single process. * @since v10.5.0 */ threadId: number; } interface Env { NODE_ENV?: string; /** * Can be used to change the default timezone at runtime */ TZ?: string; } /** * The environment variables of the process * * Defaults to `process.env` as it was when the current Bun process launched. * * Changes to `process.env` at runtime won't automatically be reflected in the default value. For that, you can pass `process.env` explicitly. */ const env: Env & NodeJS.ProcessEnv & ImportMetaEnv; /** * The raw arguments passed to the process, including flags passed to Bun. If you want to easily read flags passed to your script, consider using `process.argv` instead. */ const argv: string[]; interface WhichOptions { /** * Overrides the PATH environment variable */ PATH?: string; /** * When given a relative path, use this path to join it. */ cwd?: string; } /** * Find the path to an executable, similar to typing which in your terminal. Reads the `PATH` environment variable unless overridden with `options.PATH`. * * @category Utilities * * @param command The name of the executable or script to find * @param options Options for the search */ function which(command: string, options?: WhichOptions): string | null; interface StringWidthOptions { /** * If `true`, count ANSI escape codes as part of the string width. If `false`, ANSI escape codes are ignored when calculating the string width. * * @default false */ countAnsiEscapeCodes?: boolean; /** * When it's ambiugous and `true`, count emoji as 1 characters wide. If `false`, emoji are counted as 2 character wide. * * @default true */ ambiguousIsNarrow?: boolean; } /** * Get the column count of a string as it would be displayed in a terminal. * Supports ANSI escape codes, emoji, and wide characters. * * This is useful for: * - Aligning text in a terminal * - Quickly checking if a string contains ANSI escape codes * - Measuring the width of a string in a terminal * * This API is designed to match the popular "string-width" package, so that * existing code can be easily ported to Bun and vice versa. * * @returns The width of the string in columns * * @example * ```ts * import { stringWidth } from "bun"; * * console.log(stringWidth("abc")); // 3 * console.log(stringWidth("πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘¦")); // 1 * console.log(stringWidth("\u001b[31mhello\u001b[39m")); // 5 * console.log(stringWidth("\u001b[31mhello\u001b[39m", { countAnsiEscapeCodes: false })); // 5 * console.log(stringWidth("\u001b[31mhello\u001b[39m", { countAnsiEscapeCodes: true })); // 13 * ``` */ function stringWidth( /** * The string to measure */ input: string, options?: StringWidthOptions, ): number; /** * Remove ANSI escape codes from a string. * * @category Utilities * * @param input The string to remove ANSI escape codes from. * @returns The string with ANSI escape codes removed. * * @example * ```ts * import { stripANSI } from "bun"; * * console.log(stripANSI("\u001b[31mhello\u001b[39m")); // "hello" * ``` */ function stripANSI(input: string): string; interface WrapAnsiOptions { /** * If `true`, break words in the middle if they don't fit on a line. * If `false`, only break at word boundaries. * * @default false */ hard?: boolean; /** * If `true`, wrap at word boundaries when possible. * If `false`, don't perform word wrapping (only wrap at explicit newlines). * * @default true */ wordWrap?: boolean; /** * If `true`, trim leading and trailing whitespace from each line. * If `false`, preserve whitespace. * * @default true */ trim?: boolean; /** * When it's ambiguous and `true`, count ambiguous width characters as 1 character wide. * If `false`, count them as 2 characters wide. * * @default true */ ambiguousIsNarrow?: boolean; } /** * Wrap a string to fit within the specified column width, preserving ANSI escape codes. * * This function is designed to be compatible with the popular "wrap-ansi" NPM package. * * Features: * - Preserves ANSI escape codes (colors, styles) across line breaks * - Supports SGR codes (colors, bold, italic, etc.) and OSC 8 hyperlinks * - Respects Unicode display widths (full-width characters, emoji) * - Word wrapping at word boundaries (configurable) * * @category Utilities * * @param input The string to wrap * @param columns The maximum column width * @param options Wrapping options * @returns The wrapped string * * @example * ```ts * import { wrapAnsi } from "bun"; * * console.log(wrapAnsi("hello world", 5)); * // Output: * // hello * // world * * // Preserves ANSI colors across line breaks * console.log(wrapAnsi("\u001b[31mhello world\u001b[0m", 5)); * // Output: * // \u001b[31mhello\u001b[0m * // \u001b[31mworld\u001b[0m * * // Hard wrap long words * console.log(wrapAnsi("abcdefghij", 3, { hard: true })); * // Output: * // abc * // def * // ghi * // j * ``` */ function wrapAnsi( /** * The string to wrap */ input: string, /** * The maximum column width */ columns: number, /** * Wrapping options */ options?: WrapAnsiOptions, ): string; /** * TOML related APIs */ namespace TOML { /** * Parse a TOML string into a JavaScript object. * * @category Utilities * * @param input The TOML string to parse * @returns A JavaScript object */ export function parse(input: string): object; } /** * JSONC related APIs */ namespace JSONC { /** * Parse a JSONC (JSON with Comments) string into a JavaScript value. * * Supports both single-line (`//`) and block comments (`/* ... *\/`), as well as * trailing commas in objects and arrays. * * @category Utilities * * @param input The JSONC string to parse * @returns A JavaScript value * * @example * ```js * const result = Bun.JSONC.parse(`{ * // This is a comment * "name": "my-app", * "version": "1.0.0", // trailing comma is allowed * }`); * ``` */ export function parse(input: string): unknown; } /** * JSONL (JSON Lines) related APIs. * * Each line in the input is expected to be a valid JSON value separated by newlines. */ namespace JSONL { /** * The result of `Bun.JSONL.parseChunk`. */ interface ParseChunkResult { /** The successfully parsed JSON values. */ values: unknown[]; /** How far into the input was consumed. When the input is a string, this is a character offset. When the input is a `TypedArray`, this is a byte offset. Use `input.slice(read)` or `input.subarray(read)` to get the unconsumed remainder. */ read: number; /** `true` if all input was consumed successfully. `false` if the input ends with an incomplete value or a parse error occurred. */ done: boolean; /** A `SyntaxError` if a parse error occurred, otherwise `null`. Values parsed before the error are still available in `values`. */ error: SyntaxError | null; } /** * Parse a JSONL (JSON Lines) string into an array of JavaScript values. * * If a parse error occurs and no values were successfully parsed, throws * a `SyntaxError`. If values were parsed before the error, returns the * successfully parsed values without throwing. * * Incomplete trailing values (e.g. from a partial chunk) are silently * ignored and not included in the result. * * When a `TypedArray` is passed, the bytes are parsed directly without * copying if the content is ASCII. * * @param input The JSONL string or typed array to parse * @returns An array of parsed values * @throws {SyntaxError} If the input starts with invalid JSON and no values could be parsed * * @example * ```js * const items = Bun.JSONL.parse('{"a":1}\n{"b":2}\n'); * // [{ a: 1 }, { b: 2 }] * * // From a Uint8Array (zero-copy for ASCII): * const buf = new TextEncoder().encode('{"a":1}\n{"b":2}\n'); * const items = Bun.JSONL.parse(buf); * // [{ a: 1 }, { b: 2 }] * * // Partial results on error after valid values: * const partial = Bun.JSONL.parse('{"a":1}\n{bad}\n'); * // [{ a: 1 }] * * // Throws when no valid values precede the error: * Bun.JSONL.parse('{bad}\n'); // throws SyntaxError * ``` */ export function parse(input: string | NodeJS.TypedArray | DataView | ArrayBufferLike): unknown[]; /** * Parse a JSONL chunk, designed for streaming use. * * Never throws on parse errors. Instead, returns whatever values were * successfully parsed along with an `error` property containing the * `SyntaxError` (or `null` on success). Use `read` to determine how * much input was consumed and `done` to check if all input was parsed. * * When a `TypedArray` is passed, the bytes are parsed directly without * copying if the content is ASCII. Optional `start` and `end` parameters * allow slicing without copying, and `read` will be a byte offset into * the original typed array. * * @param input The JSONL string or typed array to parse * @param start Byte offset to start parsing from (typed array only, default: 0) * @param end Byte offset to stop parsing at (typed array only, default: input.byteLength) * @returns An object with `values`, `read`, `done`, and `error` properties * * @example * ```js * let buffer = new Uint8Array(0); * for await (const chunk of stream) { * buffer = Buffer.concat([buffer, chunk]); * const { values, read, error } = Bun.JSONL.parseChunk(buffer); * if (error) throw error; * for (const value of values) handle(value); * buffer = buffer.subarray(read); * } * ``` */ export function parseChunk(input: string): ParseChunkResult; export function parseChunk( input: NodeJS.TypedArray | DataView | ArrayBufferLike, start?: number, end?: number, ): ParseChunkResult; } /** * YAML related APIs */ namespace YAML { /** * Parse a YAML string into a JavaScript value * * @category Utilities * * @param input The YAML string to parse * @returns A JavaScript value * * @example * ```ts * import { YAML } from "bun"; * * console.log(YAML.parse("123")) // 123 * console.log(YAML.parse("null")) // null * console.log(YAML.parse("false")) // false * console.log(YAML.parse("abc")) // "abc" * console.log(YAML.parse("- abc")) // [ "abc" ] * console.log(YAML.parse("abc: def")) // { "abc": "def" } * ``` */ export function parse(input: string): unknown; /** * Convert a JavaScript value into a YAML string. Strings are double quoted if they contain keywords, non-printable or * escaped characters, or if a YAML parser would parse them as numbers. Anchors and aliases are inferred from objects, allowing cycles. * * @category Utilities * * @param input The JavaScript value to stringify. * @param replacer Currently not supported. * @param space A number for how many spaces each level of indentation gets, or a string used as indentation. * Without this parameter, outputs flow-style (single-line) YAML. * With this parameter, outputs block-style (multi-line) YAML. * The number is clamped between 0 and 10, and the first 10 characters of the string are used. * @returns A string containing the YAML document. * * @example * ```ts * import { YAML } from "bun"; * * const input = { * abc: "def", * num: 123 * }; * * // Without space - flow style (single-line) * console.log(YAML.stringify(input)); * // {abc: def,num: 123} * * // With space - block style (multi-line) * console.log(YAML.stringify(input, null, 2)); * // abc: def * // num: 123 * * const cycle = {}; * cycle.obj = cycle; * console.log(YAML.stringify(cycle, null, 2)); * // &1 * // obj: *1 */ export function stringify(input: unknown, replacer?: undefined | null, space?: string | number): string; } /** * Markdown related APIs. * * Provides fast markdown parsing and rendering with three output modes: * - `html()` β€” render to an HTML string * - `render()` β€” render with custom callbacks for each element * - `react()` β€” parse to React-compatible JSX elements * * Supports GFM extensions (tables, strikethrough, task lists, autolinks) and * component overrides to replace default HTML tags with custom components. * * @example * ```tsx * // Render markdown to HTML * const html = Bun.markdown.html("# Hello **world**"); * // "

Hello world

\n" * * // Render with custom callbacks * const ansi = Bun.markdown.render("# Hello **world**", { * heading: (children, { level }) => `\x1b[1m${children}\x1b[0m\n`, * strong: (children) => `\x1b[1m${children}\x1b[22m`, * paragraph: (children) => children + "\n", * }); * * // Render as a React component * function Markdown({ text }: { text: string }) { * return Bun.markdown.react(text); * } * * // With component overrides * const element = Bun.markdown.react("# Hello", { h1: MyHeadingComponent }); * ``` */ namespace markdown { /** * Options for configuring the markdown parser. * * By default, GFM extensions (tables, strikethrough, task lists) are enabled. */ interface Options { /** Enable GFM tables. Default: `true`. */ tables?: boolean; /** Enable GFM strikethrough (`~~text~~`). Default: `true`. */ strikethrough?: boolean; /** Enable GFM task lists (`- [x] item`). Default: `true`. */ tasklists?: boolean; /** Treat soft line breaks as hard line breaks. Default: `false`. */ hardSoftBreaks?: boolean; /** Enable wiki-style links (`[[target]]` or `[[target|label]]`). Default: `false`. */ wikiLinks?: boolean; /** Enable underline syntax (`__text__` renders as `` instead of ``). Default: `false`. */ underline?: boolean; /** Enable LaTeX math (`$inline$` and `$$display$$`). Default: `false`. */ latexMath?: boolean; /** Collapse whitespace in text content. Default: `false`. */ collapseWhitespace?: boolean; /** Allow ATX headers without a space after `#`. Default: `false`. */ permissiveAtxHeaders?: boolean; /** Disable indented code blocks. Default: `false`. */ noIndentedCodeBlocks?: boolean; /** Disable HTML blocks. Default: `false`. */ noHtmlBlocks?: boolean; /** Disable inline HTML spans. Default: `false`. */ noHtmlSpans?: boolean; /** * Enable the GFM tag filter, which replaces `<` with `<` for disallowed * HTML tags (e.g. `