bun-types 1.1.44-canary.20250111T140551 → 1.1.44-canary.20250113T140648

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ambient.d.ts CHANGED
@@ -7,3 +7,13 @@ declare module "*.toml" {
7
7
  var contents: any;
8
8
  export = contents;
9
9
  }
10
+
11
+ declare module "*.jsonc" {
12
+ var contents: any;
13
+ export = contents;
14
+ }
15
+
16
+ declare module "*/bun.lock" {
17
+ var contents: import("bun").BunLockFile;
18
+ export = contents;
19
+ }
package/bun.d.ts CHANGED
@@ -183,6 +183,8 @@ declare module "bun" {
183
183
  * ```
184
184
  */
185
185
  blob(): Blob;
186
+
187
+ bytes(): Uint8Array;
186
188
  }
187
189
 
188
190
  class ShellPromise extends Promise<ShellOutput> {
@@ -2752,8 +2754,230 @@ declare module "bun" {
2752
2754
  logs: Array<BuildMessage | ResolveMessage>;
2753
2755
  }
2754
2756
 
2757
+ /**
2758
+ * Bundles JavaScript, TypeScript, CSS, HTML and other supported files into optimized outputs.
2759
+ *
2760
+ * @param {Object} config - Build configuration options
2761
+ * @returns {Promise<BuildOutput>} Promise that resolves to build output containing generated artifacts and build status
2762
+ * @throws {AggregateError} When build fails and config.throw is true (default in Bun 1.2+)
2763
+ *
2764
+ * @example Basic usage - Bundle a single entrypoint and check results
2765
+ ```ts
2766
+ const result = await Bun.build({
2767
+ entrypoints: ['./src/index.tsx'],
2768
+ outdir: './dist'
2769
+ });
2770
+
2771
+ if (!result.success) {
2772
+ console.error('Build failed:', result.logs);
2773
+ process.exit(1);
2774
+ }
2775
+ ```
2776
+ *
2777
+ * @example Set up multiple entrypoints with code splitting enabled
2778
+ ```ts
2779
+ await Bun.build({
2780
+ entrypoints: ['./src/app.tsx', './src/admin.tsx'],
2781
+ outdir: './dist',
2782
+ splitting: true,
2783
+ sourcemap: "external"
2784
+ });
2785
+ ```
2786
+ *
2787
+ * @example Configure minification and optimization settings
2788
+ ```ts
2789
+ await Bun.build({
2790
+ entrypoints: ['./src/index.tsx'],
2791
+ outdir: './dist',
2792
+ minify: {
2793
+ whitespace: true,
2794
+ identifiers: true,
2795
+ syntax: true
2796
+ },
2797
+ drop: ['console', 'debugger']
2798
+ });
2799
+ ```
2800
+ *
2801
+ * @example Set up custom loaders and mark packages as external
2802
+ ```ts
2803
+ await Bun.build({
2804
+ entrypoints: ['./src/index.tsx'],
2805
+ outdir: './dist',
2806
+ loader: {
2807
+ '.png': 'dataurl',
2808
+ '.svg': 'file',
2809
+ '.txt': 'text',
2810
+ '.json': 'json'
2811
+ },
2812
+ external: ['react', 'react-dom']
2813
+ });
2814
+ ```
2815
+ *
2816
+ * @example Configure environment variable handling with different modes
2817
+ ```ts
2818
+ // Inline all environment variables
2819
+ await Bun.build({
2820
+ entrypoints: ['./src/index.tsx'],
2821
+ outdir: './dist',
2822
+ env: 'inline'
2823
+ });
2824
+
2825
+ // Only include specific env vars
2826
+ await Bun.build({
2827
+ entrypoints: ['./src/index.tsx'],
2828
+ outdir: './dist',
2829
+ env: 'PUBLIC_*'
2830
+ });
2831
+ ```
2832
+ *
2833
+ * @example Set up custom naming patterns for all output types
2834
+ ```ts
2835
+ await Bun.build({
2836
+ entrypoints: ['./src/index.tsx'],
2837
+ outdir: './dist',
2838
+ naming: {
2839
+ entry: '[dir]/[name]-[hash].[ext]',
2840
+ chunk: 'chunks/[name]-[hash].[ext]',
2841
+ asset: 'assets/[name]-[hash].[ext]'
2842
+ }
2843
+ });
2844
+ ```
2845
+ @example Work with build artifacts in different formats
2846
+ ```ts
2847
+ const result = await Bun.build({
2848
+ entrypoints: ['./src/index.tsx']
2849
+ });
2850
+
2851
+ for (const artifact of result.outputs) {
2852
+ const text = await artifact.text();
2853
+ const buffer = await artifact.arrayBuffer();
2854
+ const bytes = await artifact.bytes();
2855
+
2856
+ new Response(artifact);
2857
+ await Bun.write(artifact.path, artifact);
2858
+ }
2859
+ ```
2860
+ @example Implement comprehensive error handling with position info
2861
+ ```ts
2862
+ try {
2863
+ const result = await Bun.build({
2864
+ entrypoints: ['./src/index.tsx'],
2865
+ throw: true
2866
+ });
2867
+ } catch (e) {
2868
+ const error = e as AggregateError;
2869
+ console.error('Build failed:');
2870
+ for (const msg of error.errors) {
2871
+ if ('position' in msg) {
2872
+ console.error(
2873
+ `${msg.message} at ${msg.position?.file}:${msg.position?.line}:${msg.position?.column}`
2874
+ );
2875
+ } else {
2876
+ console.error(msg.message);
2877
+ }
2878
+ }
2879
+ }
2880
+ ```
2881
+ @example Set up Node.js target with specific configurations
2882
+ ```ts
2883
+ await Bun.build({
2884
+ entrypoints: ['./src/server.ts'],
2885
+ outdir: './dist',
2886
+ target: 'node',
2887
+ format: 'cjs',
2888
+ sourcemap: 'external',
2889
+ minify: false,
2890
+ packages: 'external'
2891
+ });
2892
+ ```
2893
+ *
2894
+ * @example Configure experimental CSS bundling with multiple themes
2895
+ ```ts
2896
+ await Bun.build({
2897
+ entrypoints: [
2898
+ './src/styles.css',
2899
+ './src/themes/dark.css',
2900
+ './src/themes/light.css'
2901
+ ],
2902
+ outdir: './dist/css',
2903
+ experimentalCss: true
2904
+ });
2905
+ ```
2906
+ @example Define compile-time constants and version information
2907
+ ```ts
2908
+ await Bun.build({
2909
+ entrypoints: ['./src/index.tsx'],
2910
+ outdir: './dist',
2911
+ define: {
2912
+ 'process.env.NODE_ENV': JSON.stringify('production'),
2913
+ 'CONSTANTS.VERSION': JSON.stringify('1.0.0'),
2914
+ 'CONSTANTS.BUILD_TIME': JSON.stringify(new Date().toISOString())
2915
+ }
2916
+ });
2917
+ ```
2918
+ @example Create a custom plugin for handling special file types
2919
+ ```ts
2920
+ await Bun.build({
2921
+ entrypoints: ['./src/index.tsx'],
2922
+ outdir: './dist',
2923
+ plugins: [
2924
+ {
2925
+ name: 'my-plugin',
2926
+ setup(build) {
2927
+ build.onLoad({ filter: /\.custom$/ }, async (args) => {
2928
+ const content = await Bun.file(args.path).text();
2929
+ return {
2930
+ contents: `export default ${JSON.stringify(content)}`,
2931
+ loader: 'js'
2932
+ };
2933
+ });
2934
+ }
2935
+ }
2936
+ ]
2937
+ });
2938
+ ```
2939
+ @example Enable bytecode generation for faster startup
2940
+ ```ts
2941
+ await Bun.build({
2942
+ entrypoints: ['./src/server.ts'],
2943
+ outdir: './dist',
2944
+ target: 'bun',
2945
+ format: 'cjs',
2946
+ bytecode: true
2947
+ });
2948
+ ```
2949
+ @example Add custom banner and footer to output files
2950
+ ```ts
2951
+ await Bun.build({
2952
+ entrypoints: ['./src/index.tsx'],
2953
+ outdir: './dist',
2954
+ banner: '"use client";\n// Built with Bun',
2955
+ footer: '// Generated on ' + new Date().toISOString()
2956
+ });
2957
+ ```
2958
+ @example Configure CDN public path for asset loading
2959
+ ```ts
2960
+ await Bun.build({
2961
+ entrypoints: ['./src/index.tsx'],
2962
+ outdir: './dist',
2963
+ publicPath: 'https://cdn.example.com/assets/',
2964
+ loader: {
2965
+ '.png': 'file',
2966
+ '.svg': 'file'
2967
+ }
2968
+ });
2969
+ ```
2970
+ @example Set up package export conditions for different environments
2971
+ ```ts
2972
+ await Bun.build({
2973
+ entrypoints: ['./src/index.tsx'],
2974
+ outdir: './dist',
2975
+ conditions: ['production', 'browser', 'module'],
2976
+ packages: 'external'
2977
+ });
2978
+ ```
2979
+ */
2755
2980
  function build(config: BuildConfig): Promise<BuildOutput>;
2756
-
2757
2981
  /**
2758
2982
  * A status that represents the outcome of a sent message.
2759
2983
  *
@@ -6682,9 +6906,72 @@ declare module "bun" {
6682
6906
  */
6683
6907
  timestamp?: number | Date,
6684
6908
  ): Buffer;
6685
- }
6686
6909
 
6687
- // extends lib.dom.d.ts
6688
- interface BufferEncodingOption {
6689
- encoding?: BufferEncoding;
6910
+ /**
6911
+ * Types for `bun.lock`
6912
+ */
6913
+ type BunLockFile = {
6914
+ lockfileVersion: 0;
6915
+ workspaces: {
6916
+ [workspace: string]: BunLockFileWorkspacePackage;
6917
+ };
6918
+ overrides?: Record<string, string>;
6919
+ patchedDependencies?: Record<string, string>;
6920
+ trustedDependencies?: string[];
6921
+
6922
+ /**
6923
+ * ```
6924
+ * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir }
6925
+ *
6926
+ * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity]
6927
+ * symlink -> [ "name@link:path", INFO ]
6928
+ * folder -> [ "name@file:path", INFO ]
6929
+ * workspace -> [ "name@workspace:path", INFO ]
6930
+ * tarball -> [ "name@tarball", INFO ]
6931
+ * root -> [ "name@root:", { bin, binDir } ]
6932
+ * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ]
6933
+ * github -> [ "name@github:user/repo", INFO, .bun-tag string (TODO: remove this) ]
6934
+ * ```
6935
+ * */
6936
+ packages: {
6937
+ [pkg: string]: BunLockFilePackageArray;
6938
+ };
6939
+ };
6940
+
6941
+ type BunLockFileBasePackageInfo = {
6942
+ dependencies?: Record<string, string>;
6943
+ devDependencies?: Record<string, string>;
6944
+ optionalDependencies?: Record<string, string>;
6945
+ peerDependencies?: Record<string, string>;
6946
+ optionalPeers?: string[];
6947
+ };
6948
+
6949
+ type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & {
6950
+ name?: string;
6951
+ version?: string;
6952
+ };
6953
+
6954
+ type BunLockFilePackageInfo = BunLockFileBasePackageInfo & {
6955
+ os?: string | string[];
6956
+ cpu?: string | string[];
6957
+ bin?: Record<string, string>;
6958
+ binDir?: string;
6959
+ bundled?: true;
6960
+ };
6961
+
6962
+ /** @see {@link BunLockFile.packages} for more info */
6963
+ type BunLockFilePackageArray =
6964
+ /** npm */
6965
+ | [
6966
+ pkg: string,
6967
+ registry: string,
6968
+ info: BunLockFilePackageInfo,
6969
+ integrity: string,
6970
+ ]
6971
+ /** symlink, folder, tarball, workspace */
6972
+ | [pkg: string, info: BunLockFilePackageInfo]
6973
+ /** git, github */
6974
+ | [pkg: string, info: BunLockFilePackageInfo, bunTag: string]
6975
+ /** root */
6976
+ | [pkg: string, info: Pick<BunLockFilePackageInfo, "bin" | "binDir">];
6690
6977
  }
@@ -235,7 +235,7 @@ The following classes are typed arrays, along with a description of how they int
235
235
  ---
236
236
 
237
237
  - [`BigInt64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array)
