yummies 7.19.3 → 7.20.0

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.
Files changed (162) hide show
  1. package/assert.cjs +1 -1
  2. package/assert.cjs.map +1 -1
  3. package/assert.js +1 -1
  4. package/assert.js.map +1 -1
  5. package/async.cjs +147 -137
  6. package/async.cjs.map +1 -1
  7. package/async.d.ts +98 -131
  8. package/async.js +147 -137
  9. package/async.js.map +1 -1
  10. package/common.cjs +3 -1
  11. package/common.cjs.map +1 -1
  12. package/common.d.ts +18 -24
  13. package/common.js +3 -1
  14. package/common.js.map +1 -1
  15. package/complex.cjs +1 -0
  16. package/complex.cjs.map +1 -1
  17. package/complex.js +1 -0
  18. package/complex.js.map +1 -1
  19. package/cookie.cjs +1 -1
  20. package/cookie.cjs.map +1 -1
  21. package/cookie.d.ts +0 -18
  22. package/cookie.js +1 -1
  23. package/cookie.js.map +1 -1
  24. package/css-cx.cjs +78 -0
  25. package/css-cx.cjs.map +1 -0
  26. package/css-cx.d.ts +69 -0
  27. package/css-cx.js +74 -0
  28. package/css-cx.js.map +1 -0
  29. package/css.cjs +32 -111
  30. package/css.cjs.map +1 -1
  31. package/css.d.ts +32 -42
  32. package/css.js +30 -107
  33. package/css.js.map +1 -1
  34. package/data.cjs +60 -50
  35. package/data.cjs.map +1 -1
  36. package/data.d.ts +21 -34
  37. package/data.js +60 -50
  38. package/data.js.map +1 -1
  39. package/date-time.cjs +104 -98
  40. package/date-time.cjs.map +1 -1
  41. package/date-time.d.ts +51 -57
  42. package/date-time.js +104 -97
  43. package/date-time.js.map +1 -1
  44. package/device.cjs +14 -19
  45. package/device.cjs.map +1 -1
  46. package/device.d.ts +15 -26
  47. package/device.js +14 -19
  48. package/device.js.map +1 -1
  49. package/encodings.cjs +1 -1
  50. package/encodings.cjs.map +1 -1
  51. package/encodings.d.ts +0 -17
  52. package/encodings.js +1 -1
  53. package/encodings.js.map +1 -1
  54. package/errors.cjs +1 -18
  55. package/errors.cjs.map +1 -1
  56. package/errors.d.ts +0 -17
  57. package/errors.js +1 -17
  58. package/errors.js.map +1 -1
  59. package/file.cjs +3 -17
  60. package/file.cjs.map +1 -1
  61. package/file.d.ts +1 -16
  62. package/file.js +3 -17
  63. package/file.js.map +1 -1
  64. package/format.cjs +1 -1
  65. package/format.cjs.map +1 -1
  66. package/format.js +1 -1
  67. package/format.js.map +1 -1
  68. package/html.cjs +113 -173
  69. package/html.cjs.map +1 -1
  70. package/html.d.ts +68 -58
  71. package/html.js +112 -170
  72. package/html.js.map +1 -1
  73. package/id-nanoid.cjs +36 -0
  74. package/id-nanoid.cjs.map +1 -0
  75. package/id-nanoid.d.ts +26 -0
  76. package/id-nanoid.js +32 -0
  77. package/id-nanoid.js.map +1 -0
  78. package/id.cjs +10 -45
  79. package/id.cjs.map +1 -1
  80. package/id.d.ts +27 -36
  81. package/id.js +6 -40
  82. package/id.js.map +1 -1
  83. package/imports.cjs +3 -18
  84. package/imports.cjs.map +1 -1
  85. package/imports.d.ts +1 -16
  86. package/imports.js +3 -17
  87. package/imports.js.map +1 -1
  88. package/math.cjs +16 -12
  89. package/math.cjs.map +1 -1
  90. package/math.d.ts +9 -24
  91. package/math.js +16 -12
  92. package/math.js.map +1 -1
  93. package/media.cjs +88 -89
  94. package/media.cjs.map +1 -1
  95. package/media.d.ts +72 -80
  96. package/media.js +88 -88
  97. package/media.js.map +1 -1
  98. package/mobx.cjs +0 -1
  99. package/mobx.cjs.map +1 -1
  100. package/mobx.js.map +1 -1
  101. package/ms.cjs +3 -17
  102. package/ms.cjs.map +1 -1
  103. package/ms.d.ts +1 -16
  104. package/ms.js +3 -17
  105. package/ms.js.map +1 -1
  106. package/number.cjs +1 -17
  107. package/number.cjs.map +1 -1
  108. package/number.d.ts +0 -16
  109. package/number.js +1 -17
  110. package/number.js.map +1 -1
  111. package/package.json +6 -6
  112. package/parser.cjs +1 -1
  113. package/parser.cjs.map +1 -1
  114. package/parser.js +1 -1
  115. package/parser.js.map +1 -1
  116. package/price.cjs +1 -1
  117. package/price.cjs.map +1 -1
  118. package/price.d.ts +0 -16
  119. package/price.js +1 -1
  120. package/price.js.map +1 -1
  121. package/random.cjs +37 -39
  122. package/random.cjs.map +1 -1
  123. package/random.d.ts +31 -40
  124. package/random.js +37 -39
  125. package/random.js.map +1 -1
  126. package/react.cjs +0 -1
  127. package/react.cjs.map +1 -1
  128. package/react.js.map +1 -1
  129. package/sanitize-html.cjs +82 -0
  130. package/sanitize-html.cjs.map +1 -0
  131. package/sanitize-html.d.ts +28 -0
  132. package/sanitize-html.js +79 -0
  133. package/sanitize-html.js.map +1 -0
  134. package/sound.cjs +1 -17
  135. package/sound.cjs.map +1 -1
  136. package/sound.d.ts +0 -16
  137. package/sound.js +1 -17
  138. package/sound.js.map +1 -1
  139. package/storage.cjs +7 -5
  140. package/storage.cjs.map +1 -1
  141. package/storage.d.ts +3 -17
  142. package/storage.js +7 -5
  143. package/storage.js.map +1 -1
  144. package/text.cjs +3 -17
  145. package/text.cjs.map +1 -1
  146. package/text.d.ts +1 -16
  147. package/text.js +3 -17
  148. package/text.js.map +1 -1
  149. package/type-guard.cjs +38 -1
  150. package/type-guard.cjs.map +1 -1
  151. package/type-guard.d.ts +38 -0
  152. package/type-guard.js +38 -1
  153. package/type-guard.js.map +1 -1
  154. package/types.d.ts +10 -1
  155. package/types.global.d.ts +9 -0
  156. package/vibrate.cjs +1 -17
  157. package/vibrate.cjs.map +1 -1
  158. package/vibrate.d.ts +0 -16
  159. package/vibrate.js +1 -17
  160. package/vibrate.js.map +1 -1
  161. /package/{chunk-pbuEa-1d.js → chunk-D7D4PA-g.js} +0 -0
  162. /package/{chunk-CZWwpsFl.cjs → chunk-DakpK96I.cjs} +0 -0
