{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Web-standard middleware that converts HTML responses to Markdown\n * when the client sends an `Accept: text/markdown` header.\n *\n * Compatible with any runtime that supports the Fetch API\n * (Cloudflare Workers, Deno, Bun, etc.).\n *\n * ```ts\n * import { markdownMiddleware } from \"@markdown-for-agents/web\";\n *\n * const md = markdownMiddleware({ extract: true });\n * const response = await md(request, handler);\n * ```\n * @module\n */\n\nimport { convert, buildContentSignalHeader } from 'markdown-for-agents';\nimport type { MiddlewareOptions } from 'markdown-for-agents';\n\nexport type { MiddlewareOptions } from 'markdown-for-agents';\n\n/** A request handler that produces a `Response` (sync or async). */\ntype Handler = (request: Request) => Response | Promise<Response>;\n/** A middleware function that wraps a {@link Handler} with pre/post-processing. */\ntype Middleware = (request: Request, next: Handler) => Response | Promise<Response>;\n\n/**\n * Web-standard middleware that converts HTML responses to markdown\n * when the client sends an `Accept: text/markdown` header.\n *\n * Compatible with any runtime that supports the Fetch API\n * (Cloudflare Workers, Deno, Bun, etc.).\n *\n * @param options - Conversion and middleware options.\n * @returns A middleware function that wraps a {@link Handler}.\n *\n * @example\n * ```ts\n * import { markdownMiddleware } from \"@markdown-for-agents/web\";\n *\n * const md = markdownMiddleware({ extract: true });\n * const response = await md(request, handler);\n * ```\n */\nexport function markdownMiddleware(options?: MiddlewareOptions): Middleware {\n    const tokenHeader = options?.tokenHeader ?? 'x-markdown-tokens';\n    const timingHeader = options?.timingHeader ?? 'x-markdown-timing';\n\n    return async (request: Request, next: Handler): Promise<Response> => {\n        const response = await next(request);\n\n        // Always signal that responses vary by Accept so caches store\n        // separate entries for HTML and Markdown representations.\n        response.headers.append('vary', 'Accept');\n\n        const accept = request.headers.get('accept') ?? '';\n        if (!accept.includes('text/markdown')) {\n            return response;\n        }\n\n        const contentType = response.headers.get('content-type') ?? '';\n\n        if (!contentType.includes('text/html')) {\n            return response;\n        }\n\n        const html = await response.text();\n\n        const { markdown, tokenEstimate, contentHash, convertDuration } = convert(html, options);\n\n        const headers = new Headers(response.headers);\n        headers.set('content-type', 'text/markdown; charset=utf-8');\n        headers.set(tokenHeader, String(tokenEstimate.tokens));\n        headers.set('etag', `\"${contentHash}\"`);\n        if (convertDuration !== undefined) {\n            const timingValue = `mfa.convert;dur=${convertDuration.toFixed(1)};desc=\"HTML to Markdown\"`;\n            headers.set('server-timing', timingValue);\n            headers.set(timingHeader, timingValue);\n        }\n        if (options?.contentSignal) {\n            const signalValue = buildContentSignalHeader(options.contentSignal);\n            if (signalValue) headers.set('content-signal', signalValue);\n        }\n\n        return new Response(markdown, {\n            status: response.status,\n            statusText: response.statusText,\n            headers\n        });\n    };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,SAAgB,mBAAmB,SAAyC;CACxE,MAAM,cAAc,SAAS,eAAe;CAC5C,MAAM,eAAe,SAAS,gBAAgB;AAE9C,QAAO,OAAO,SAAkB,SAAqC;EACjE,MAAM,WAAW,MAAM,KAAK,QAAQ;AAIpC,WAAS,QAAQ,OAAO,QAAQ,SAAS;AAGzC,MAAI,EADW,QAAQ,QAAQ,IAAI,SAAS,IAAI,IACpC,SAAS,gBAAgB,CACjC,QAAO;AAKX,MAAI,EAFgB,SAAS,QAAQ,IAAI,eAAe,IAAI,IAE3C,SAAS,YAAY,CAClC,QAAO;EAKX,MAAM,EAAE,UAAU,eAAe,aAAa,oBAAoB,QAFrD,MAAM,SAAS,MAAM,EAE8C,QAAQ;EAExF,MAAM,UAAU,IAAI,QAAQ,SAAS,QAAQ;AAC7C,UAAQ,IAAI,gBAAgB,+BAA+B;AAC3D,UAAQ,IAAI,aAAa,OAAO,cAAc,OAAO,CAAC;AACtD,UAAQ,IAAI,QAAQ,IAAI,YAAY,GAAG;AACvC,MAAI,oBAAoB,KAAA,GAAW;GAC/B,MAAM,cAAc,mBAAmB,gBAAgB,QAAQ,EAAE,CAAC;AAClE,WAAQ,IAAI,iBAAiB,YAAY;AACzC,WAAQ,IAAI,cAAc,YAAY;;AAE1C,MAAI,SAAS,eAAe;GACxB,MAAM,cAAc,yBAAyB,QAAQ,cAAc;AACnE,OAAI,YAAa,SAAQ,IAAI,kBAAkB,YAAY;;AAG/D,SAAO,IAAI,SAAS,UAAU;GAC1B,QAAQ,SAAS;GACjB,YAAY,SAAS;GACrB;GACH,CAAC"}