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/html.cjs CHANGED
@@ -1,67 +1,42 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_chunk = require("./chunk-CZWwpsFl.cjs");
3
- let dompurify = require("dompurify");
4
- dompurify = require_chunk.__toESM(dompurify, 1);
2
+ const require_sanitize_html = require("./sanitize-html.cjs");
5
3
  let yummies_media = require("yummies/media");
6
- //#region src/html.ts
4
+ //#region src/html/calc-scrollbar-width.ts
7
5
  /**
8
- * ---header-docs-section---
9
- * # yummies/html
10
- *
11
- * ## Description
12
- *
13
- * DOM-centric utilities: sanitizing HTML with **DOMPurify**, computed style probes, downloads via
14
- * temporary anchors, and small string helpers for safe markup. Prefer these over `innerHTML` with
15
- * raw user input; keep CSP and server-side validation as the real security boundary.
16
- *
17
- * ## Usage
18
- *
19
- * ```ts
20
- * import { getComputedColor } from "yummies/html";
21
- * ```
22
- */
23
- /**
24
- * Extracts an RGB value from any valid CSS color.
25
- *
26
- * Not recommended for frequent use because it triggers a reflow.
6
+ * Calculates the scrollbar width.
27
7
  */
28
- var getComputedColor = (color) => {
29
- if (!color) return null;
30
- const d = document.createElement("div");
31
- d.style.color = color;
32
- document.body.append(d);
33
- const rgbcolor = globalThis.getComputedStyle(d).color;
34
- const match = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[.d+]*)*\)/g.exec(rgbcolor);
35
- d.remove();
36
- if (!match) return null;
37
- return `${match[1]}, ${match[2]}, ${match[3]}`;
8
+ var calcScrollbarWidth = (elementToAppend = document.body) => {
9
+ const outer = document.createElement("div");
10
+ outer.style.visibility = "hidden";
11
+ outer.style.width = "100px";
12
+ outer.style.overflow = "scroll";
13
+ elementToAppend.append(outer);
14
+ const inner = document.createElement("div");
15
+ inner.style.width = "100%";
16
+ outer.append(inner);
17
+ const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
18
+ outer.parentNode?.removeChild(outer);
19
+ return scrollbarWidth;
38
20
  };
21
+ //#endregion
22
+ //#region src/html/check-element-has-parent.ts
39
23
  /**
40
- * Triggers a file download by creating and clicking a temporary anchor element.
24
+ * Checks whether the element is nested inside the provided parent element.
41
25
  *
42
26
  * @example
43
27
  * ```ts
44
- * downloadUsingAnchor('/report.pdf', 'report.pdf');
28
+ * checkElementHasParent(childElement, modalElement);
45
29
  * ```
46
30
  */
