import { ReadableStream , TransformStream } from "stream/web" ; import { Response } from "@miniflare/core" ; import type { HTMLRewriter as BaseHTMLRewriter , DocumentHandlers , ElementHandlers , } from "html-rewriter-wasm" ; import { Response as BaseResponse } from "undici" ; type SelectorElementHandlers = [ selector : string , handlers : ElementHandlers ] ; export class HTMLRewriter { readonly #elementHandlers : SelectorElementHandlers [ ] = [ ] ; readonly #documentHandlers : DocumentHandlers [ ] = [ ] ; on ( selector , handlers ) { this . #elementHandlers . push ( [ selector , handlers ] ) ; return this ; } onDocument ( handlers ) { this . #documentHandlers . push ( handlers ) ; return this ; } transform ( response ) { const body = response . body as ReadableStream < Uint8Array > | null ; if ( body === null ) return new Response ( body , response ) ; if ( response instanceof BaseResponse ) { response = new Response ( response . body , response ) ; } let rewriter ; const transformStream = new TransformStream < Uint8Array , Uint8Array > ( { start : async ( controller ) => { const { HTMLRewriter : BaseHTMLRewriter , } = require ( "html-rewriter-wasm" ) ; rewriter = new BaseHTMLRewriter ( ( output ) => { if ( output . length !== 0 ) controller . enqueue ( output ) ; } ) ; for ( const [ selector , handlers ] of this . #elementHandlers ) { rewriter . on ( selector , handlers ) ; } for ( const handlers of this . #documentHandlers ) { rewriter . onDocument ( handlers ) ; } } , transform : ( chunk ) => rewriter . write ( chunk ) , flush : ( ) => rewriter . end ( ) , } ) ; const promise = body . pipeTo ( transformStream . writable ) ; promise . catch ( ( ) => { } ) . finally ( ( ) => rewriter . free ( ) ) ; const res = new Response ( transformStream . readable , response ) ; res . headers . delete ( "Content-Length" ) ; return res ; } }