package/media.cjs CHANGED
@@ -1,23 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- require("./chunk-CZWwpsFl.cjs");
3
2
  let yummies_math = require("yummies/math");
4
- //#region src/media.ts
5
- /**
6
- * ---header-docs-section---
7
- * # yummies/media
8
- *
9
- * ## Description
10
- *
11
- * Binary and media helpers: Base64 data URLs, object URLs, image orientation fixes, and related
12
- * browser APIs wrapped in promises. Centralizes `FileReader`/`URL.createObjectURL` usage so image
13
- * pipelines and uploads stay consistent and easier to test or mock.
14
- *
15
- * ## Usage
16
- *
17
- * ```ts
18
- * import { blobToBase64 } from "yummies/media";
19
- * ```
20
- */
3
+ //#region src/media/blob-to-base64.ts
21
4
  /**
22
5
  * Reads a {@link Blob} as a **data URL** string (`data:<mime>;base64,...`) using {@link FileReader#readAsDataURL}.
23
6
  *
@@ -48,6 +31,8 @@ function blobToBase64(blob) {
48
31
  reader.readAsDataURL(blob);
49
32
  });
50
33
  }
34
+ //#endregion
35
+ //#region src/media/blob-to-url.ts
51
36
  /**
52
37
  * If `urlOrBlob` is already a string, returns it unchanged. If it is a {@link Blob}, returns
53
38
  * `URL.createObjectURL(blob)` — a short-lived `blob:` URL valid in this document until
@@ -73,9 +58,39 @@ function blobToBase64(blob) {
73
58
  * ```
74
59
  */
75
60
  var blobToUrl = (urlOrBlob) => urlOrBlob instanceof Blob ? URL.createObjectURL(urlOrBlob) : urlOrBlob;
61
+ //#endregion
62
+ //#region src/media/decode-data-url.ts
63
+ /**
64
+ * Parses a `data:` URL of the form `data:<mime>;base64,<payload>` into its MIME type and raw
65
+ * Base64 body (without the `data:...;base64,` prefix). Non-matching strings yield `undefined`
66
+ * fields in the result object.
67
+ *
68
+ * @param url - Full data URL string.
69
+ * @returns `{ mimeType, data }` — both optional when the regex does not match.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * const { mimeType, data } = decodeDataUrl('data:image/png;base64,iVBORw0KGgo=');
74
+ * // mimeType === 'image/png', data === 'iVBORw0KGgo='
75
+ * ```
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * decodeDataUrl('not-a-data-url'); // { mimeType: undefined, data: undefined }
80
+ * ```
81
+ */
82
+ function decodeDataUrl(url) {
83
+ const matches = (/* @__PURE__ */ new RegExp(/^data:(.*);base64,\s?(.*)$/)).exec(url);
84
+ return {
85
+ mimeType: matches?.[1],
86
+ data: matches?.[2]
87
+ };
88
+ }
89
+ //#endregion
90
+ //#region src/media/file-to-blob.ts
76
91
  /**
77
92
  * Creates a new {@link Blob} from a {@link File}, copying the bytes and keeping `file.type` as
78
- * the blobs MIME type. Handy when an API accepts `Blob` but you only have `File`, or you want a
93
+ * the blob's MIME type. Handy when an API accepts `Blob` but you only have `File`, or you want a
79
94
  * plain blob without the `File` name/lastModified metadata.
80
95
  *
81
96
  * @param file - Source file from an `<input type="file">` or drag-and-drop.
@@ -96,6 +111,8 @@ var blobToUrl = (urlOrBlob) => urlOrBlob instanceof Blob ? URL.createObjectURL(u
96
111
  var fileToBlob = (file) => {
97
112
  return new Blob([file], { type: file.type });
98
113
  };
114
+ //#endregion
115
+ //#region src/media/image-to-blob.ts
99
116
  /**
100
117
  * Draws an {@link HTMLImageElement} onto an offscreen canvas, then builds a {@link Blob} from the
101
118
  * raster (via `canvas.toDataURL` + binary decode). Dimensions use `naturalWidth` / `naturalHeight`,
@@ -133,6 +150,56 @@ var imageToBlob = (imageElement, mimeType = "image/png") => {
133
150
  for (let index = 0; index < bytes.length; index++) array[index] = bytes.charCodeAt(index);
134
151
  return new Blob([array], { type: base64MimeType });
135
152
  };
153
+ //#endregion
154
+ //#region src/media/is-base64-image.ts
155
+ /**
156
+ * Returns `true` when `str` is a data URL that {@link decodeDataUrl} can parse **and** the MIME
157
+ * type starts with `image/` (e.g. `image/png`, `image/jpeg`). Requires both a non-empty Base64
158
+ * payload and an image MIME — arbitrary `data:text/plain;base64,...` is `false`.
159
+ *
160
+ * @param str - Candidate string (often `img.src` or API payload).
161
+ *
162
+ * @example
163
+ * ```ts
164
+ * isBase64Image('data:image/png;base64,iVBORw0KGgo='); // true
165
+ * ```
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * isBase64Image('https://example.com/x.png'); // false
170
+ * isBase64Image('data:text/plain;base64,SGk='); // false
171
+ * ```
172
+ */
173
+ var isBase64Image = (str) => {
174
+ const { mimeType, data } = decodeDataUrl(str);
175
+ return !!(data && mimeType?.startsWith("image/"));
176
+ };
177
+ //#endregion
178
+ //#region src/media/is-http-url.ts
179
+ /**
180
+ * Returns `true` if `url` starts with `https://` or `http://` (case-sensitive, as in
181
+ * `String#startsWith`). Does not validate that the rest is a well-formed URL — only the scheme
182
+ * prefix. `blob:`, `data:`, and relative paths return `false`.
183
+ *
184
+ * @param url - String to test (often a user-provided or configured href).
185
+ *
186
+ * @example
187
+ * ```ts
188
+ * isHttpUrl('https://example.com/path'); // true
189
+ * isHttpUrl('http://localhost:3000'); // true
190
+ * ```
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * isHttpUrl('//cdn.example.com'); // false — no explicit http(s) prefix
195
+ * isHttpUrl('/assets/logo.png'); // false — relative path
196
+ * ```
197
+ */
198
+ var isHttpUrl = (url) => {
199
+ return url.startsWith("https://") || url.startsWith("http://");
200
+ };
201
+ //#endregion
202
+ //#region src/media/render-image.ts
136
203
  /**
137
204
  * Loads a resource into a new `HTMLImageElement`: `src` is set via {@link blobToUrl} (so blobs get
138
205
  * object URLs, strings are used directly). Resolves on `load` with the same element; rejects on
@@ -162,6 +229,8 @@ var renderImage = (urlOrBlob) => new Promise((resolve, reject) => {
162
229
  image.onload = () => resolve(image);
163
230
  image.onerror = () => reject();
164
231
  });
232
+ //#endregion
233
+ //#region src/media/rotate-image.ts
165
234
  function cropImageFromCanvas(context) {
166
235
  const canvas = context.canvas;
167
236
  let w = canvas.width;
@@ -229,76 +298,6 @@ var rotateImage = (image, angle) => {
229
298
  cropImageFromCanvas(context);
230
299
  return renderImage(canvas.toDataURL("image/png"));
231
300
  };
232
- /**
233
- * Parses a `data:` URL of the form `data:<mime>;base64,<payload>` into its MIME type and raw
234
- * Base64 body (without the `data:...;base64,` prefix). Non-matching strings yield `undefined`
235
- * fields in the result object.
236
- *
237
- * @param url - Full data URL string.
238
- * @returns `{ mimeType, data }` — both optional when the regex does not match.
239
- *
240
- * @example
241
- * ```ts
242
- * const { mimeType, data } = decodeDataUrl('data:image/png;base64,iVBORw0KGgo=');
243
- * // mimeType === 'image/png', data === 'iVBORw0KGgo='
244
- * ```
245
- *
246
- * @example
247
- * ```ts
248
- * decodeDataUrl('not-a-data-url'); // { mimeType: undefined, data: undefined }
249
- * ```
250
- */
251
- function decodeDataUrl(url) {
252
- const matches = (/* @__PURE__ */ new RegExp(/^data:(.*);base64,\s?(.*)$/)).exec(url);
253
- return {
254
- mimeType: matches?.[1],
255
- data: matches?.[2]
256
- };
257
- }
258
- /**
259
- * Returns `true` if `url` starts with `https://` or `http://` (case-sensitive, as in
260
- * `String#startsWith`). Does not validate that the rest is a well-formed URL — only the scheme
261
- * prefix. `blob:`, `data:`, and relative paths return `false`.
262
- *
263
- * @param url - String to test (often a user-provided or configured href).
264
- *
265
- * @example
266
- * ```ts
267
- * isHttpUrl('https://example.com/path'); // true
268
- * isHttpUrl('http://localhost:3000'); // true
269
- * ```
270
- *
271
- * @example
272
- * ```ts
273
- * isHttpUrl('//cdn.example.com'); // false — no explicit http(s) prefix
274
- * isHttpUrl('/assets/logo.png'); // false — relative path
275
- * ```
276
- */
277
- var isHttpUrl = (url) => {
278
- return url.startsWith("https://") || url.startsWith("http://");
279
- };
280
- /**
281
- * Returns `true` when `str` is a data URL that {@link decodeDataUrl} can parse **and** the MIME
282
- * type starts with `image/` (e.g. `image/png`, `image/jpeg`). Requires both a non-empty Base64
283
- * payload and an image MIME — arbitrary `data:text/plain;base64,...` is `false`.
284
- *
285
- * @param str - Candidate string (often `img.src` or API payload).
286
- *
287
- * @example
288
- * ```ts
289
- * isBase64Image('data:image/png;base64,iVBORw0KGgo='); // true
290
- * ```
291
- *
292
- * @example
293
- * ```ts
294
- * isBase64Image('https://example.com/x.png'); // false
295
- * isBase64Image('data:text/plain;base64,SGk='); // false
296
- * ```
297
- */
298
- var isBase64Image = (str) => {
299
- const { mimeType, data } = decodeDataUrl(str);
300
- return !!(data && mimeType?.startsWith("image/"));
301
- };
302
301
  //#endregion
