@oscarpalmer/toretto 0.29.0 → 0.30.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.
package/package.json CHANGED
@@ -8,17 +8,15 @@
8
8
  },
9
9
  "description": "A collection of badass DOM utilities.",
10
10
  "devDependencies": {
11
- "@rollup/plugin-node-resolve": "^16",
12
- "@rollup/plugin-typescript": "^12.3",
13
- "@types/node": "^24.10",
11
+ "@types/node": "^25",
14
12
  "@vitest/coverage-istanbul": "^4",
15
- "jsdom": "^27.2",
16
- "oxfmt": "^0.16",
17
- "oxlint": "^1.31",
18
- "rollup": "^4.53",
13
+ "jsdom": "^27.3",
14
+ "oxfmt": "^0.18",
15
+ "oxlint": "^1.33",
16
+ "rolldown": "1.0.0-beta.55",
19
17
  "tslib": "^2.8",
20
18
  "typescript": "^5.9",
21
- "vite": "8.0.0-beta.0",
19
+ "vite": "8.0.0-beta.2",
22
20
  "vitest": "^4"
23
21
  },
24
22
  "exports": {
@@ -74,6 +72,8 @@
74
72
  ],
75
73
  "keywords": [
76
74
  "dom",
75
+ "html",
76
+ "sanitization",
77
77
  "utility"
78
78
  ],
79
79
  "license": "MIT",
@@ -84,14 +84,14 @@
84
84
  "url": "git+https://github.com/oscarpalmer/toretto.git"
85
85
  },
86
86
  "scripts": {
87
- "build": "npm run clean && npx vite build && npm run rollup:build && npx tsc",
87
+ "build": "npm run clean && npx vite build && npm run rolldown:build && npx tsc",
88
88
  "clean": "rm -rf ./dist && rm -rf ./types && rm -f ./tsconfig.tsbuildinfo",
89
- "rollup:build": "npx rollup -c",
90
- "rollup:watch": "npx rollup -c --watch",
89
+ "rolldown:build": "npx rolldown -c",
90
+ "rolldown:watch": "npx rolldown -c --watch",
91
91
  "test": "npx vitest --coverage",
92
92
  "watch": "npx vite build --watch"
93
93
  },
94
94
  "type": "module",
95
95
  "types": "types/index.d.ts",
96
- "version": "0.29.0"
96
+ "version": "0.30.0"
97
97
  }