238
- - Every eight (8) bytes are interpreted as an unsigned `BigInt`. Range -9223372036854775808 to 9223372036854775807 (though `BigInt` is capable of representing larger numbers).
238
+ - Every eight (8) bytes are interpreted as a signed `BigInt`. Range -9223372036854775808 to 9223372036854775807 (though `BigInt` is capable of representing larger numbers).
239
239
 
240
240
  ---
241
241
 
package/docs/api/fetch.md CHANGED
@@ -195,7 +195,7 @@ This will print the request and response headers to your terminal:
195
195
  ```sh
196
196
  [fetch] > HTTP/1.1 GET http://example.com/
197
197
  [fetch] > Connection: keep-alive
198
- [fetch] > User-Agent: Bun/1.1.21
198
+ [fetch] > User-Agent: Bun/1.1.44-canary.20250113T140648
199
199
  [fetch] > Accept: */*
200
200
  [fetch] > Host: example.com
201
201
  [fetch] > Accept-Encoding: gzip, deflate, br
@@ -1,31 +1,334 @@
1
- Bun provides a fast native implementation of the `HTMLRewriter` pattern developed by Cloudflare. It provides a convenient, `EventListener`-like API for traversing and transforming HTML documents.
1
+ HTMLRewriter lets you use CSS selectors to transform HTML documents. It works with `Request`, `Response`, as well as `string`. Bun's implementation is based on Cloudflare's [lol-html](https://github.com/cloudflare/lol-html).
2
+
3
+ ## Usage
4
+
5
+ A common usecase is rewriting URLs in HTML content. Here's an example that rewrites image sources and link URLs to use a CDN domain:
2
6
 
3
7
  ```ts