303
302
  exports.blobToBase64 = blobToBase64;
304
303
  exports.blobToUrl = blobToUrl;
package/media.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"media.cjs","names":[],"sources":["../src/media.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/media\n *\n * ## Description\n *\n * Binary and media helpers: Base64 data URLs, object URLs, image orientation fixes, and related\n * browser APIs wrapped in promises. Centralizes `FileReader`/`URL.createObjectURL` usage so image\n * pipelines and uploads stay consistent and easier to test or mock.\n *\n * ## Usage\n *\n * ```ts\n * import { blobToBase64 } from \"yummies/media\";\n * ```\n */\n\nimport { degToRad } from 'yummies/math';\n\n/**\n * Reads a {@link Blob} as a **data URL** string (`data:<mime>;base64,...`) using {@link FileReader#readAsDataURL}.\n *\n * Useful for previewing uploads, embedding small assets inline, or serializing binary for APIs that\n * expect Base64-in-JSON. The result includes the MIME prefix, not raw Base64 alone — use\n * {@link decodeDataUrl} if you need the payload and type separately.\n *\n * @param blob - Any `Blob` or `File` (files are blobs).\n * @returns Resolves to the data URL string; rejects if reading fails.\n *\n * @example\n * ```ts\n * const dataUrl = await blobToBase64(file);\n * previewImg.src = dataUrl;\n * ```\n *\n * @example\n * ```ts\n * const fromFetch = await fetch('/api/export').then((r) => r.blob());\n * const dataUrl = await blobToBase64(fromFetch);\n * ```\n */\nexport function blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result as string);\n reader.onerror = reject;\n reader.readAsDataURL(blob);\n });\n}\n\n/**\n * If `urlOrBlob` is already a string, returns it unchanged. If it is a {@link Blob}, returns\n * `URL.createObjectURL(blob)` — a short-lived `blob:` URL valid in this document until\n * {@link URL.revokeObjectURL} is called.\n *\n * Pair with {@link renderImage} or `<img src>` without re-fetching binary data. **Remember to\n * `revokeObjectURL`** when the URL is no longer needed to avoid retaining blob memory.\n *\n * @param urlOrBlob - Remote/http(s) URL string, data URL, or a `Blob` / `File`.\n * @returns A string suitable for `HTMLImageElement.src` or similar.\n *\n * @example\n * ```ts\n * const src = blobToUrl(uploadedFile);\n * img.src = src;\n * // when done:\n * URL.revokeObjectURL(src);\n * ```\n *\n * @example\n * ```ts\n * blobToUrl('https://cdn.example.com/logo.png'); // passed through as-is\n * ```\n */\nexport const blobToUrl = (urlOrBlob: string | Blob) =>\n urlOrBlob instanceof Blob ? URL.createObjectURL(urlOrBlob) : urlOrBlob;\n\n/**\n * Creates a new {@link Blob} from a {@link File}, copying the bytes and keeping `file.type` as\n * the blob’s MIME type. Handy when an API accepts `Blob` but you only have `File`, or you want a\n * plain blob without the `File` name/lastModified metadata.\n *\n * @param file - Source file from an `<input type=\"file\">` or drag-and-drop.\n * @returns A `Blob` with the same content and `type` as the file.\n *\n * @example\n * ```ts\n * const blob = fileToBlob(fileFromInput);\n * await uploadEndpoint(blob);\n * ```\n *\n * @example\n * ```ts\n * const blob = fileToBlob(imageFile);\n * const url = URL.createObjectURL(blob);\n * ```\n */\nexport const fileToBlob = (file: File) => {\n return new Blob([file], { type: file.type });\n};\n\n/**\n * Draws an {@link HTMLImageElement} onto an offscreen canvas, then builds a {@link Blob} from the\n * raster (via `canvas.toDataURL` + binary decode). Dimensions use `naturalWidth` / `naturalHeight`,\n * falling back to `300×300` if those are zero (e.g. not yet decoded).\n *\n * **CORS:** if the image is cross-origin without proper CORS headers, the canvas may be\n * *tainted* and `toDataURL` can throw — same browser rules as any canvas export.\n *\n * @param imageElement - Loaded image (`complete` / decoded recommended).\n * @param mimeType - Output MIME type, e.g. `'image/png'` (default) or `'image/jpeg'`. Encoder support is browser-dependent.\n * @returns Encoded image as a `Blob` with a matching `type` when possible.\n *\n * @example\n * ```ts\n * const img = await renderImage('/photo.jpg');\n * const jpegBlob = imageToBlob(img, 'image/jpeg');\n * ```\n *\n * @example\n * ```ts\n * const pngBlob = imageToBlob(cachedImg); // default image/png\n * ```\n */\nexport const imageToBlob = (\n imageElement: HTMLImageElement,\n mimeType: string = 'image/png',\n) => {\n const canvas = document.createElement('canvas');\n\n canvas.width = imageElement.naturalWidth || 300;\n canvas.height = imageElement.naturalHeight || 300;\n\n canvas.getContext('2d')!.drawImage(imageElement, 0, 0);\n\n const dataUri = canvas.toDataURL(mimeType, 1);\n const base64data = dataUri.split(',')[1];\n const base64MimeType = dataUri.split(';')[0].slice(5);\n\n const bytes = globalThis.atob(base64data);\n const buf = new ArrayBuffer(bytes.length);\n const array = new Uint8Array(buf);\n\n for (let index = 0; index < bytes.length; index++) {\n array[index] = bytes.charCodeAt(index);\n }\n\n const blob = new Blob([array], { type: base64MimeType });\n\n return blob;\n};\n\n/**\n * Loads a resource into a new `HTMLImageElement`: `src` is set via {@link blobToUrl} (so blobs get\n * object URLs, strings are used directly). Resolves on `load` with the same element; rejects on\n * `error` (e.g. bad URL, network failure, corrupt image) **with no rejection value**.\n *\n * Does not add the node to the DOM — use the returned element for canvas, measuring, or\n * {@link imageToBlob}.\n *\n * @param urlOrBlob - Remote URL, data URL, or `Blob` / `File`.\n * @returns Promise that fulfills with the loaded `HTMLImageElement`.\n *\n * @example\n * ```ts\n * const img = await renderImage('https://example.com/pic.png');\n * document.body.appendChild(img);\n * ```\n *\n * @example\n * ```ts\n * const img = await renderImage(pickedFile);\n * const blob = imageToBlob(img, 'image/webp');\n * ```\n */\nexport const renderImage = (urlOrBlob: Blob | string) =>\n new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n image.src = blobToUrl(urlOrBlob);\n image.onload = () => resolve(image);\n image.onerror = () => reject();\n });\n\nfunction cropImageFromCanvas(context: CanvasRenderingContext2D) {\n const canvas = context.canvas;\n let w = canvas.width;\n let h = canvas.height;\n const pix: { x: number[]; y: number[] } = { x: [], y: [] };\n const imageData = context.getImageData(0, 0, canvas.width, canvas.height);\n let x: number;\n let y: number;\n let index: number;\n\n for (y = 0; y < h; y++) {\n for (x = 0; x < w; x++) {\n index = (y * w + x) * 4;\n if (imageData.data[index + 3] > 0) {\n pix.x.push(x);\n pix.y.push(y);\n }\n }\n }\n pix.x.sort((a, b) => a - b);\n pix.y.sort((a, b) => a - b);\n const n = pix.x.length - 1;\n\n w = 1 + pix.x[n] - pix.x[0];\n h = 1 + pix.y[n] - pix.y[0];\n const cut = context.getImageData(pix.x[0], pix.y[0], w, h);\n\n canvas.width = w;\n canvas.height = h;\n context.putImageData(cut, 0, 0);\n return canvas;\n}\n\n// TODO: ломает iphone с огромными изображениями\n/**\n * Rotates `image` around its center on a square canvas (side = max(width, height)), then **crops**\n * transparent margins by trimming to the bounding box of pixels with non-zero alpha.\n * Returns a **new** loaded `HTMLImageElement` (PNG data URL under the hood via {@link renderImage}).\n *\n * `angle` is in **degrees**; converted with {@link degToRad} from `yummies/math`.\n *\n * Very large sources can stress memory on some mobile browsers (known iPhone issues — see TODO in source).\n *\n * @param image - Source image (should be decoded; uses `width` / `height`).\n * @param angle - Rotation in degrees (e.g. `90` for quarter turn).\n * @returns Promise of a new `HTMLImageElement` showing the rotated, cropped result.\n *\n * @example\n * ```ts\n * const upright = await rotateImage(landscapeImg, 90);\n * ```\n *\n * @example\n * ```ts\n * const fixed = await rotateImage(await renderImage(file), -15);\n * ```\n */\nexport const rotateImage = (image: HTMLImageElement, angle: number) => {\n const maxSize = Math.max(image.width, image.height);\n const canvas = document.createElement('canvas');\n canvas.width = maxSize;\n canvas.height = maxSize;\n const context = canvas.getContext('2d')!;\n context.save();\n context.translate(canvas.width / 2, canvas.height / 2);\n context.rotate(degToRad(angle));\n context.drawImage(image, -image.width / 2, -image.height / 2);\n context.restore();\n cropImageFromCanvas(context);\n return renderImage(canvas.toDataURL('image/png'));\n};\n\ninterface DecodedDataUrl {\n mimeType?: string;\n data?: string;\n}\n\n/**\n * Parses a `data:` URL of the form `data:<mime>;base64,<payload>` into its MIME type and raw\n * Base64 body (without the `data:...;base64,` prefix). Non-matching strings yield `undefined`\n * fields in the result object.\n *\n * @param url - Full data URL string.\n * @returns `{ mimeType, data }` — both optional when the regex does not match.\n *\n * @example\n * ```ts\n * const { mimeType, data } = decodeDataUrl('data:image/png;base64,iVBORw0KGgo=');\n * // mimeType === 'image/png', data === 'iVBORw0KGgo='\n * ```\n *\n * @example\n * ```ts\n * decodeDataUrl('not-a-data-url'); // { mimeType: undefined, data: undefined }\n * ```\n */\nexport function decodeDataUrl(url: string): DecodedDataUrl {\n const regex = /^data:(.*);base64,\\s?(.*)$/;\n const matches = new RegExp(regex).exec(url);\n\n return {\n mimeType: matches?.[1],\n data: matches?.[2],\n };\n}\n\n/**\n * Returns `true` if `url` starts with `https://` or `http://` (case-sensitive, as in\n * `String#startsWith`). Does not validate that the rest is a well-formed URL — only the scheme\n * prefix. `blob:`, `data:`, and relative paths return `false`.\n *\n * @param url - String to test (often a user-provided or configured href).\n *\n * @example\n * ```ts\n * isHttpUrl('https://example.com/path'); // true\n * isHttpUrl('http://localhost:3000'); // true\n * ```\n *\n * @example\n * ```ts\n * isHttpUrl('//cdn.example.com'); // false — no explicit http(s) prefix\n * isHttpUrl('/assets/logo.png'); // false — relative path\n * ```\n */\nexport const isHttpUrl = (url: string): boolean => {\n return url.startsWith('https://') || url.startsWith('http://');\n};\n\n/**\n * Returns `true` when `str` is a data URL that {@link decodeDataUrl} can parse **and** the MIME\n * type starts with `image/` (e.g. `image/png`, `image/jpeg`). Requires both a non-empty Base64\n * payload and an image MIME — arbitrary `data:text/plain;base64,...` is `false`.\n *\n * @param str - Candidate string (often `img.src` or API payload).\n *\n * @example\n * ```ts\n * isBase64Image('data:image/png;base64,iVBORw0KGgo='); // true\n * ```\n *\n * @example\n * ```ts\n * isBase64Image('https://example.com/x.png'); // false\n * isBase64Image('data:text/plain;base64,SGk='); // false\n * ```\n */\nexport const isBase64Image = (str: string): boolean => {\n const { mimeType, data } = decodeDataUrl(str);\n return !!(data && mimeType?.startsWith('image/'));\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,SAAgB,aAAa,MAA6B;AACxD,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,SAAS,IAAI,YAAY;AAC/B,SAAO,kBAAkB,QAAQ,OAAO,OAAiB;AACzD,SAAO,UAAU;AACjB,SAAO,cAAc,KAAK;GAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BJ,IAAa,aAAa,cACxB,qBAAqB,OAAO,IAAI,gBAAgB,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;AAsB/D,IAAa,cAAc,SAAe;AACxC,QAAO,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0B9C,IAAa,eACX,cACA,WAAmB,gBAChB;CACH,MAAM,SAAS,SAAS,cAAc,SAAS;AAE/C,QAAO,QAAQ,aAAa,gBAAgB;AAC5C,QAAO,SAAS,aAAa,iBAAiB;AAE9C,QAAO,WAAW,KAAK,CAAE,UAAU,cAAc,GAAG,EAAE;CAEtD,MAAM,UAAU,OAAO,UAAU,UAAU,EAAE;CAC7C,MAAM,aAAa,QAAQ,MAAM,IAAI,CAAC;CACtC,MAAM,iBAAiB,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,EAAE;CAErD,MAAM,QAAQ,WAAW,KAAK,WAAW;CACzC,MAAM,MAAM,IAAI,YAAY,MAAM,OAAO;CACzC,MAAM,QAAQ,IAAI,WAAW,IAAI;AAEjC,MAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,QACxC,OAAM,SAAS,MAAM,WAAW,MAAM;AAKxC,QAFa,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA4B1D,IAAa,eAAe,cAC1B,IAAI,SAA2B,SAAS,WAAW;CACjD,MAAM,QAAQ,IAAI,OAAO;AACzB,OAAM,MAAM,UAAU,UAAU;AAChC,OAAM,eAAe,QAAQ,MAAM;AACnC,OAAM,gBAAgB,QAAQ;EAC9B;AAEJ,SAAS,oBAAoB,SAAmC;CAC9D,MAAM,SAAS,QAAQ;CACvB,IAAI,IAAI,OAAO;CACf,IAAI,IAAI,OAAO;CACf,MAAM,MAAoC;EAAE,GAAG,EAAE;EAAE,GAAG,EAAE;EAAE;CAC1D,MAAM,YAAY,QAAQ,aAAa,GAAG,GAAG,OAAO,OAAO,OAAO,OAAO;CACzE,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,MAAK,IAAI,GAAG,IAAI,GAAG,IACjB,MAAK,IAAI,GAAG,IAAI,GAAG,KAAK;AACtB,WAAS,IAAI,IAAI,KAAK;AACtB,MAAI,UAAU,KAAK,QAAQ,KAAK,GAAG;AACjC,OAAI,EAAE,KAAK,EAAE;AACb,OAAI,EAAE,KAAK,EAAE;;;AAInB,KAAI,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE;AAC3B,KAAI,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE;CAC3B,MAAM,IAAI,IAAI,EAAE,SAAS;AAEzB,KAAI,IAAI,IAAI,EAAE,KAAK,IAAI,EAAE;AACzB,KAAI,IAAI,IAAI,EAAE,KAAK,IAAI,EAAE;CACzB,MAAM,MAAM,QAAQ,aAAa,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,GAAG,EAAE;AAE1D,QAAO,QAAQ;AACf,QAAO,SAAS;AAChB,SAAQ,aAAa,KAAK,GAAG,EAAE;AAC/B,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;AA2BT,IAAa,eAAe,OAAyB,UAAkB;CACrE,MAAM,UAAU,KAAK,IAAI,MAAM,OAAO,MAAM,OAAO;CACnD,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,QAAQ;AACf,QAAO,SAAS;CAChB,MAAM,UAAU,OAAO,WAAW,KAAK;AACvC,SAAQ,MAAM;AACd,SAAQ,UAAU,OAAO,QAAQ,GAAG,OAAO,SAAS,EAAE;AACtD,SAAQ,QAAA,GAAA,aAAA,UAAgB,MAAM,CAAC;AAC/B,SAAQ,UAAU,OAAO,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAM,SAAS,EAAE;AAC7D,SAAQ,SAAS;AACjB,qBAAoB,QAAQ;AAC5B,QAAO,YAAY,OAAO,UAAU,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;AA2BnD,SAAgB,cAAc,KAA6B;CAEzD,MAAM,2BAAU,IAAI,OADN,6BACmB,EAAC,KAAK,IAAI;AAE3C,QAAO;EACL,UAAU,UAAU;EACpB,MAAM,UAAU;EACjB;;;;;;;;;;;;;;;;;;;;;AAsBH,IAAa,aAAa,QAAyB;AACjD,QAAO,IAAI,WAAW,WAAW,IAAI,IAAI,WAAW,UAAU;;;;;;;;;;;;;;;;;;;;AAqBhE,IAAa,iBAAiB,QAAyB;CACrD,MAAM,EAAE,UAAU,SAAS,cAAc,IAAI;AAC7C,QAAO,CAAC,EAAE,QAAQ,UAAU,WAAW,SAAS"}
1
+ {"version":3,"file":"media.cjs","names":[],"sources":["../src/media/blob-to-base64.ts","../src/media/blob-to-url.ts","../src/media/decode-data-url.ts","../src/media/file-to-blob.ts","../src/media/image-to-blob.ts","../src/media/is-base64-image.ts","../src/media/is-http-url.ts","../src/media/render-image.ts","../src/media/rotate-image.ts"],"sourcesContent":["/**\n * Reads a {@link Blob} as a **data URL** string (`data:<mime>;base64,...`) using {@link FileReader#readAsDataURL}.\n *\n * Useful for previewing uploads, embedding small assets inline, or serializing binary for APIs that\n * expect Base64-in-JSON. The result includes the MIME prefix, not raw Base64 alone — use\n * {@link decodeDataUrl} if you need the payload and type separately.\n *\n * @param blob - Any `Blob` or `File` (files are blobs).\n * @returns Resolves to the data URL string; rejects if reading fails.\n *\n * @example\n * ```ts\n * const dataUrl = await blobToBase64(file);\n * previewImg.src = dataUrl;\n * ```\n *\n * @example\n * ```ts\n * const fromFetch = await fetch('/api/export').then((r) => r.blob());\n * const dataUrl = await blobToBase64(fromFetch);\n * ```\n */\nexport function blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result as string);\n reader.onerror = reject;\n reader.readAsDataURL(blob);\n });\n}\n","/**\n * If `urlOrBlob` is already a string, returns it unchanged. If it is a {@link Blob}, returns\n * `URL.createObjectURL(blob)` — a short-lived `blob:` URL valid in this document until\n * {@link URL.revokeObjectURL} is called.\n *\n * Pair with {@link renderImage} or `<img src>` without re-fetching binary data. **Remember to\n * `revokeObjectURL`** when the URL is no longer needed to avoid retaining blob memory.\n *\n * @param urlOrBlob - Remote/http(s) URL string, data URL, or a `Blob` / `File`.\n * @returns A string suitable for `HTMLImageElement.src` or similar.\n *\n * @example\n * ```ts\n * const src = blobToUrl(uploadedFile);\n * img.src = src;\n * // when done:\n * URL.revokeObjectURL(src);\n * ```\n *\n * @example\n * ```ts\n * blobToUrl('https://cdn.example.com/logo.png'); // passed through as-is\n * ```\n */\nexport const blobToUrl = (urlOrBlob: string | Blob) =>\n urlOrBlob instanceof Blob ? URL.createObjectURL(urlOrBlob) : urlOrBlob;\n","interface DecodedDataUrl {\n mimeType?: string;\n data?: string;\n}\n\n/**\n * Parses a `data:` URL of the form `data:<mime>;base64,<payload>` into its MIME type and raw\n * Base64 body (without the `data:...;base64,` prefix). Non-matching strings yield `undefined`\n * fields in the result object.\n *\n * @param url - Full data URL string.\n * @returns `{ mimeType, data }` — both optional when the regex does not match.\n *\n * @example\n * ```ts\n * const { mimeType, data } = decodeDataUrl('data:image/png;base64,iVBORw0KGgo=');\n * // mimeType === 'image/png', data === 'iVBORw0KGgo='\n * ```\n *\n * @example\n * ```ts\n * decodeDataUrl('not-a-data-url'); // { mimeType: undefined, data: undefined }\n * ```\n */\nexport function decodeDataUrl(url: string): DecodedDataUrl {\n const regex = /^data:(.*);base64,\\s?(.*)$/;\n const matches = new RegExp(regex).exec(url);\n\n return {\n mimeType: matches?.[1],\n data: matches?.[2],\n };\n}\n","/**\n * Creates a new {@link Blob} from a {@link File}, copying the bytes and keeping `file.type` as\n * the blob's MIME type. Handy when an API accepts `Blob` but you only have `File`, or you want a\n * plain blob without the `File` name/lastModified metadata.\n *\n * @param file - Source file from an `<input type=\"file\">` or drag-and-drop.\n * @returns A `Blob` with the same content and `type` as the file.\n *\n * @example\n * ```ts\n * const blob = fileToBlob(fileFromInput);\n * await uploadEndpoint(blob);\n * ```\n *\n * @example\n * ```ts\n * const blob = fileToBlob(imageFile);\n * const url = URL.createObjectURL(blob);\n * ```\n */\nexport const fileToBlob = (file: File) => {\n return new Blob([file], { type: file.type });\n};\n","/**\n * Draws an {@link HTMLImageElement} onto an offscreen canvas, then builds a {@link Blob} from the\n * raster (via `canvas.toDataURL` + binary decode). Dimensions use `naturalWidth` / `naturalHeight`,\n * falling back to `300×300` if those are zero (e.g. not yet decoded).\n *\n * **CORS:** if the image is cross-origin without proper CORS headers, the canvas may be\n * *tainted* and `toDataURL` can throw — same browser rules as any canvas export.\n *\n * @param imageElement - Loaded image (`complete` / decoded recommended).\n * @param mimeType - Output MIME type, e.g. `'image/png'` (default) or `'image/jpeg'`. Encoder support is browser-dependent.\n * @returns Encoded image as a `Blob` with a matching `type` when possible.\n *\n * @example\n * ```ts\n * const img = await renderImage('/photo.jpg');\n * const jpegBlob = imageToBlob(img, 'image/jpeg');\n * ```\n *\n * @example\n * ```ts\n * const pngBlob = imageToBlob(cachedImg); // default image/png\n * ```\n */\nexport const imageToBlob = (\n imageElement: HTMLImageElement,\n mimeType: string = 'image/png',\n) => {\n const canvas = document.createElement('canvas');\n\n canvas.width = imageElement.naturalWidth || 300;\n canvas.height = imageElement.naturalHeight || 300;\n\n canvas.getContext('2d')!.drawImage(imageElement, 0, 0);\n\n const dataUri = canvas.toDataURL(mimeType, 1);\n const base64data = dataUri.split(',')[1];\n const base64MimeType = dataUri.split(';')[0].slice(5);\n\n const bytes = globalThis.atob(base64data);\n const buf = new ArrayBuffer(bytes.length);\n const array = new Uint8Array(buf);\n\n for (let index = 0; index < bytes.length; index++) {\n array[index] = bytes.charCodeAt(index);\n }\n\n const blob = new Blob([array], { type: base64MimeType });\n\n return blob;\n};\n","import { decodeDataUrl } from './decode-data-url.js';\n\n/**\n * Returns `true` when `str` is a data URL that {@link decodeDataUrl} can parse **and** the MIME\n * type starts with `image/` (e.g. `image/png`, `image/jpeg`). Requires both a non-empty Base64\n * payload and an image MIME — arbitrary `data:text/plain;base64,...` is `false`.\n *\n * @param str - Candidate string (often `img.src` or API payload).\n *\n * @example\n * ```ts\n * isBase64Image('data:image/png;base64,iVBORw0KGgo='); // true\n * ```\n *\n * @example\n * ```ts\n * isBase64Image('https://example.com/x.png'); // false\n * isBase64Image('data:text/plain;base64,SGk='); // false\n * ```\n */\nexport const isBase64Image = (str: string): boolean => {\n const { mimeType, data } = decodeDataUrl(str);\n return !!(data && mimeType?.startsWith('image/'));\n};\n","/**\n * Returns `true` if `url` starts with `https://` or `http://` (case-sensitive, as in\n * `String#startsWith`). Does not validate that the rest is a well-formed URL — only the scheme\n * prefix. `blob:`, `data:`, and relative paths return `false`.\n *\n * @param url - String to test (often a user-provided or configured href).\n *\n * @example\n * ```ts\n * isHttpUrl('https://example.com/path'); // true\n * isHttpUrl('http://localhost:3000'); // true\n * ```\n *\n * @example\n * ```ts\n * isHttpUrl('//cdn.example.com'); // false — no explicit http(s) prefix\n * isHttpUrl('/assets/logo.png'); // false — relative path\n * ```\n */\nexport const isHttpUrl = (url: string): boolean => {\n return url.startsWith('https://') || url.startsWith('http://');\n};\n","import { blobToUrl } from './blob-to-url.js';\n\n/**\n * Loads a resource into a new `HTMLImageElement`: `src` is set via {@link blobToUrl} (so blobs get\n * object URLs, strings are used directly). Resolves on `load` with the same element; rejects on\n * `error` (e.g. bad URL, network failure, corrupt image) **with no rejection value**.\n *\n * Does not add the node to the DOM — use the returned element for canvas, measuring, or\n * {@link imageToBlob}.\n *\n * @param urlOrBlob - Remote URL, data URL, or `Blob` / `File`.\n * @returns Promise that fulfills with the loaded `HTMLImageElement`.\n *\n * @example\n * ```ts\n * const img = await renderImage('https://example.com/pic.png');\n * document.body.appendChild(img);\n * ```\n *\n * @example\n * ```ts\n * const img = await renderImage(pickedFile);\n * const blob = imageToBlob(img, 'image/webp');\n * ```\n */\nexport const renderImage = (urlOrBlob: Blob | string) =>\n new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n image.src = blobToUrl(urlOrBlob);\n image.onload = () => resolve(image);\n image.onerror = () => reject();\n });\n","import { degToRad } from 'yummies/math';\nimport { renderImage } from './render-image.js';\n\nfunction cropImageFromCanvas(context: CanvasRenderingContext2D) {\n const canvas = context.canvas;\n let w = canvas.width;\n let h = canvas.height;\n const pix: { x: number[]; y: number[] } = { x: [], y: [] };\n const imageData = context.getImageData(0, 0, canvas.width, canvas.height);\n let x: number;\n let y: number;\n let index: number;\n\n for (y = 0; y < h; y++) {\n for (x = 0; x < w; x++) {\n index = (y * w + x) * 4;\n if (imageData.data[index + 3] > 0) {\n pix.x.push(x);\n pix.y.push(y);\n }\n }\n }\n pix.x.sort((a, b) => a - b);\n pix.y.sort((a, b) => a - b);\n const n = pix.x.length - 1;\n\n w = 1 + pix.x[n] - pix.x[0];\n h = 1 + pix.y[n] - pix.y[0];\n const cut = context.getImageData(pix.x[0], pix.y[0], w, h);\n\n canvas.width = w;\n canvas.height = h;\n context.putImageData(cut, 0, 0);\n return canvas;\n}\n\n// TODO: ломает iphone с огромными изображениями\n/**\n * Rotates `image` around its center on a square canvas (side = max(width, height)), then **crops**\n * transparent margins by trimming to the bounding box of pixels with non-zero alpha.\n * Returns a **new** loaded `HTMLImageElement` (PNG data URL under the hood via {@link renderImage}).\n *\n * `angle` is in **degrees**; converted with {@link degToRad} from `yummies/math`.\n *\n * Very large sources can stress memory on some mobile browsers (known iPhone issues — see TODO in source).\n *\n * @param image - Source image (should be decoded; uses `width` / `height`).\n * @param angle - Rotation in degrees (e.g. `90` for quarter turn).\n * @returns Promise of a new `HTMLImageElement` showing the rotated, cropped result.\n *\n * @example\n * ```ts\n * const upright = await rotateImage(landscapeImg, 90);\n * ```\n *\n * @example\n * ```ts\n * const fixed = await rotateImage(await renderImage(file), -15);\n * ```\n */\nexport const rotateImage = (image: HTMLImageElement, angle: number) => {\n const maxSize = Math.max(image.width, image.height);\n const canvas = document.createElement('canvas');\n canvas.width = maxSize;\n canvas.height = maxSize;\n const context = canvas.getContext('2d')!;\n context.save();\n context.translate(canvas.width / 2, canvas.height / 2);\n context.rotate(degToRad(angle));\n context.drawImage(image, -image.width / 2, -image.height / 2);\n context.restore();\n cropImageFromCanvas(context);\n return renderImage(canvas.toDataURL('image/png'));\n};\n"],"mappings":"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"}
package/media.d.ts CHANGED
@@ -1,19 +1,3 @@
1
- /**
2
- * ---header-docs-section---
3
- * # yummies/media
4
- *
5
- * ## Description
6
- *
7
- * Binary and media helpers: Base64 data URLs, object URLs, image orientation fixes, and related
8
- * browser APIs wrapped in promises. Centralizes `FileReader`/`URL.createObjectURL` usage so image
9
- * pipelines and uploads stay consistent and easier to test or mock.
10
- *
11
- * ## Usage
12
- *
13
- * ```ts
14
- * import { blobToBase64 } from "yummies/media";
15
- * ```
16
- */
17
1
  /**
18
2
  * Reads a {@link Blob} as a **data URL** string (`data:<mime>;base64,...`) using {@link FileReader#readAsDataURL}.
19
3
  *
@@ -37,6 +21,7 @@
37
21
  * ```
38
22
  */