@@ -1,9 +1,90 @@
1
- export {
2
- booleanAttributes,
3
- isBadAttribute,
4
- isBooleanAttribute,
5
- isEmptyNonBooleanAttribute,
6
- isInvalidBooleanAttribute,
1
+ import {
2
+ isBadAttribute as internalIsBadAttribute,
3
+ isBooleanAttribute as _isBooleanAttribute,
4
+ isEmptyNonBooleanAttribute as _isEmptyNonBooleanAttribute,
5
+ isInvalidBooleanAttribute as _isInvalidBooleanAttribute,
7
6
  } from '../internal/attribute';
7
+ import type {Attribute} from '../models';
8
+
9
+ /**
10
+ * Is the attribute considered bad and potentially harmful?
11
+ * @param attribute Attribute to check
12
+ * @returns `true` if attribute is considered bad
13
+ */
14
+ export function isBadAttribute(attribute: Attr | Attribute): boolean;
15
+
16
+ /**
17
+ * Is the attribute considered bad and potentially harmful?
18
+ * @param name Attribute name
19
+ * @param value Attribute value
20
+ * @returns `true` if attribute is considered bad
21
+ */
22
+ export function isBadAttribute(name: string, value: string): boolean;
23
+
24
+ export function isBadAttribute(first: unknown, second?: unknown): boolean {
25
+ return internalIsBadAttribute(first, second, true);
26
+ }
27
+
28
+ /**
29
+ * Is the attribute a boolean attribute?
30
+ * @param name Attribute to check
31
+ * @returns `true` if attribute is a boolean attribute
32
+ */
33
+ export function isBooleanAttribute(attribute: Attr | Attribute): boolean;
34
+
35
+ /**
36
+ * Is the attribute a boolean attribute?
37
+ * @param name Attribute name
38
+ * @returns `true` if attribute is a boolean attribute
39
+ */
40
+ export function isBooleanAttribute(name: string): boolean;
41
+
42
+ export function isBooleanAttribute(first: unknown): boolean {
43
+ return _isBooleanAttribute(first, true);
44
+ }
45
+
46
+ /**
47
+ * Is the attribute empty and not a boolean attribute?
48
+ * @param attribute Attribute to check
49
+ * @returns `true` if attribute is empty and not a boolean attribute
50
+ */
51
+ export function isEmptyNonBooleanAttribute(attribute: Attr | Attribute): boolean;
52
+
53
+ /**
54
+ * Is the attribute empty and not a boolean attribute?
55
+ * @param name Attribute name
56
+ * @param value Attribute value
57
+ * @returns `true` if attribute is empty and not a boolean attribute
58
+ */
59
+ export function isEmptyNonBooleanAttribute(name: string, value: string): boolean;
60
+
61
+ export function isEmptyNonBooleanAttribute(first: unknown, second?: unknown): boolean {
62
+ return _isEmptyNonBooleanAttribute(first, second, true);
63
+ }
64
+
65
+ /**
66
+ * Is the attribute an invalid boolean attribute?
67
+ *
68
+ * _(I.e., its value is not empty or the same as its name)_
69
+ * @param attribute Attribute to check
70
+ * @returns `true` if attribute is an invalid boolean attribute
71
+ */
72
+ export function isInvalidBooleanAttribute(attribute: Attr | Attribute): boolean;
73
+
74
+ /**
75
+ * Is the attribute an invalid boolean attribute?
76
+ *
77
+ * _(I.e., its value is not empty or the same as its name)_
78
+ * @param name Attribute name
79
+ * @param value Attribute value
80
+ * @returns `true` if attribute is an invalid boolean attribute
81
+ */
82
+ export function isInvalidBooleanAttribute(name: string, value: string): boolean;
83
+
84
+ export function isInvalidBooleanAttribute(first: unknown, second?: unknown): boolean {
85
+ return _isInvalidBooleanAttribute(first, second, true);
86
+ }
87
+
88
+ export {booleanAttributes} from '../internal/attribute';
8
89
  export * from './get';
9
90
  export * from './set';
@@ -1,5 +1,5 @@
1
1
  import {isPlainObject} from '@oscarpalmer/atoms/is';
2
- import {sanitizeNodes} from './internal/sanitize';
2
+ import {sanitizeNodes} from './sanitize';
3
3
 
4
4
  //
5
5
 
@@ -34,9 +34,9 @@ type Html = {
34
34
 
35
35
  type HtmlOptions = {
36
36
  /**
37
- * Ignore caching the template element for the HTML string? _(defaults to `false`)_
37
+ * Cache template element for the HTML string? _(defaults to `true`)_
38
38
  */
39
- ignoreCache?: boolean;
39
+ cache?: boolean;
40
40
  };
41
41
 
42
42
  type Options = Required<HtmlOptions>;
@@ -51,7 +51,7 @@ function createHtml(value: string | HTMLTemplateElement): string {
51
51
 
52
52
  html.body.normalize();
53
53
 
54
- sanitizeNodes([html.body]);
54
+ sanitizeNodes([html.body], 0);
55
55
 
56
56
  return html.body.innerHTML;
57
57
  }
@@ -64,7 +64,7 @@ function createTemplate(
64
64
 
65
65
  template.innerHTML = createHtml(value);
66
66
 
67
- if (typeof value === 'string' && !options.ignoreCache) {
67
+ if (typeof value === 'string' && options.cache) {
68
68
  templates[value] = template;
69
69
  }
70
70
 
@@ -84,7 +84,7 @@ function getNodes(value: string | HTMLTemplateElement, options: Options): Node[]
84
84
  function getOptions(input?: HtmlOptions): Options {
85
85
  const options = isPlainObject(input) ? input : {};
86
86
 
87
- options.ignoreCache = typeof options.ignoreCache === 'boolean' ? options.ignoreCache : false;
87
+ options.cache = typeof options.cache === 'boolean' ? options.cache : true;
88
88
 
89
89
  return options as Options;
90
90
  }
@@ -156,7 +156,7 @@ html.remove = (template: string): void => {
156
156
  * @returns Sanitized nodes
157
157
  */
158
158
  export function sanitize(value: Node | Node[]): Node[] {
159
- return sanitizeNodes(Array.isArray(value) ? value : [value]);
159
+ return sanitizeNodes(Array.isArray(value) ? value : [value], 0);
160
160
  }
161
161
 
162
162
  //
@@ -0,0 +1,83 @@
1
+ import {
2
+ isBadAttribute,
3
+ isEmptyNonBooleanAttribute,
4
+ isInvalidBooleanAttribute,
5
+ } from '../internal/attribute';
6
+
7
+ function handleElement(element: Element, depth: number): boolean {
8
+ if (isClobbered(element)) {
9
+ element.remove();
10
+
11
+ return true;
12
+ }
13
+
14
+ if (depth === 0) {
15
+ const scripts = element.querySelectorAll('script');
16
+
17
+ for (const script of scripts) {
18
+ script.remove();
19
+ }
20
+ }
21
+
22
+ sanitizeAttributes(element, [...element.attributes]);
23
+
24
+ return false;
25
+ }
26
+
27
+ /**
28
+ * Is the element clobbered?
29
+ *
30
+ * Thanks, DOMPurify _(https://github.com/cure53/DOMPurify)_
31
+ */
32
+ function isClobbered(element: Element): boolean {
33
+ return (
34
+ element instanceof HTMLFormElement &&
35
+ (typeof element.nodeName !== 'string' ||
36
+ typeof element.textContent !== 'string' ||
37
+ typeof element.removeChild !== 'function' ||
38
+ !(element.attributes instanceof NamedNodeMap) ||
39
+ typeof element.removeAttribute !== 'function' ||
40
+ typeof element.setAttribute !== 'function' ||
41
+ typeof element.namespaceURI !== 'string' ||
42
+ typeof element.insertBefore !== 'function' ||
43
+ typeof element.hasChildNodes !== 'function')
44
+ );
45
+ }
46
+
47
+ export function sanitizeAttributes(element: Element, attributes: Attr[]): void {
48
+ const {length} = attributes;
49
+
50
+ for (let index = 0; index < length; index += 1) {
51
+ const {name, value} = attributes[index];
52
+
53
+ if (isBadAttribute(name, value, false) || isEmptyNonBooleanAttribute(name, value, false)) {
54
+ element.removeAttribute(name);
55
+ } else if (isInvalidBooleanAttribute(name, value, false)) {
56
+ element.setAttribute(name, '');
57
+ }
58
+ }
59
+ }
60
+
61
+ export function sanitizeNodes(nodes: Node[], depth: number): Node[] {
62
+ const actual = nodes.filter(node => node instanceof Node);
63
+ let {length} = nodes;
64
+
65
+ for (let index = 0; index < length; index += 1) {
66
+ const node = actual[index];
67
+
68
+ if (node instanceof Element && handleElement(node, depth)) {
69
+ actual.splice(index, 1);
70
+
71
+ length -= 1;
72
+ index -= 1;
73
+
74
+ continue;
75
+ }
76
+
77
+ if (node.hasChildNodes()) {
78
+ sanitizeNodes([...node.childNodes], depth + 1);
79
+ }
80
+ }
81
+
82
+ return nodes;
83
+ }
package/src/index.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  import supportsTouch from './touch';
2
2
 
3
- export * from './attribute';
3
+ export {
4
+ isBadAttribute,
5
+ isBooleanAttribute,
6
+ isEmptyNonBooleanAttribute,
7
+ isInvalidBooleanAttribute,
8
+ } from './attribute';
4
9
  export * from './data';
5
10
  export * from './event/index';
6
11
  export * from './find/index';
7
12
  export * from './focusable';
8
- export * from './html';
13
+ export * from './html/index';
9
14
  export * from './is';
10
15
  export * from './models';
11
16
  export * from './style';
@@ -4,6 +4,75 @@ import {getString} from '@oscarpalmer/atoms/string';
4
4
  import type {Attribute, HTMLOrSVGElement, Property} from '../models';
5
5
  import {isHTMLOrSVGElement} from './is';
6
6
 
7
+ function badAttributeHandler(name?: string, value?: string): boolean {
8
+ if (name == null || value == null) {
9
+ return true;
10
+ }
11
+
12
+ if (
13
+ (EXPRESSION_CLOBBERED_NAME.test(name) && (value in document || value in formElement)) ||
14
+ EXPRESSION_EVENT_NAME.test(name)
15
+ ) {
16
+ return true;
17
+ }
18
+
19
+ if (
20
+ EXPRESSION_SKIP_NAME.test(name) ||
21
+ EXPRESSION_URI_VALUE.test(value) ||
22
+ isValidSourceAttribute(name, value)
23
+ ) {
24
+ return false;
25
+ }
26
+
27
+ return EXPRESSION_DATA_OR_SCRIPT.test(value);
28
+ }
29
+
30
+ function booleanAttributeHandler(name?: string, value?: string): boolean {
31
+ if (name == null || value == null) {
32
+ return true;
33
+ }
34
+
35
+ if (!booleanAttributesSet.has(name)) {
36
+ return false;
37
+ }
38
+
39
+ const normalized = value.toLowerCase().trim();
40
+
41
+ return !(normalized.length === 0 || normalized === name);
42
+ }
43
+
44
+ function decodeAttribute(value: string): string {
45
+ textArea ??= document.createElement('textarea');
46
+
47
+ textArea.innerHTML = value;
48
+
49
+ return decodeURIComponent(textArea.value);
50
+ }
51
+
52
+ function handleAttribute(
53
+ callback: (name?: string, value?: string) => boolean,
54
+ decode: boolean,
55
+ first: unknown,
56
+ second?: unknown,
57
+ ): boolean {
58
+ let name: string | undefined;
59
+ let value: string | undefined;
60
+
61
+ if (isAttribute(first)) {
62
+ name = first.name;
63
+ value = String(first.value);
64
+ } else if (typeof first === 'string' && typeof second === 'string') {
65
+ name = first;
66
+ value = second;
67
+ }
68
+
69
+ if (decode && value != null) {
70
+ value = decodeAttribute(value);
71
+ }
72
+
73
+ return callback(name, value?.replace(EXPRESSION_WHITESPACE, ''));
74
+ }
75
+
7
76
  function isAttribute(value: unknown): value is Attr | Attribute {
8
77
  return (
9
78
  value instanceof Attr ||
@@ -13,148 +82,51 @@ function isAttribute(value: unknown): value is Attr | Attribute {
13
82
  );
14
83
  }
15
84
 
16
- /**
17
- * Is the attribute considered bad and potentially harmful?
18
- * @param attribute Attribute to check
19
- * @returns `true` if attribute is considered bad
20
- */
21
- export function isBadAttribute(attribute: Attr | Attribute): boolean;
22
-
23
- /**
24
- * Is the attribute considered bad and potentially harmful?
25
- * @param name Attribute name
26
- * @param value Attribute value
27
- * @returns `true` if attribute is considered bad
28
- */
29
- export function isBadAttribute(name: string, value: string): boolean;
30
-
31
- export function isBadAttribute(first: string | Attr | Attribute, second?: string): boolean {
32
- return isValidAttribute(
33
- attribute =>
34
- attribute == null ||
35
- EXPRESSION_ON_PREFIX.test(attribute.name) ||
36
- (EXPRESSION_SOURCE_PREFIX.test(attribute.name) &&
37
- EXPRESSION_VALUE_PREFIX.test(String(attribute.value))),
38
- first,
39
- second,
40
- );
85
+ export function isBadAttribute(first: unknown, second: unknown, decode: boolean): boolean {
86
+ return handleAttribute(badAttributeHandler, decode, first, second);
41
87
  }
42
88
 
43
- /**
44
- * Is the attribute a boolean attribute?
45
- * @param name Attribute to check
46
- * @returns `true` if attribute is a boolean attribute
47
- */
48
- export function isBooleanAttribute(attribute: Attr | Attribute): boolean;
49
-
50
- /**
51
- * Is the attribute a boolean attribute?
52
- * @param name Attribute name
53
- * @returns `true` if attribute is a boolean attribute
54
- */
55
- export function isBooleanAttribute(name: string): boolean;
56
-
57
- export function isBooleanAttribute(value: string | Attr | Attribute): boolean {
58
- return isValidAttribute(
59
- attribute => attribute != null && booleanAttributes.includes(attribute.name.toLowerCase()),
60
- value,
89
+ export function isBooleanAttribute(first: unknown, decode: boolean): boolean {
90
+ return handleAttribute(
91
+ name => booleanAttributesSet.has(name?.toLowerCase() as string),
92
+ decode,
93
+ first,
61
94
  '',
62
95
  );
63
96
  }
64
97
 
65
- /**
66
- * Is the attribute empty and not a boolean attribute?
67
- * @param attribute Attribute to check
68
- * @returns `true` if attribute is empty and not a boolean attribute
69
- */
70
- export function isEmptyNonBooleanAttribute(attribute: Attr | Attribute): boolean;
71
-
72
- /**
73
- * Is the attribute empty and not a boolean attribute?
74
- * @param name Attribute name
75
- * @param value Attribute value
76
- * @returns `true` if attribute is empty and not a boolean attribute
77
- */
78
- export function isEmptyNonBooleanAttribute(name: string, value: string): boolean;
79
-
80
98
  export function isEmptyNonBooleanAttribute(
81
- first: string | Attr | Attribute,
82
- second?: string,
99
+ first: unknown,
100
+ second: unknown,
101
+ decode: boolean,
83
102
  ): boolean {
84
- return isValidAttribute(
85
- attribute =>
86
- attribute != null &&
87
- !booleanAttributes.includes(attribute.name) &&
88
- String(attribute.value).trim().length === 0,
103
+ return handleAttribute(
104
+ (name, value) =>
105
+ name != null && value != null && !booleanAttributesSet.has(name) && value.trim().length === 0,
106
+ decode,
89
107
  first,
90
108
  second,
91
109
  );
92
110
  }
93
111
 
94
- /**
95
- * Is the attribute an invalid boolean attribute?
96
- *
97
- * _(I.e., its value is not empty or the same as its name)_
98
- * @param attribute Attribute to check
99
- * @returns `true` if attribute is an invalid boolean attribute
100
- */
101
- export function isInvalidBooleanAttribute(attribute: Attr | Attribute): boolean;
102
-
103
- /**
104
- * Is the attribute an invalid boolean attribute?
105
- *
106
- * _(I.e., its value is not empty or the same as its name)_
107
- * @param name Attribute name
108
- * @param value Attribute value
109
- * @returns `true` if attribute is an invalid boolean attribute
110
- */
111
- export function isInvalidBooleanAttribute(name: string, value: string): boolean;
112
-
113
112
  export function isInvalidBooleanAttribute(
114
- first: string | Attr | Attribute,
115
- second?: string,
113
+ first: unknown,
114
+ second: unknown,
115
+ decode: boolean,
116
116
  ): boolean {
117
- return isValidAttribute(
118
- attribute => {
119
- if (attribute == null) {
120
- return true;
121
- }
122
-
123
- if (!booleanAttributes.includes(attribute.name)) {
124
- return false;
125
- }
126
-
127
- const normalized = String(attribute.value).toLowerCase().trim();
128
-
129
- return !(normalized.length === 0 || normalized === attribute.name);
130
- },
131
- first,
132
- second,
133
- );
117
+ return handleAttribute(booleanAttributeHandler, decode, first, second);
134
118
  }
135
119
 
136
120
  export function isProperty(value: unknown): value is Property {
137
121
  return isPlainObject(value) && typeof (value as PlainObject).name === 'string';
138
122
  }
139
123
 
140
- function isValidAttribute(
141
- callback: (attribute: Attr | Attribute | undefined) => boolean,
142
- first: string | Attr | Attribute,
143
- second?: string,
144
- ): boolean {
145
- let attribute: Attribute | undefined;
146
-
147
- if (isAttribute(first)) {
148
- attribute = first;
149
- } else if (typeof first === 'string' && typeof second === 'string') {
150
- attribute = {name: first, value: second};
151
- }
152
-
153
- return callback(attribute);
124
+ function isValidSourceAttribute(name: string, value: string): boolean {
125
+ return EXPRESSION_SOURCE_NAME.test(name) && EXPRESSION_SOURCE_VALUE.test(value);
154
126
  }
155
127
 
156
128
  function updateAttribute(element: HTMLOrSVGElement, name: string, value: unknown): void {
157
- const isBoolean = booleanAttributes.includes(name.toLowerCase());
129
+ const isBoolean = booleanAttributesSet.has(name.toLowerCase());
158
130
 
159
131
  if (isBoolean) {
160
132
  updateProperty(element, name, value);
@@ -211,11 +183,23 @@ export function updateValues(
211
183
 
212
184
  //
213
185
 
214
- const EXPRESSION_ON_PREFIX = /^on/i;
186
+ const EXPRESSION_CLOBBERED_NAME = /^(id|name)$/i;
187
+
188
+ const EXPRESSION_DATA_OR_SCRIPT = /^(?:data|\w+script):/i;
189
+
190
+ const EXPRESSION_EVENT_NAME = /^on/i;
191
+
192
+ const EXPRESSION_SKIP_NAME = /^(aria-[-\w]+|data-[-\w.\u00B7-\uFFFF]+)$/i;
193
+
194
+ const EXPRESSION_SOURCE_NAME = /^src$/i;
215
195
 
216
- const EXPRESSION_SOURCE_PREFIX = /^(href|src|xlink:href)$/i;
196
+ const EXPRESSION_SOURCE_VALUE = /^data:/i;
217
197
 
218
- const EXPRESSION_VALUE_PREFIX = /(data:text\/html|javascript:)/i;
198
+ const EXPRESSION_URI_VALUE =
199
+ /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
200
+
201
+ // oxlint-disable-next-line no-control-regex
202
+ const EXPRESSION_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
219
203
 
220
204
  /**
221
205
  * List of boolean attributes
@@ -246,3 +230,9 @@ export const booleanAttributes: readonly string[] = Object.freeze([
246
230
  'reversed',
247
231
  'selected',
248
232
  ]);
233
+
234
+ const booleanAttributesSet = new Set(booleanAttributes);
235
+
236
+ const formElement = document.createElement('form');
237
+
238
+ let textArea: HTMLTextAreaElement;
@@ -1,3 +1,59 @@
1
- export { booleanAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute, } from '../internal/attribute';
1
+ import type { Attribute } from '../models';
2
+ /**
3
+ * Is the attribute considered bad and potentially harmful?
4
+ * @param attribute Attribute to check
5
+ * @returns `true` if attribute is considered bad
6
+ */
7
+ export declare function isBadAttribute(attribute: Attr | Attribute): boolean;
8
+ /**
9
+ * Is the attribute considered bad and potentially harmful?
10
+ * @param name Attribute name
11
+ * @param value Attribute value
12
+ * @returns `true` if attribute is considered bad
13
+ */
14
+ export declare function isBadAttribute(name: string, value: string): boolean;
15
+ /**
16
+ * Is the attribute a boolean attribute?
17
+ * @param name Attribute to check
18
+ * @returns `true` if attribute is a boolean attribute
19
+ */
20
+ export declare function isBooleanAttribute(attribute: Attr | Attribute): boolean;
21
+ /**
22
+ * Is the attribute a boolean attribute?
23
+ * @param name Attribute name
24
+ * @returns `true` if attribute is a boolean attribute
25
+ */
26
+ export declare function isBooleanAttribute(name: string): boolean;
27
+ /**
28
+ * Is the attribute empty and not a boolean attribute?
29
+ * @param attribute Attribute to check
30
+ * @returns `true` if attribute is empty and not a boolean attribute
31
+ */
32
+ export declare function isEmptyNonBooleanAttribute(attribute: Attr | Attribute): boolean;
33
+ /**
34
+ * Is the attribute empty and not a boolean attribute?
35
+ * @param name Attribute name
36
+ * @param value Attribute value
37
+ * @returns `true` if attribute is empty and not a boolean attribute
38
+ */
39
+ export declare function isEmptyNonBooleanAttribute(name: string, value: string): boolean;
40
+ /**
41
+ * Is the attribute an invalid boolean attribute?
42
+ *
43
+ * _(I.e., its value is not empty or the same as its name)_
44
+ * @param attribute Attribute to check
45
+ * @returns `true` if attribute is an invalid boolean attribute
46
+ */
47
+ export declare function isInvalidBooleanAttribute(attribute: Attr | Attribute): boolean;
48
+ /**
49
+ * Is the attribute an invalid boolean attribute?
50
+ *
51
+ * _(I.e., its value is not empty or the same as its name)_
52
+ * @param name Attribute name
53
+ * @param value Attribute value
54
+ * @returns `true` if attribute is an invalid boolean attribute
55
+ */
56
+ export declare function isInvalidBooleanAttribute(name: string, value: string): boolean;
57
+ export { booleanAttributes } from '../internal/attribute';
2
58
  export * from './get';
3
59
  export * from './set';
@@ -25,9 +25,9 @@ type Html = {
25
25
  };
26
26
  type HtmlOptions = {
27
27
  /**
28
- * Ignore caching the template element for the HTML string? _(defaults to `false`)_
28
+ * Cache template element for the HTML string? _(defaults to `true`)_
29
29
  */
30
- ignoreCache?: boolean;
30
+ cache?: boolean;
31
31
  };
32
32
  declare const html: Html;
33
33
  /**
@@ -1,2 +1,2 @@
1
1
  export declare function sanitizeAttributes(element: Element, attributes: Attr[]): void;
2
- export declare function sanitizeNodes(nodes: Node[]): Node[];
2
+ export declare function sanitizeNodes(nodes: Node[], depth: number): Node[];
package/types/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import supportsTouch from './touch';
2
- export * from './attribute';
2
+ export { isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute, } from './attribute';
3
3
  export * from './data';
4
4
  export * from './event/index';
5
5
  export * from './find/index';
6
6
  export * from './focusable';
7
- export * from './html';
7
+ export * from './html/index';
8
8
  export * from './is';
9
9
  export * from './models';
10
10
  export * from './style';