47
- var downloadUsingAnchor = (urlOrBlob, fileName) => {
48
- const url = (0, yummies_media.blobToUrl)(urlOrBlob);
49
- const a = document.createElement("a");
50
- a.href = url;
51
- a.download = fileName ?? "file";
52
- a.target = "_blank";
53
- document.body.append(a);
54
- a.click();
55
- a.remove();
31
+ var checkElementHasParent = (element, parent) => {
32
+ let node = element;
33
+ if (!parent) return false;
34
+ while (node != null) if (node === parent) return true;
35
+ else node = node.parentElement;
36
+ return false;
56
37
  };
57
- /**
58
- * Surrounds string in an anchor tag
59
- */
60
- function wrapTextToTagLink(link) {
61
- const descr = String(link).replace(/^(https?:\/{0,2})?(w{3}\.)?/, "www.");
62
- if (!/^https?:\/{2}/.test(link)) link = `http://${link}`;
63
- return `<a href=${link} target="_blank">${descr}</a>`;
64
- }
38
+ //#endregion
39
+ //#region src/html/collect-offset-top.ts
65
40
  /**
66
41
  * Collects the cumulative `offsetTop` value through the element parent chain.
67
42
  *
@@ -79,19 +54,66 @@ var collectOffsetTop = (element) => {
79
54
  }
80
55
  return offsetTop;
81
56
  };
57
+ //#endregion
58
+ //#region src/html/download-using-anchor.ts
82
59
  /**
83
- * Prevents the default browser action and stops event propagation.
60
+ * Triggers a file download by creating and clicking a temporary anchor element.
84
61
  *
85
62
  * @example
86
63
  * ```ts
87
- * button.addEventListener('click', (event) => skipEvent(event));
64
+ * downloadUsingAnchor('/report.pdf', 'report.pdf');
88
65
  * ```
89
66
  */
90
- var skipEvent = (e) => {
91
- e.preventDefault();
92
- e.stopPropagation();
93
- return false;
67
+ var downloadUsingAnchor = (urlOrBlob, fileName) => {
68
+ const url = (0, yummies_media.blobToUrl)(urlOrBlob);
69
+ const a = document.createElement("a");
70
+ a.href = url;
71
+ a.download = fileName ?? "file";
72
+ a.target = "_blank";
73
+ document.body.append(a);
74
+ a.click();
75
+ a.remove();
94
76
  };
77
+ //#endregion
78
+ //#region src/html/get-computed-color.ts
79
+ /**
80
+ * Extracts an RGB value from any valid CSS color.
81
+ *
82
+ * Not recommended for frequent use because it triggers a reflow.
83
+ */
84
+ var getComputedColor = (color) => {
85
+ if (!color) return null;
86
+ const d = document.createElement("div");
87
+ d.style.color = color;
88
+ document.body.append(d);
89
+ const rgbcolor = globalThis.getComputedStyle(d).color;
90
+ const match = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[.d+]*)*\)/g.exec(rgbcolor);
91
+ d.remove();
92
+ if (!match) return null;
93
+ return `${match[1]}, ${match[2]}, ${match[3]}`;
94
+ };
95
+ //#endregion
96
+ //#region src/html/get-element-inner-height.ts
97
+ /**
98
+ * Calculates the inner height of an HTML element, accounting for padding.
99
+ */
100
+ function getElementInnerHeight(element) {
101
+ const { clientHeight } = element;
102
+ const { paddingTop, paddingBottom } = getComputedStyle(element);
103
+ return clientHeight - Number.parseFloat(paddingTop) - Number.parseFloat(paddingBottom);
104
+ }
105
+ //#endregion
106
+ //#region src/html/get-element-inner-width.ts
107
+ /**
108
+ * Calculates the inner width of an HTML element, accounting for padding.
109
+ */
110
+ function getElementInnerWidth(el) {
111
+ const { clientWidth } = el;
112
+ const { paddingLeft, paddingRight } = getComputedStyle(el);
113
+ return clientWidth - Number.parseFloat(paddingLeft) - Number.parseFloat(paddingRight);
114
+ }
115
+ //#endregion
116
+ //#region src/html/global-scroll-into-view-for-y.ts
95
117
  /**
96
118
  * Scrolls the page vertically to the viewport section containing the target element.
97
119
  *
@@ -111,87 +133,45 @@ var globalScrollIntoViewForY = (node) => {
111
133
  behavior: "smooth"
112
134
  });
113
135
  };
114
- var sanitizeDefaults = {
115
- ALLOWED_TAGS: [
116
- "a",
117
- "article",
118
- "b",
119
- "blockquote",
120
- "br",
121
- "caption",
122
- "code",
123
- "del",
124
- "details",
125
- "div",
126
- "em",
127
- "h1",
128
- "h2",
129
- "h3",
130
- "h4",
131
- "h5",
132
- "h6",
133
- "hr",
134
- "i",
135
- "img",
136
- "ins",
137
- "kbd",
138
- "li",
139
- "main",
140
- "ol",
141
- "p",
142
- "pre",
143
- "section",
144
- "span",
145
- "strong",
146
- "sub",
147
- "summary",
148
- "sup",
149
- "table",
150
- "tbody",
151
- "td",
152
- "th",
153
- "thead",
154
- "tr",
155
- "u",
156
- "ul"
157
- ],
158
- ALLOWED_ATTR: [
159
- "href",
160
- "target",
161
- "name",
162
- "src",
163
- "class"
164
- ]
165
- };
136
+ //#endregion
137
+ //#region src/html/is-prefers-dark-theme.ts
166
138
  /**
167
- * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.
139
+ * Checks whether the user prefers a dark color scheme.
168
140
  *
169
141
  * @example
170
142
  * ```ts
171
- * sanitizeHtml('<img src=x onerror=alert(1) />');
143
+ * const prefersDark = isPrefersDarkTheme();
172
144
  * ```
173
145
  */
174
- var sanitizeHtml = (html, config) => {
175
- return dompurify.default.sanitize(html || "", {
176
- ...sanitizeDefaults,
177
- ...config
178
- });
179
- };
146
+ var isPrefersDarkTheme = () => !!globalThis.matchMedia?.("(prefers-color-scheme: dark)")?.matches;
147
+ //#endregion
148
+ //#region src/html/is-prefers-light-theme.ts
180
149
  /**
181
- * Checks whether the element is nested inside the provided parent element.
150
+ * Checks whether the user prefers a light color scheme.
182
151
  *
183
152
  * @example
184
153
  * ```ts
185
- * checkElementHasParent(childElement, modalElement);
154
+ * const prefersLight = isPrefersLightTheme();
186
155
  * ```
187
156
  */