39
23
  declare function blobToBase64(blob: Blob): Promise<string>;
24
+
40
25
  /**
41
26
  * If `urlOrBlob` is already a string, returns it unchanged. If it is a {@link Blob}, returns
42
27
  * `URL.createObjectURL(blob)` — a short-lived `blob:` URL valid in this document until
@@ -62,9 +47,35 @@ declare function blobToBase64(blob: Blob): Promise<string>;
62
47
  * ```
63
48
  */
64
49
  declare const blobToUrl: (urlOrBlob: string | Blob) => string;
50
+
51
+ interface DecodedDataUrl {
52
+ mimeType?: string;
53
+ data?: string;
54
+ }
55
+ /**
56
+ * Parses a `data:` URL of the form `data:<mime>;base64,<payload>` into its MIME type and raw
57
+ * Base64 body (without the `data:...;base64,` prefix). Non-matching strings yield `undefined`
58
+ * fields in the result object.
59
+ *
60
+ * @param url - Full data URL string.
61
+ * @returns `{ mimeType, data }` — both optional when the regex does not match.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const { mimeType, data } = decodeDataUrl('data:image/png;base64,iVBORw0KGgo=');
66
+ * // mimeType === 'image/png', data === 'iVBORw0KGgo='
67
+ * ```
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * decodeDataUrl('not-a-data-url'); // { mimeType: undefined, data: undefined }
72
+ * ```
73
+ */
74
+ declare function decodeDataUrl(url: string): DecodedDataUrl;
75
+
65
76
  /**
66
77
  * Creates a new {@link Blob} from a {@link File}, copying the bytes and keeping `file.type` as
67
- * the blobs MIME type. Handy when an API accepts `Blob` but you only have `File`, or you want a
78
+ * the blob's MIME type. Handy when an API accepts `Blob` but you only have `File`, or you want a
68
79
  * plain blob without the `File` name/lastModified metadata.
69
80
  *
70
81
  * @param file - Source file from an `<input type="file">` or drag-and-drop.
@@ -83,6 +94,7 @@ declare const blobToUrl: (urlOrBlob: string | Blob) => string;
83
94
  * ```
84
95
  */
