declare namespace HTMLRewriterTypes {
	interface HTMLRewriterElementContentHandlers {
		element?(element: Element): void | Promise<void>;
		comments?(comment: Comment): void | Promise<void>;
		text?(text: Text): void | Promise<void>;
	}

	interface HTMLRewriterDocumentContentHandlers {
		doctype?(doctype: Doctype): void | Promise<void>;
		comments?(comment: Comment): void | Promise<void>;
		text?(text: Text): void | Promise<void>;
		end?(end: DocumentEnd): void | Promise<void>;
	}

	interface Text {
		readonly text: string;
		readonly lastInTextNode: boolean;
		readonly removed: boolean;
		before(content: Content, options?: ContentOptions): Text;
		after(content: Content, options?: ContentOptions): Text;
		replace(content: Content, options?: ContentOptions): Text;
		remove(): Text;
	}

	interface Doctype {
		readonly name: string | null;
		readonly publicId: string | null;
		readonly systemId: string | null;
	}

	interface DocumentEnd {
		append(content: Content, options?: ContentOptions): DocumentEnd;
	}

	interface ContentOptions {
		html?: boolean;
	}
	type Content = string;

	interface Comment {
		text: string;
		readonly removed: boolean;
		before(content: Content, options?: ContentOptions): Comment;
		after(content: Content, options?: ContentOptions): Comment;
		replace(content: Content, options?: ContentOptions): Comment;
		remove(): Comment;
	}

	interface Element {
		tagName: string;
		readonly attributes: IterableIterator<string[]>;
		readonly removed: boolean;
		/** Whether the element is explicitly self-closing, e.g. `<foo />` */
		readonly selfClosing: boolean;
		/**
		 * Whether the element can have inner content. Returns `true` unless
		 * - the element is an [HTML void element](https://html.spec.whatwg.org/multipage/syntax.html#void-elements)
		 * - or it's self-closing in a foreign context (eg. in SVG, MathML).
		 */
		readonly canHaveContent: boolean;
		readonly namespaceURI: string;
		getAttribute(name: string): string | null;
		hasAttribute(name: string): boolean;
		setAttribute(name: string, value: string): Element;
		removeAttribute(name: string): Element;
		before(content: Content, options?: ContentOptions): Element;
		after(content: Content, options?: ContentOptions): Element;
		prepend(content: Content, options?: ContentOptions): Element;
		append(content: Content, options?: ContentOptions): Element;
		replace(content: Content, options?: ContentOptions): Element;
		remove(): Element;
		removeAndKeepContent(): Element;
		setInnerContent(content: Content, options?: ContentOptions): Element;
		onEndTag(handler: (tag: EndTag) => void | Promise<void>): void;
	}

	interface EndTag {
		name: string;
		before(content: Content, options?: ContentOptions): EndTag;
		after(content: Content, options?: ContentOptions): EndTag;
		remove(): EndTag;
	}
}

/**
 * [HTMLRewriter](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter?bun) is a fast API for transforming HTML.
 *
 * Bun leverages a native implementation powered by [lol-html](https://github.com/cloudflare/lol-html).
 *
 * HTMLRewriter can be used to transform HTML in a variety of ways, including:
 * * Rewriting URLs
 * * Adding meta tags
 * * Removing elements
 * * Adding elements to the head
 *
 * @example
 * ```ts
 * const rewriter = new HTMLRewriter().on('a[href]', {
 *   element(element: Element) {
 *     // Rewrite all the URLs to this youtube video
 *     element.setAttribute('href', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ');
 *   }
 * });
 * rewriter.transform(await fetch("https://remix.run"));
 * ```
 */
declare class HTMLRewriter {
	constructor();
	on(
		selector: string,
		handlers: HTMLRewriterTypes.HTMLRewriterElementContentHandlers,
	): HTMLRewriter;
	onDocument(
		handlers: HTMLRewriterTypes.HTMLRewriterDocumentContentHandlers,
	): HTMLRewriter;
	/**
	 * @param input - The HTML to transform
	 * @returns A new {@link Response} with the transformed HTML
	 */
	transform(input: Response | Blob | Bun.BufferSource): Response;
	/**
	 * @param input - The HTML string to transform
	 * @returns A new {@link String} containing the transformed HTML
	 */
	transform(input: string): string;
	/**
	 * @param input - The HTML to transform as a {@link ArrayBuffer}
	 * @returns A new {@link ArrayBuffer} with the transformed HTML
	 */
	transform(input: ArrayBuffer): ArrayBuffer;
}