188
- var checkElementHasParent = (element, parent) => {
189
- let node = element;
190
- if (!parent) return false;
191
- while (node != null) if (node === parent) return true;
192
- else node = node.parentElement;
157
+ var isPrefersLightTheme = () => !!globalThis.matchMedia?.("(prefers-color-scheme: light)")?.matches;
158
+ //#endregion
159
+ //#region src/html/skip-event.ts
160
+ /**
161
+ * Prevents the default browser action and stops event propagation.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * button.addEventListener('click', (event) => skipEvent(event));
166
+ * ```
167
+ */
168
+ var skipEvent = (e) => {
169
+ e.preventDefault();
170
+ e.stopPropagation();
193
171
  return false;
194
172
  };
173
+ //#endregion
174
+ //#region src/html/start-view-transition-safety.ts
195
175
  /**
196
176
  * Executes a function within a view transition if supported by the browser.
197
177
  *
@@ -204,56 +184,16 @@ var startViewTransitionSafety = (fn, params) => {
204
184
  if (typeof document !== "undefined" && document.startViewTransition && !params?.disabled) return document.startViewTransition(fn);
205
185
  fn();
206
186
  };
187
+ //#endregion
188
+ //#region src/html/wrap-text-to-tag-link.ts
207
189
  /**
208
- * Calculates the scrollbar width.
209
- */
210
- var calcScrollbarWidth = (elementToAppend = document.body) => {
211
- const outer = document.createElement("div");
212
- outer.style.visibility = "hidden";
213
- outer.style.width = "100px";
214
- outer.style.overflow = "scroll";
215
- elementToAppend.append(outer);
216
- const inner = document.createElement("div");
217
- inner.style.width = "100%";
218
- outer.append(inner);
219
- const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
220
- outer.parentNode?.removeChild(outer);
221
- return scrollbarWidth;
222
- };
223
- /**
224
- * Calculates the inner height of an HTML element, accounting for padding.
225
- */
226
- function getElementInnerHeight(element) {
227
- const { clientHeight } = element;
228
- const { paddingTop, paddingBottom } = getComputedStyle(element);
229
- return clientHeight - Number.parseFloat(paddingTop) - Number.parseFloat(paddingBottom);
230
- }
231
- /**
232
- * Calculates the inner width of an HTML element, accounting for padding.
190
+ * Surrounds string in an anchor tag
233
191
  */
234
- function getElementInnerWidth(el) {
235
- const { clientWidth } = el;
236
- const { paddingLeft, paddingRight } = getComputedStyle(el);
237
- return clientWidth - Number.parseFloat(paddingLeft) - Number.parseFloat(paddingRight);
192
+ function wrapTextToTagLink(link) {
193
+ const descr = String(link).replace(/^(https?:\/{0,2})?(w{3}\.)?/, "www.");
194
+ if (!/^https?:\/{2}/.test(link)) link = `http://${link}`;
195
+ return `<a href=${link} target="_blank">${descr}</a>`;
238
196
  }
239
- /**
240
- * Checks whether the user prefers a dark color scheme.
241
- *
242
- * @example
243
- * ```ts
244
- * const prefersDark = isPrefersDarkTheme();
245
- * ```
246
- */
247
- var isPrefersDarkTheme = () => !!globalThis.matchMedia?.("(prefers-color-scheme: dark)")?.matches;
248
- /**
249
- * Checks whether the user prefers a light color scheme.
250
- *
251
- * @example
252
- * ```ts
253
- * const prefersLight = isPrefersLightTheme();
254
- * ```
255
- */
256
- var isPrefersLightTheme = () => !!globalThis.matchMedia?.("(prefers-color-scheme: light)")?.matches;
257
197
  //#endregion
258
198
  exports.calcScrollbarWidth = calcScrollbarWidth;
259
199
  exports.checkElementHasParent = checkElementHasParent;
@@ -265,7 +205,7 @@ exports.getElementInnerWidth = getElementInnerWidth;
265
205
  exports.globalScrollIntoViewForY = globalScrollIntoViewForY;
266
206
  exports.isPrefersDarkTheme = isPrefersDarkTheme;
267
207
  exports.isPrefersLightTheme = isPrefersLightTheme;
268
- exports.sanitizeHtml = sanitizeHtml;
208
+ exports.sanitizeHtml = require_sanitize_html.sanitizeHtml;
269
209
  exports.skipEvent = skipEvent;
270
210
  exports.startViewTransitionSafety = startViewTransitionSafety;
271
211
  exports.wrapTextToTagLink = wrapTextToTagLink;
package/html.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"html.cjs","names":[],"sources":["../src/html.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/html\n *\n * ## Description\n *\n * DOM-centric utilities: sanitizing HTML with **DOMPurify**, computed style probes, downloads via\n * temporary anchors, and small string helpers for safe markup. Prefer these over `innerHTML` with\n * raw user input; keep CSP and server-side validation as the real security boundary.\n *\n * ## Usage\n *\n * ```ts\n * import { getComputedColor } from \"yummies/html\";\n * ```\n */\n\nimport DOMPurify, { type Config as DOMPurifyConfig } from 'dompurify';\nimport { blobToUrl } from 'yummies/media';\nimport type { Maybe } from 'yummies/types';\n\n/**\n * Extracts an RGB value from any valid CSS color.\n *\n * Not recommended for frequent use because it triggers a reflow.\n */\nexport const getComputedColor = (color?: string): string | null => {\n if (!color) return null;\n\n const d = document.createElement('div');\n d.style.color = color;\n document.body.append(d);\n const rgbcolor = globalThis.getComputedStyle(d).color;\n const match =\n /rgba?\\((\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*\\d+[.d+]*)*\\)/g.exec(rgbcolor);\n\n d.remove();\n\n if (!match) return null;\n\n return `${match[1]}, ${match[2]}, ${match[3]}`;\n};\n\n/**\n * Triggers a file download by creating and clicking a temporary anchor element.\n *\n * @example\n * ```ts\n * downloadUsingAnchor('/report.pdf', 'report.pdf');\n * ```\n */\nexport const downloadUsingAnchor = (\n urlOrBlob: string | Blob,\n fileName?: string,\n) => {\n const url = blobToUrl(urlOrBlob);\n\n const a = document.createElement('a');\n a.href = url;\n\n a.download = fileName ?? 'file';\n\n a.target = '_blank';\n\n document.body.append(a);\n\n a.click();\n\n a.remove();\n};\n\n/**\n * Surrounds string in an anchor tag\n */\nexport function wrapTextToTagLink(link: string) {\n const descr = String(link).replace(/^(https?:\\/{0,2})?(w{3}\\.)?/, 'www.');\n if (!/^https?:\\/{2}/.test(link)) link = `http://${link}`;\n return `<a href=${link} target=\"_blank\">${descr}</a>`;\n}\n\n/**\n * Collects the cumulative `offsetTop` value through the element parent chain.\n *\n * @example\n * ```ts\n * const offsetTop = collectOffsetTop(document.getElementById('section'));\n * ```\n */\nexport const collectOffsetTop = (element: HTMLElement | null) => {\n let offsetTop = 0;\n let node = element;\n\n while (node != null) {\n offsetTop += node.offsetTop;\n node = node.parentElement;\n }\n\n return offsetTop;\n};\n\n/**\n * Prevents the default browser action and stops event propagation.\n *\n * @example\n * ```ts\n * button.addEventListener('click', (event) => skipEvent(event));\n * ```\n */\nexport const skipEvent = (e: Event) => {\n e.preventDefault();\n e.stopPropagation();\n\n return false;\n};\n\n/**\n * Scrolls the page vertically to the viewport section containing the target element.\n *\n * @example\n * ```ts\n * globalScrollIntoViewForY(document.getElementById('footer')!);\n * ```\n */\nexport const globalScrollIntoViewForY = (node: HTMLElement) => {\n const scrollContainer = document.body;\n const pageHeight = window.innerHeight;\n const nodeBounding = node.getBoundingClientRect();\n const scrollPagesCount = scrollContainer.scrollHeight / pageHeight;\n\n const scrollPageNumber = Math.min(\n Math.max(nodeBounding.top / pageHeight, 1),\n scrollPagesCount,\n );\n\n window.scroll({\n top: scrollPageNumber * pageHeight,\n behavior: 'smooth',\n });\n};\n\nconst sanitizeDefaults: DOMPurifyConfig = {\n ALLOWED_TAGS: [\n 'a',\n 'article',\n 'b',\n 'blockquote',\n 'br',\n 'caption',\n 'code',\n 'del',\n 'details',\n 'div',\n 'em',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'hr',\n 'i',\n 'img',\n 'ins',\n 'kbd',\n 'li',\n 'main',\n 'ol',\n 'p',\n 'pre',\n 'section',\n 'span',\n 'strong',\n 'sub',\n 'summary',\n 'sup',\n 'table',\n 'tbody',\n 'td',\n 'th',\n 'thead',\n 'tr',\n 'u',\n 'ul',\n ],\n ALLOWED_ATTR: ['href', 'target', 'name', 'src', 'class'],\n};\n\n/**\n * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.\n *\n * @example\n * ```ts\n * sanitizeHtml('<img src=x onerror=alert(1) />');\n * ```\n */\nexport const sanitizeHtml = (html: Maybe<string>, config?: DOMPurifyConfig) => {\n return DOMPurify.sanitize(html || '', {\n ...sanitizeDefaults,\n ...config,\n });\n};\n\n/**\n * Checks whether the element is nested inside the provided parent element.\n *\n * @example\n * ```ts\n * checkElementHasParent(childElement, modalElement);\n * ```\n */\nexport const checkElementHasParent = (\n element: HTMLElement | null,\n parent: Maybe<HTMLElement>,\n) => {\n let node = element;\n\n if (!parent) return false;\n\n while (node != null) {\n if (node === parent) {\n return true;\n } else {\n node = node.parentElement;\n }\n }\n\n return false;\n};\n\n/**\n * Executes a function within a view transition if supported by the browser.\n *\n * @param {VoidFunction} fn - The function to be executed.\n * @returns {ViewTransition} - The result of the executed function.\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition | MDN: Document.startViewTransition}\n */\nexport const startViewTransitionSafety = (\n fn: VoidFunction,\n params?: { disabled?: boolean },\n) => {\n if (\n typeof document !== 'undefined' &&\n document.startViewTransition &&\n !params?.disabled\n ) {\n return document.startViewTransition(fn);\n }\n fn();\n};\n\n/**\n * Calculates the scrollbar width.\n */\nexport const calcScrollbarWidth = (elementToAppend = document.body) => {\n const outer = document.createElement('div');\n\n outer.style.visibility = 'hidden';\n outer.style.width = '100px';\n outer.style.overflow = 'scroll';\n\n elementToAppend.append(outer);\n\n const inner = document.createElement('div');\n inner.style.width = '100%';\n\n outer.append(inner);\n\n const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;\n\n outer.parentNode?.removeChild(outer);\n\n return scrollbarWidth;\n};\n\n/**\n * Calculates the inner height of an HTML element, accounting for padding.\n */\nexport function getElementInnerHeight(element: HTMLElement) {\n const { clientHeight } = element;\n const { paddingTop, paddingBottom } = getComputedStyle(element);\n return (\n clientHeight -\n Number.parseFloat(paddingTop) -\n Number.parseFloat(paddingBottom)\n );\n}\n\n/**\n * Calculates the inner width of an HTML element, accounting for padding.\n */\nexport function getElementInnerWidth(el: HTMLElement) {\n const { clientWidth } = el;\n const { paddingLeft, paddingRight } = getComputedStyle(el);\n return (\n clientWidth -\n Number.parseFloat(paddingLeft) -\n Number.parseFloat(paddingRight)\n );\n}\n\n/**\n * Checks whether the user prefers a dark color scheme.\n *\n * @example\n * ```ts\n * const prefersDark = isPrefersDarkTheme();\n * ```\n */\nexport const isPrefersDarkTheme = () =>\n !!globalThis.matchMedia?.('(prefers-color-scheme: dark)')?.matches;\n\n/**\n * Checks whether the user prefers a light color scheme.\n *\n * @example\n * ```ts\n * const prefersLight = isPrefersLightTheme();\n * ```\n */\nexport const isPrefersLightTheme = () =>\n !!globalThis.matchMedia?.('(prefers-color-scheme: light)')?.matches;\n"],"mappings":"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"}
1
+ {"version":3,"file":"html.cjs","names":[],"sources":["../src/html/calc-scrollbar-width.ts","../src/html/check-element-has-parent.ts","../src/html/collect-offset-top.ts","../src/html/download-using-anchor.ts","../src/html/get-computed-color.ts","../src/html/get-element-inner-height.ts","../src/html/get-element-inner-width.ts","../src/html/global-scroll-into-view-for-y.ts","../src/html/is-prefers-dark-theme.ts","../src/html/is-prefers-light-theme.ts","../src/html/skip-event.ts","../src/html/start-view-transition-safety.ts","../src/html/wrap-text-to-tag-link.ts"],"sourcesContent":["/**\n * Calculates the scrollbar width.\n */\nexport const calcScrollbarWidth = (elementToAppend = document.body) => {\n const outer = document.createElement('div');\n\n outer.style.visibility = 'hidden';\n outer.style.width = '100px';\n outer.style.overflow = 'scroll';\n\n elementToAppend.append(outer);\n\n const inner = document.createElement('div');\n inner.style.width = '100%';\n\n outer.append(inner);\n\n const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;\n\n outer.parentNode?.removeChild(outer);\n\n return scrollbarWidth;\n};\n","import type { Maybe } from 'yummies/types';\n\n/**\n * Checks whether the element is nested inside the provided parent element.\n *\n * @example\n * ```ts\n * checkElementHasParent(childElement, modalElement);\n * ```\n */\nexport const checkElementHasParent = (\n element: HTMLElement | null,\n parent: Maybe<HTMLElement>,\n) => {\n let node = element;\n\n if (!parent) return false;\n\n while (node != null) {\n if (node === parent) {\n return true;\n } else {\n node = node.parentElement;\n }\n }\n\n return false;\n};\n","/**\n * Collects the cumulative `offsetTop` value through the element parent chain.\n *\n * @example\n * ```ts\n * const offsetTop = collectOffsetTop(document.getElementById('section'));\n * ```\n */\nexport const collectOffsetTop = (element: HTMLElement | null) => {\n let offsetTop = 0;\n let node = element;\n\n while (node != null) {\n offsetTop += node.offsetTop;\n node = node.parentElement;\n }\n\n return offsetTop;\n};\n","import { blobToUrl } from 'yummies/media';\n\n/**\n * Triggers a file download by creating and clicking a temporary anchor element.\n *\n * @example\n * ```ts\n * downloadUsingAnchor('/report.pdf', 'report.pdf');\n * ```\n */\nexport const downloadUsingAnchor = (\n urlOrBlob: string | Blob,\n fileName?: string,\n) => {\n const url = blobToUrl(urlOrBlob);\n\n const a = document.createElement('a');\n a.href = url;\n\n a.download = fileName ?? 'file';\n\n a.target = '_blank';\n\n document.body.append(a);\n\n a.click();\n\n a.remove();\n};\n","/**\n * Extracts an RGB value from any valid CSS color.\n *\n * Not recommended for frequent use because it triggers a reflow.\n */\nexport const getComputedColor = (color?: string): string | null => {\n if (!color) return null;\n\n const d = document.createElement('div');\n d.style.color = color;\n document.body.append(d);\n const rgbcolor = globalThis.getComputedStyle(d).color;\n const match =\n /rgba?\\((\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*\\d+[.d+]*)*\\)/g.exec(rgbcolor);\n\n d.remove();\n\n if (!match) return null;\n\n return `${match[1]}, ${match[2]}, ${match[3]}`;\n};\n","/**\n * Calculates the inner height of an HTML element, accounting for padding.\n */\nexport function getElementInnerHeight(element: HTMLElement) {\n const { clientHeight } = element;\n const { paddingTop, paddingBottom } = getComputedStyle(element);\n return (\n clientHeight -\n Number.parseFloat(paddingTop) -\n Number.parseFloat(paddingBottom)\n );\n}\n","/**\n * Calculates the inner width of an HTML element, accounting for padding.\n */\nexport function getElementInnerWidth(el: HTMLElement) {\n const { clientWidth } = el;\n const { paddingLeft, paddingRight } = getComputedStyle(el);\n return (\n clientWidth -\n Number.parseFloat(paddingLeft) -\n Number.parseFloat(paddingRight)\n );\n}\n","/**\n * Scrolls the page vertically to the viewport section containing the target element.\n *\n * @example\n * ```ts\n * globalScrollIntoViewForY(document.getElementById('footer')!);\n * ```\n */\nexport const globalScrollIntoViewForY = (node: HTMLElement) => {\n const scrollContainer = document.body;\n const pageHeight = window.innerHeight;\n const nodeBounding = node.getBoundingClientRect();\n const scrollPagesCount = scrollContainer.scrollHeight / pageHeight;\n\n const scrollPageNumber = Math.min(\n Math.max(nodeBounding.top / pageHeight, 1),\n scrollPagesCount,\n );\n\n window.scroll({\n top: scrollPageNumber * pageHeight,\n behavior: 'smooth',\n });\n};\n","/**\n * Checks whether the user prefers a dark color scheme.\n *\n * @example\n * ```ts\n * const prefersDark = isPrefersDarkTheme();\n * ```\n */\nexport const isPrefersDarkTheme = () =>\n !!globalThis.matchMedia?.('(prefers-color-scheme: dark)')?.matches;\n","/**\n * Checks whether the user prefers a light color scheme.\n *\n * @example\n * ```ts\n * const prefersLight = isPrefersLightTheme();\n * ```\n */\nexport const isPrefersLightTheme = () =>\n !!globalThis.matchMedia?.('(prefers-color-scheme: light)')?.matches;\n","/**\n * Prevents the default browser action and stops event propagation.\n *\n * @example\n * ```ts\n * button.addEventListener('click', (event) => skipEvent(event));\n * ```\n */\nexport const skipEvent = (e: Event) => {\n e.preventDefault();\n e.stopPropagation();\n\n return false;\n};\n","/**\n * Executes a function within a view transition if supported by the browser.\n *\n * @param {VoidFunction} fn - The function to be executed.\n * @returns {ViewTransition} - The result of the executed function.\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition | MDN: Document.startViewTransition}\n */\nexport const startViewTransitionSafety = (\n fn: VoidFunction,\n params?: { disabled?: boolean },\n) => {\n if (\n typeof document !== 'undefined' &&\n document.startViewTransition &&\n !params?.disabled\n ) {\n return document.startViewTransition(fn);\n }\n fn();\n};\n","/**\n * Surrounds string in an anchor tag\n */\nexport function wrapTextToTagLink(link: string) {\n const descr = String(link).replace(/^(https?:\\/{0,2})?(w{3}\\.)?/, 'www.');\n if (!/^https?:\\/{2}/.test(link)) link = `http://${link}`;\n return `<a href=${link} target=\"_blank\">${descr}</a>`;\n}\n"],"mappings":"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"}
package/html.d.ts CHANGED
@@ -1,29 +1,31 @@
1
- import { Config } from 'dompurify';
2
1
  import { Maybe } from 'yummies/types';
2
+ import { Config } from 'dompurify';
3
3
 
4
4
  /**
5
- * ---header-docs-section---
6
- * # yummies/html
7
- *
8
- * ## Description
9
- *
10
- * DOM-centric utilities: sanitizing HTML with **DOMPurify**, computed style probes, downloads via
11
- * temporary anchors, and small string helpers for safe markup. Prefer these over `innerHTML` with
12
- * raw user input; keep CSP and server-side validation as the real security boundary.
13
- *
14
- * ## Usage
5
+ * Calculates the scrollbar width.
6
+ */
7
+ declare const calcScrollbarWidth: (elementToAppend?: HTMLElement) => number;
8
+
9
+ /**
10
+ * Checks whether the element is nested inside the provided parent element.
15
11
  *
12
+ * @example
16
13
  * ```ts
17
- * import { getComputedColor } from "yummies/html";
14
+ * checkElementHasParent(childElement, modalElement);
18
15
  * ```
19
16
  */
17
+ declare const checkElementHasParent: (element: HTMLElement | null, parent: Maybe<HTMLElement>) => boolean;
20
18
 
21
19
  /**
22
- * Extracts an RGB value from any valid CSS color.
20
+ * Collects the cumulative `offsetTop` value through the element parent chain.
23
21
  *
24
- * Not recommended for frequent use because it triggers a reflow.
22
+ * @example
23
+ * ```ts
24
+ * const offsetTop = collectOffsetTop(document.getElementById('section'));
25
+ * ```
25
26
  */
26
- declare const getComputedColor: (color?: string) => string | null;
27
+ declare const collectOffsetTop: (element: HTMLElement | null) => number;
28
+
27
29
  /**
28
30
  * Triggers a file download by creating and clicking a temporary anchor element.
29
31
  *
@@ -33,55 +35,88 @@ declare const getComputedColor: (color?: string) => string | null;
33
35
  * ```
34
36
  */
35
37
  declare const downloadUsingAnchor: (urlOrBlob: string | Blob, fileName?: string) => void;
38
+
36
39
  /**
37
- * Surrounds string in an anchor tag
40
+ * Extracts an RGB value from any valid CSS color.
41
+ *
42
+ * Not recommended for frequent use because it triggers a reflow.
38
43
  */
39
- declare function wrapTextToTagLink(link: string): string;
44
+ declare const getComputedColor: (color?: string) => string | null;
45
+
40
46
  /**
41
- * Collects the cumulative `offsetTop` value through the element parent chain.
47
+ * Calculates the inner height of an HTML element, accounting for padding.
48
+ */
49
+ declare function getElementInnerHeight(element: HTMLElement): number;
50
+
51
+ /**
52
+ * Calculates the inner width of an HTML element, accounting for padding.
53
+ */
54
+ declare function getElementInnerWidth(el: HTMLElement): number;
55
+
56
+ /**
57
+ * Scrolls the page vertically to the viewport section containing the target element.
42
58
  *
43
59
  * @example
44
60
  * ```ts
45
- * const offsetTop = collectOffsetTop(document.getElementById('section'));
61
+ * globalScrollIntoViewForY(document.getElementById('footer')!);
46
62
  * ```
47
63
  */
48
- declare const collectOffsetTop: (element: HTMLElement | null) => number;
64
+ declare const globalScrollIntoViewForY: (node: HTMLElement) => void;
65
+
49
66
  /**
50
- * Prevents the default browser action and stops event propagation.
67
+ * Checks whether the user prefers a dark color scheme.
51
68
  *
52
69
  * @example
53
70
  * ```ts
54
- * button.addEventListener('click', (event) => skipEvent(event));
71
+ * const prefersDark = isPrefersDarkTheme();
55
72
  * ```
56
73
  */
57
- declare const skipEvent: (e: Event) => boolean;
74
+ declare const isPrefersDarkTheme: () => boolean;
75
+
58
76
  /**
59
- * Scrolls the page vertically to the viewport section containing the target element.
77
+ * Checks whether the user prefers a light color scheme.
60
78
  *
61
79
  * @example
62
80
  * ```ts
63
- * globalScrollIntoViewForY(document.getElementById('footer')!);
81
+ * const prefersLight = isPrefersLightTheme();
64
82
  * ```
65
83
  */
66
- declare const globalScrollIntoViewForY: (node: HTMLElement) => void;
84
+ declare const isPrefersLightTheme: () => boolean;
85
+
86
+ /**
87
+ * @internal Separate chunk so DOMPurify is tree-shaken away when `sanitizeHtml` is not used.
88
+ * Consumers import from `yummies/html` — this module is not a public entry point.
89
+ */
90
+
91
+ type SanitizeHtmlFn = ((html: Maybe<string>, config?: Config) => string) & {
92
+ /**
93
+ * Default DOMPurify settings
94
+ */
95
+ defaults: Config;
96
+ };
67
97
  /**
68
98
  * Sanitizes HTML using the default allowlist merged with custom DOMPurify config.
69
99
  *
100
+ * Default DOMPurify settings are exposed on `sanitizeHtml.defaults` and can be
101
+ * overridden per call via `config`.
102
+ *
70
103
  * @example
71
104
  * ```ts
72
105
  * sanitizeHtml('<img src=x onerror=alert(1) />');
73
106
  * ```
74
107
  */
75
- declare const sanitizeHtml: (html: Maybe<string>, config?: Config) => string;
108
+ declare const sanitizeHtml: SanitizeHtmlFn;
109
+
76
110
  /**
77
- * Checks whether the element is nested inside the provided parent element.
111
+ * Prevents the default browser action and stops event propagation.
78
112
  *
79
113
  * @example
80
114
  * ```ts
81
- * checkElementHasParent(childElement, modalElement);
115
+ * button.addEventListener('click', (event) => skipEvent(event));
82
116
  * ```
83
117
  */
84
- declare const checkElementHasParent: (element: HTMLElement | null, parent: Maybe<HTMLElement>) => boolean;
118
+ declare const skipEvent: (e: Event) => boolean;
119
+
85
120
  /**
86
121
  * Executes a function within a view transition if supported by the browser.
87
122
  *
@@ -93,35 +128,10 @@ declare const checkElementHasParent: (element: HTMLElement | null, parent: Maybe
93
128
  declare const startViewTransitionSafety: (fn: VoidFunction, params?: {
94
129
  disabled?: boolean;
95
130
  }) => ViewTransition | undefined;
131
+
96
132
  /**
97
- * Calculates the scrollbar width.
98
- */
99
- declare const calcScrollbarWidth: (elementToAppend?: HTMLElement) => number;
100
- /**
101
- * Calculates the inner height of an HTML element, accounting for padding.
102
- */
103
- declare function getElementInnerHeight(element: HTMLElement): number;
104
- /**
105
- * Calculates the inner width of an HTML element, accounting for padding.
106
- */
107
- declare function getElementInnerWidth(el: HTMLElement): number;
108
- /**
109
- * Checks whether the user prefers a dark color scheme.
110
- *
111
- * @example
112
- * ```ts
113
- * const prefersDark = isPrefersDarkTheme();
114
- * ```
115
- */
116
- declare const isPrefersDarkTheme: () => boolean;
117
- /**
118
- * Checks whether the user prefers a light color scheme.
119
- *
120
- * @example
121
- * ```ts
122
- * const prefersLight = isPrefersLightTheme();
123
- * ```
133
+ * Surrounds string in an anchor tag
124
134
  */
125
- declare const isPrefersLightTheme: () => boolean;
135
+ declare function wrapTextToTagLink(link: string): string;
126
136
 
127
137
  export { calcScrollbarWidth, checkElementHasParent, collectOffsetTop, downloadUsingAnchor, getComputedColor, getElementInnerHeight, getElementInnerWidth, globalScrollIntoViewForY, isPrefersDarkTheme, isPrefersLightTheme, sanitizeHtml, skipEvent, startViewTransitionSafety, wrapTextToTagLink };