85
96
  declare const fileToBlob: (file: File) => Blob;
97
+
86
98
  /**
87
99
  * Draws an {@link HTMLImageElement} onto an offscreen canvas, then builds a {@link Blob} from the
88
100
  * raster (via `canvas.toDataURL` + binary decode). Dimensions use `naturalWidth` / `naturalHeight`,
@@ -107,6 +119,48 @@ declare const fileToBlob: (file: File) => Blob;
107
119
  * ```
108
120
  */
109
121
  declare const imageToBlob: (imageElement: HTMLImageElement, mimeType?: string) => Blob;
122
+
123
+ /**
124
+ * Returns `true` when `str` is a data URL that {@link decodeDataUrl} can parse **and** the MIME
125
+ * type starts with `image/` (e.g. `image/png`, `image/jpeg`). Requires both a non-empty Base64
126
+ * payload and an image MIME — arbitrary `data:text/plain;base64,...` is `false`.
127
+ *
128
+ * @param str - Candidate string (often `img.src` or API payload).
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * isBase64Image('data:image/png;base64,iVBORw0KGgo='); // true
133
+ * ```
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * isBase64Image('https://example.com/x.png'); // false
138
+ * isBase64Image('data:text/plain;base64,SGk='); // false
139
+ * ```
140
+ */
141
+ declare const isBase64Image: (str: string) => boolean;
142
+
143
+ /**
144
+ * Returns `true` if `url` starts with `https://` or `http://` (case-sensitive, as in
145
+ * `String#startsWith`). Does not validate that the rest is a well-formed URL — only the scheme
146
+ * prefix. `blob:`, `data:`, and relative paths return `false`.
147
+ *
148
+ * @param url - String to test (often a user-provided or configured href).
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * isHttpUrl('https://example.com/path'); // true
153
+ * isHttpUrl('http://localhost:3000'); // true
154
+ * ```
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * isHttpUrl('//cdn.example.com'); // false — no explicit http(s) prefix
159
+ * isHttpUrl('/assets/logo.png'); // false — relative path
160
+ * ```
161
+ */
162
+ declare const isHttpUrl: (url: string) => boolean;
163
+
110
164
  /**
111
165
  * Loads a resource into a new `HTMLImageElement`: `src` is set via {@link blobToUrl} (so blobs get
112
166
  * object URLs, strings are used directly). Resolves on `load` with the same element; rejects on
@@ -131,6 +185,7 @@ declare const imageToBlob: (imageElement: HTMLImageElement, mimeType?: string) =
131
185
  * ```
132
186
  */