4
- const rewriter = new HTMLRewriter();
8
+ // Replace all images with a rickroll
9
+ const rewriter = new HTMLRewriter().on("img", {
10
+ element(img) {
11
+ // Famous rickroll video thumbnail
12
+ img.setAttribute(
13
+ "src",
14
+ "https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
15
+ );
5
16
 
6
- rewriter.on("*", {
7
- element(el) {
8
- console.log(el.tagName); // "body" | "div" | ...
17
+ // Wrap the image in a link to the video
18
+ img.before(
19
+ '<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">',
20
+ { html: true },
21
+ );
22
+ img.after("</a>", { html: true });
23
+
24
+ // Add some fun alt text
25
+ img.setAttribute("alt", "Definitely not a rickroll");
9
26
  },
10
27
  });
11
- ```
12
-
13
- To parse and/or transform the HTML:
14
28
 
15
- ```ts#rewriter.ts
16
- rewriter.transform(
17
- new Response(`
18
- <!DOCTYPE html>
29
+ // An example HTML document
30
+ const html = `
19
31
  <html>
20
- <!-- comment -->
21
- <head>
22
- <title>My First HTML Page</title>
23
- </head>
24
32
  <body>
25
- <h1>My First Heading</h1>
26
- <p>My first paragraph.</p>
33
+ <img src="/cat.jpg">
34
+ <img src="dog.png">
35
+ <img src="https://example.com/bird.webp">
27
36
  </body>
28
- `));
37
+ </html>
38
+ `;
39
+
40
+ const result = rewriter.transform(html);
41
+ console.log(result);
29
42
  ```
30
43
 
31
- View the full documentation on the [Cloudflare website](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/).
44
+ This replaces all images with a thumbnail of Rick Astley and wraps each `<img>` in a link, producing a diff like this:
45
+
46
+ ```html-diff
47
+ <html>
48
+ <body>
49
+ - <img src="/cat.jpg">
50
+ - <img src="dog.png">
51
+ - <img src="https://example.com/bird.webp">
52
+ + <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">
53
+ + <img src="https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" alt="Definitely not a rickroll">
54
+ + </a>
55
+ + <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">
56
+ + <img src="https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" alt="Definitely not a rickroll">
57
+ + </a>
58
+ + <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank">
59
+ + <img src="https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" alt="Definitely not a rickroll">
60
+ + </a>
61
+ </body>
62
+ </html>
63
+ ```
64
+
65
+ Now every image on the page will be replaced with a thumbnail of Rick Astley, and clicking any image will lead to [a very famous video](https://www.youtube.com/watch?v=dQw4w9WgXcQ).
66
+
67
+ ### Input types
68
+
69
+ HTMLRewriter can transform HTML from various sources. The input is automatically handled based on its type:
70
+
71
+ ```ts
72
+ // From Response
73
+ rewriter.transform(new Response("<div>content</div>"));
74
+
75
+ // From string
76
+ rewriter.transform("<div>content</div>");
77
+
78
+ // From ArrayBuffer
79
+ rewriter.transform(new TextEncoder().encode("<div>content</div>").buffer);
80
+
81
+ // From Blob
82
+ rewriter.transform(new Blob(["<div>content</div>"]));
83
+
84
+ // From File
85
+ rewriter.transform(Bun.file("index.html"));
86
+ ```
87
+
88
+ Note that Cloudflare Workers implementation of HTMLRewriter only supports `Response` objects.
89
+
90
+ ### Element Handlers
91
+
92
+ The `on(selector, handlers)` method allows you to register handlers for HTML elements that match a CSS selector. The handlers are called for each matching element during parsing:
93
+
94
+ ```ts
95
+ rewriter.on("div.content", {
96
+ // Handle elements
97
+ element(element) {
98
+ element.setAttribute("class", "new-content");
99
+ element.append("<p>New content</p>", { html: true });
100
+ },
101
+ // Handle text nodes
102
+ text(text) {
103
+ text.replace("new text");
104
+ },
105
+ // Handle comments
106
+ comments(comment) {
107
+ comment.remove();
108
+ },
109
+ });
110
+ ```
111
+
112
+ The handlers can be asynchronous and return a Promise. Note that async operations will block the transformation until they complete:
113
+
114
+ ```ts
115
+ rewriter.on("div", {
116
+ async element(element) {
117
+ await Bun.sleep(1000);
118
+ element.setInnerContent("<span>replace</span>", { html: true });
119
+ },
120
+ });
121
+ ```
122
+
123
+ ### CSS Selector Support
124
+
125
+ The `on()` method supports a wide range of CSS selectors:
126
+
127
+ ```ts
128
+ // Tag selectors
129
+ rewriter.on("p", handler);
130
+
131
+ // Class selectors
132
+ rewriter.on("p.red", handler);
133
+
134
+ // ID selectors
135
+ rewriter.on("h1#header", handler);
136
+
137
+ // Attribute selectors
138
+ rewriter.on("p[data-test]", handler); // Has attribute
139
+ rewriter.on('p[data-test="one"]', handler); // Exact match
140
+ rewriter.on('p[data-test="one" i]', handler); // Case-insensitive
141
+ rewriter.on('p[data-test="one" s]', handler); // Case-sensitive
142
+ rewriter.on('p[data-test~="two"]', handler); // Word match
143
+ rewriter.on('p[data-test^="a"]', handler); // Starts with
144
+ rewriter.on('p[data-test$="1"]', handler); // Ends with
145
+ rewriter.on('p[data-test*="b"]', handler); // Contains
146
+ rewriter.on('p[data-test|="a"]', handler); // Dash-separated
147
+
148
+ // Combinators
149
+ rewriter.on("div span", handler); // Descendant
150
+ rewriter.on("div > span", handler); // Direct child
151
+
152
+ // Pseudo-classes
153
+ rewriter.on("p:nth-child(2)", handler);
154
+ rewriter.on("p:first-child", handler);
155
+ rewriter.on("p:nth-of-type(2)", handler);
156
+ rewriter.on("p:first-of-type", handler);
157
+ rewriter.on("p:not(:first-child)", handler);
158
+
159
+ // Universal selector
160
+ rewriter.on("*", handler);
161
+ ```
162
+
163
+ ### Element Operations
164
+
165
+ Elements provide various methods for manipulation. All modification methods return the element instance for chaining:
166
+
167
+ ```ts
168
+ rewriter.on("div", {
169
+ element(el) {
170
+ // Attributes
171
+ el.setAttribute("class", "new-class").setAttribute("data-id", "123");
172
+
173
+ const classAttr = el.getAttribute("class"); // "new-class"
174
+ const hasId = el.hasAttribute("id"); // boolean
175
+ el.removeAttribute("class");
176
+
177
+ // Content manipulation
178
+ el.setInnerContent("New content"); // Escapes HTML by default
179
+ el.setInnerContent("<p>HTML content</p>", { html: true }); // Parses HTML
180
+ el.setInnerContent(""); // Clear content
181
+
182
+ // Position manipulation
183
+ el.before("Content before")
184
+ .after("Content after")
185
+ .prepend("First child")
186
+ .append("Last child");
187
+
188
+ // HTML content insertion
189
+ el.before("<span>before</span>", { html: true })
190
+ .after("<span>after</span>", { html: true })
191
+ .prepend("<span>first</span>", { html: true })
192
+ .append("<span>last</span>", { html: true });
193
+
194
+ // Removal
195
+ el.remove(); // Remove element and contents
196
+ el.removeAndKeepContent(); // Remove only the element tags
197
+
198
+ // Properties
199
+ console.log(el.tagName); // Lowercase tag name
200
+ console.log(el.namespaceURI); // Element's namespace URI
201
+ console.log(el.selfClosing); // Whether element is self-closing (e.g. <div />)
202
+ console.log(el.canHaveContent); // Whether element can contain content (false for void elements like <br>)
203
+ console.log(el.removed); // Whether element was removed
204
+
205
+ // Attributes iteration
206
+ for (const [name, value] of el.attributes) {
207
+ console.log(name, value);
208
+ }
209
+
210
+ // End tag handling
211
+ el.onEndTag(endTag => {
212
+ endTag.before("Before end tag");
213
+ endTag.after("After end tag");
214
+ endTag.remove(); // Remove the end tag
215
+ console.log(endTag.name); // Tag name in lowercase
216
+ });
217
+ },
218
+ });
219
+ ```
220
+
221
+ ### Text Operations
222
+
223
+ Text handlers provide methods for text manipulation. Text chunks represent portions of text content and provide information about their position in the text node:
224
+
225
+ ```ts
226
+ rewriter.on("p", {
227
+ text(text) {
228
+ // Content
229
+ console.log(text.text); // Text content
230
+ console.log(text.lastInTextNode); // Whether this is the last chunk
231
+ console.log(text.removed); // Whether text was removed
232
+
233
+ // Manipulation
234
+ text.before("Before text").after("After text").replace("New text").remove();
235
+
236
+ // HTML content insertion
237
+ text
238
+ .before("<span>before</span>", { html: true })
239
+ .after("<span>after</span>", { html: true })
240
+ .replace("<span>replace</span>", { html: true });
241
+ },
242
+ });
243
+ ```
244
+
245
+ ### Comment Operations
246
+
247
+ Comment handlers allow comment manipulation with similar methods to text nodes:
248
+
249
+ ```ts
250
+ rewriter.on("*", {
251
+ comments(comment) {
252
+ // Content
253
+ console.log(comment.text); // Comment text
254
+ comment.text = "New comment text"; // Set comment text
255
+ console.log(comment.removed); // Whether comment was removed
256
+
257
+ // Manipulation
258
+ comment
259
+ .before("Before comment")
260
+ .after("After comment")
261
+ .replace("New comment")
262
+ .remove();
263
+
264
+ // HTML content insertion
265
+ comment
266
+ .before("<span>before</span>", { html: true })
267
+ .after("<span>after</span>", { html: true })
268
+ .replace("<span>replace</span>", { html: true });
269
+ },
270
+ });
271
+ ```
272
+
273
+ ### Document Handlers
274
+
275
+ The `onDocument(handlers)` method allows you to handle document-level events. These handlers are called for events that occur at the document level rather than within specific elements:
276
+
277
+ ```ts
278
+ rewriter.onDocument({
279
+ // Handle doctype
280
+ doctype(doctype) {
281
+ console.log(doctype.name); // "html"
282
+ console.log(doctype.publicId); // public identifier if present
283
+ console.log(doctype.systemId); // system identifier if present
284
+ },
285
+ // Handle text nodes
286
+ text(text) {
287
+ console.log(text.text);
288
+ },
289
+ // Handle comments
290
+ comments(comment) {
291
+ console.log(comment.text);
292
+ },
293
+ // Handle document end
294
+ end(end) {
295
+ end.append("<!-- Footer -->", { html: true });
296
+ },
297
+ });
298
+ ```
299
+
300
+ ### Response Handling
301
+
302
+ When transforming a Response:
303
+
304
+ - The status code, headers, and other response properties are preserved
305
+ - The body is transformed while maintaining streaming capabilities
306
+ - Content-encoding (like gzip) is handled automatically
307
+ - The original response body is marked as used after transformation
308
+ - Headers are cloned to the new response
309
+
310
+ ## Error Handling
311
+
312
+ HTMLRewriter operations can throw errors in several cases:
313
+
314
+ - Invalid selector syntax in `on()` method
315
+ - Invalid HTML content in transformation methods
316
+ - Stream errors when processing Response bodies
317
+ - Memory allocation failures
318
+ - Invalid input types (e.g., passing Symbol)
319
+ - Body already used errors
320
+
321
+ Errors should be caught and handled appropriately:
322
+
323
+ ```ts
324
+ try {
325
+ const result = rewriter.transform(input);
326
+ // Process result
327
+ } catch (error) {
328
+ console.error("HTMLRewriter error:", error);
329
+ }
330
+ ```
331
+
332
+ ## See also
333
+
334
+ You can also read the [Cloudflare documentation](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/), which this API is intended to be compatible with.