133
187
  declare const renderImage: (urlOrBlob: Blob | string) => Promise<HTMLImageElement>;
188
+
134
189
  /**
135
190
  * Rotates `image` around its center on a square canvas (side = max(width, height)), then **crops**
136
191
  * transparent margins by trimming to the bounding box of pixels with non-zero alpha.
@@ -155,68 +210,5 @@ declare const renderImage: (urlOrBlob: Blob | string) => Promise<HTMLImageElemen
155
210
  * ```
156
211
  */
157
212
  declare const rotateImage: (image: HTMLImageElement, angle: number) => Promise<HTMLImageElement>;
158
- interface DecodedDataUrl {
159
- mimeType?: string;
160
- data?: string;
161
- }
162
- /**
163
- * Parses a `data:` URL of the form `data:<mime>;base64,<payload>` into its MIME type and raw
164
- * Base64 body (without the `data:...;base64,` prefix). Non-matching strings yield `undefined`
165
- * fields in the result object.
166
- *
167
- * @param url - Full data URL string.
168
- * @returns `{ mimeType, data }` — both optional when the regex does not match.
169
- *
170
- * @example
171
- * ```ts
172
- * const { mimeType, data } = decodeDataUrl('data:image/png;base64,iVBORw0KGgo=');
173
- * // mimeType === 'image/png', data === 'iVBORw0KGgo='
174
- * ```
175
- *
176
- * @example
177
- * ```ts
178
- * decodeDataUrl('not-a-data-url'); // { mimeType: undefined, data: undefined }
179
- * ```
180
- */
181
- declare function decodeDataUrl(url: string): DecodedDataUrl;
182
- /**
183
- * Returns `true` if `url` starts with `https://` or `http://` (case-sensitive, as in
184
- * `String#startsWith`). Does not validate that the rest is a well-formed URL — only the scheme
185
- * prefix. `blob:`, `data:`, and relative paths return `false`.
186
- *
187
- * @param url - String to test (often a user-provided or configured href).
188
- *
189
- * @example
190
- * ```ts
191
- * isHttpUrl('https://example.com/path'); // true
192
- * isHttpUrl('http://localhost:3000'); // true
193
- * ```
194
- *
195
- * @example
196
- * ```ts
197
- * isHttpUrl('//cdn.example.com'); // false — no explicit http(s) prefix
198
- * isHttpUrl('/assets/logo.png'); // false — relative path
199
- * ```
200
- */
201
- declare const isHttpUrl: (url: string) => boolean;
202
- /**
203
- * Returns `true` when `str` is a data URL that {@link decodeDataUrl} can parse **and** the MIME
204
- * type starts with `image/` (e.g. `image/png`, `image/jpeg`). Requires both a non-empty Base64
205
- * payload and an image MIME — arbitrary `data:text/plain;base64,...` is `false`.
206
- *
207
- * @param str - Candidate string (often `img.src` or API payload).
208
- *
209
- * @example
210
- * ```ts
211
- * isBase64Image('data:image/png;base64,iVBORw0KGgo='); // true
212
- * ```
213
- *
214
- * @example
215
- * ```ts
216
- * isBase64Image('https://example.com/x.png'); // false
217
- * isBase64Image('data:text/plain;base64,SGk='); // false
218
- * ```
219
- */
220
- declare const isBase64Image: (str: string) => boolean;
221
213
 
222
214
  export { blobToBase64, blobToUrl, decodeDataUrl, fileToBlob, imageToBlob, isBase64Image, isHttpUrl, renderImage, rotateImage };