@bquery/bquery 1.3.0 → 1.5.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/README.md +546 -501
- package/dist/component/component.d.ts.map +1 -1
- package/dist/component/index.d.ts +2 -0
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/library.d.ts +34 -0
- package/dist/component/library.d.ts.map +1 -0
- package/dist/component/types.d.ts +10 -6
- package/dist/component/types.d.ts.map +1 -1
- package/dist/component-CY5MVoYN.js +531 -0
- package/dist/component-CY5MVoYN.js.map +1 -0
- package/dist/component.es.mjs +6 -184
- package/dist/config-DRmZZno3.js +40 -0
- package/dist/config-DRmZZno3.js.map +1 -0
- package/dist/core/collection.d.ts +19 -3
- package/dist/core/collection.d.ts.map +1 -1
- package/dist/core/element.d.ts +23 -4
- package/dist/core/element.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/utils/function.d.ts +21 -4
- package/dist/core/utils/function.d.ts.map +1 -1
- package/dist/core-CK2Mfpf4.js +648 -0
- package/dist/core-CK2Mfpf4.js.map +1 -0
- package/dist/core-DPdbItcq.js +112 -0
- package/dist/core-DPdbItcq.js.map +1 -0
- package/dist/core.es.mjs +45 -1218
- package/dist/full.d.ts +6 -6
- package/dist/full.d.ts.map +1 -1
- package/dist/full.es.mjs +98 -92
- package/dist/full.iife.js +173 -3
- package/dist/full.iife.js.map +1 -1
- package/dist/full.umd.js +173 -3
- package/dist/full.umd.js.map +1 -1
- package/dist/index.es.mjs +143 -139
- package/dist/motion/transition.d.ts +1 -1
- package/dist/motion/transition.d.ts.map +1 -1
- package/dist/motion/types.d.ts +11 -1
- package/dist/motion/types.d.ts.map +1 -1
- package/dist/motion-C5DRdPnO.js +415 -0
- package/dist/motion-C5DRdPnO.js.map +1 -0
- package/dist/motion.es.mjs +25 -361
- package/dist/object-qGpWr6-J.js +38 -0
- package/dist/object-qGpWr6-J.js.map +1 -0
- package/dist/platform/announcer.d.ts +59 -0
- package/dist/platform/announcer.d.ts.map +1 -0
- package/dist/platform/config.d.ts +92 -0
- package/dist/platform/config.d.ts.map +1 -0
- package/dist/platform/cookies.d.ts +45 -0
- package/dist/platform/cookies.d.ts.map +1 -0
- package/dist/platform/index.d.ts +8 -0
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/meta.d.ts +62 -0
- package/dist/platform/meta.d.ts.map +1 -0
- package/dist/platform/storage.d.ts.map +1 -1
- package/dist/platform-B7JhGBc7.js +361 -0
- package/dist/platform-B7JhGBc7.js.map +1 -0
- package/dist/platform.es.mjs +11 -243
- package/dist/reactive/async-data.d.ts +114 -0
- package/dist/reactive/async-data.d.ts.map +1 -0
- package/dist/reactive/core.d.ts +12 -0
- package/dist/reactive/core.d.ts.map +1 -1
- package/dist/reactive/effect.d.ts.map +1 -1
- package/dist/reactive/index.d.ts +2 -2
- package/dist/reactive/index.d.ts.map +1 -1
- package/dist/reactive/internals.d.ts +6 -0
- package/dist/reactive/internals.d.ts.map +1 -1
- package/dist/reactive/signal.d.ts +2 -0
- package/dist/reactive/signal.d.ts.map +1 -1
- package/dist/reactive-BDya-ia8.js +253 -0
- package/dist/reactive-BDya-ia8.js.map +1 -0
- package/dist/reactive.es.mjs +18 -34
- package/dist/router-CijiICxt.js +188 -0
- package/dist/router-CijiICxt.js.map +1 -0
- package/dist/router.es.mjs +11 -200
- package/dist/sanitize-jyJ2ryE2.js +302 -0
- package/dist/sanitize-jyJ2ryE2.js.map +1 -0
- package/dist/security/constants.d.ts.map +1 -1
- package/dist/security/sanitize-core.d.ts.map +1 -1
- package/dist/security.es.mjs +10 -56
- package/dist/store-CPK9E62U.js +262 -0
- package/dist/store-CPK9E62U.js.map +1 -0
- package/dist/store.es.mjs +12 -25
- package/dist/view/evaluate.d.ts.map +1 -1
- package/dist/view-Cdi0g-qo.js +396 -0
- package/dist/view-Cdi0g-qo.js.map +1 -0
- package/dist/view.es.mjs +10 -424
- package/package.json +136 -132
- package/src/component/component.ts +319 -289
- package/src/component/index.ts +42 -40
- package/src/component/library.ts +504 -0
- package/src/component/types.ts +91 -85
- package/src/core/collection.ts +44 -4
- package/src/core/element.ts +33 -5
- package/src/core/index.ts +1 -0
- package/src/core/utils/function.ts +56 -15
- package/src/full.ts +223 -187
- package/src/motion/transition.ts +97 -51
- package/src/motion/types.ts +208 -198
- package/src/platform/announcer.ts +208 -0
- package/src/platform/config.ts +163 -0
- package/src/platform/cookies.ts +165 -0
- package/src/platform/index.ts +39 -18
- package/src/platform/meta.ts +168 -0
- package/src/platform/storage.ts +8 -1
- package/src/reactive/async-data.ts +486 -0
- package/src/reactive/core.ts +21 -0
- package/src/reactive/effect.ts +18 -7
- package/src/reactive/index.ts +37 -23
- package/src/reactive/internals.ts +18 -1
- package/src/reactive/signal.ts +29 -20
- package/src/security/constants.ts +211 -209
- package/src/security/sanitize-core.ts +22 -1
- package/src/view/evaluate.ts +29 -13
- package/dist/batch-4LAvfLE7.js +0 -13
- package/dist/batch-4LAvfLE7.js.map +0 -1
- package/dist/component.es.mjs.map +0 -1
- package/dist/core-COenAZjD.js +0 -145
- package/dist/core-COenAZjD.js.map +0 -1
- package/dist/core.es.mjs.map +0 -1
- package/dist/full.es.mjs.map +0 -1
- package/dist/index.es.mjs.map +0 -1
- package/dist/motion.es.mjs.map +0 -1
- package/dist/persisted-Dz_ryNuC.js +0 -278
- package/dist/persisted-Dz_ryNuC.js.map +0 -1
- package/dist/platform.es.mjs.map +0 -1
- package/dist/reactive.es.mjs.map +0 -1
- package/dist/router.es.mjs.map +0 -1
- package/dist/sanitize-1FBEPAFH.js +0 -272
- package/dist/sanitize-1FBEPAFH.js.map +0 -1
- package/dist/security.es.mjs.map +0 -1
- package/dist/store.es.mjs.map +0 -1
- package/dist/type-guards-DRma3-Kc.js +0 -16
- package/dist/type-guards-DRma3-Kc.js.map +0 -1
- package/dist/untrack-BuEQKH7_.js +0 -6
- package/dist/untrack-BuEQKH7_.js.map +0 -1
- package/dist/view.es.mjs.map +0 -1
- package/dist/watch-CXyaBC_9.js +0 -58
- package/dist/watch-CXyaBC_9.js.map +0 -1
package/src/reactive/signal.ts
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reactive primitives inspired by fine-grained reactivity.
|
|
3
|
-
*
|
|
4
|
-
* @module bquery/reactive
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export { batch } from './batch';
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
16
|
-
export {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export type {
|
|
20
|
-
export type {
|
|
1
|
+
/**
|
|
2
|
+
* Reactive primitives inspired by fine-grained reactivity.
|
|
3
|
+
*
|
|
4
|
+
* @module bquery/reactive
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { batch } from './batch';
|
|
8
|
+
export { createUseFetch, useAsyncData, useFetch } from './async-data';
|
|
9
|
+
export { Computed, computed } from './computed';
|
|
10
|
+
export { Signal, signal } from './core';
|
|
11
|
+
export { effect } from './effect';
|
|
12
|
+
export { linkedSignal } from './linked';
|
|
13
|
+
export { persistedSignal } from './persisted';
|
|
14
|
+
export { readonly } from './readonly';
|
|
15
|
+
export { isComputed, isSignal } from './type-guards';
|
|
16
|
+
export { untrack } from './untrack';
|
|
17
|
+
export { watch } from './watch';
|
|
18
|
+
|
|
19
|
+
export type { CleanupFn, Observer } from './internals';
|
|
20
|
+
export type {
|
|
21
|
+
AsyncDataState,
|
|
22
|
+
AsyncDataStatus,
|
|
23
|
+
AsyncWatchSource,
|
|
24
|
+
FetchInput,
|
|
25
|
+
UseAsyncDataOptions,
|
|
26
|
+
UseFetchOptions,
|
|
27
|
+
} from './async-data';
|
|
28
|
+
export type { LinkedSignal } from './linked';
|
|
29
|
+
export type { ReadonlySignal } from './readonly';
|
|
@@ -1,209 +1,211 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security constants and safe lists.
|
|
3
|
-
*
|
|
4
|
-
* @module bquery/security
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Trusted Types policy name.
|
|
9
|
-
*/
|
|
10
|
-
export const POLICY_NAME = 'bquery-sanitizer';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Default allowed HTML tags considered safe.
|
|
14
|
-
*/
|
|
15
|
-
export const DEFAULT_ALLOWED_TAGS = new Set([
|
|
16
|
-
'a',
|
|
17
|
-
'abbr',
|
|
18
|
-
'address',
|
|
19
|
-
'article',
|
|
20
|
-
'aside',
|
|
21
|
-
'b',
|
|
22
|
-
'bdi',
|
|
23
|
-
'bdo',
|
|
24
|
-
'blockquote',
|
|
25
|
-
'br',
|
|
26
|
-
'button',
|
|
27
|
-
'caption',
|
|
28
|
-
'cite',
|
|
29
|
-
'code',
|
|
30
|
-
'col',
|
|
31
|
-
'colgroup',
|
|
32
|
-
'data',
|
|
33
|
-
'dd',
|
|
34
|
-
'del',
|
|
35
|
-
'details',
|
|
36
|
-
'dfn',
|
|
37
|
-
'div',
|
|
38
|
-
'dl',
|
|
39
|
-
'dt',
|
|
40
|
-
'em',
|
|
41
|
-
'figcaption',
|
|
42
|
-
'figure',
|
|
43
|
-
'footer',
|
|
44
|
-
'form',
|
|
45
|
-
'h1',
|
|
46
|
-
'h2',
|
|
47
|
-
'h3',
|
|
48
|
-
'h4',
|
|
49
|
-
'h5',
|
|
50
|
-
'h6',
|
|
51
|
-
'header',
|
|
52
|
-
'hgroup',
|
|
53
|
-
'hr',
|
|
54
|
-
'i',
|
|
55
|
-
'img',
|
|
56
|
-
'input',
|
|
57
|
-
'ins',
|
|
58
|
-
'kbd',
|
|
59
|
-
'label',
|
|
60
|
-
'legend',
|
|
61
|
-
'li',
|
|
62
|
-
'main',
|
|
63
|
-
'mark',
|
|
64
|
-
'nav',
|
|
65
|
-
'ol',
|
|
66
|
-
'optgroup',
|
|
67
|
-
'option',
|
|
68
|
-
'p',
|
|
69
|
-
'picture',
|
|
70
|
-
'pre',
|
|
71
|
-
'progress',
|
|
72
|
-
'q',
|
|
73
|
-
'rp',
|
|
74
|
-
'rt',
|
|
75
|
-
'ruby',
|
|
76
|
-
's',
|
|
77
|
-
'samp',
|
|
78
|
-
'section',
|
|
79
|
-
'select',
|
|
80
|
-
'small',
|
|
81
|
-
'source',
|
|
82
|
-
'span',
|
|
83
|
-
'strong',
|
|
84
|
-
'sub',
|
|
85
|
-
'summary',
|
|
86
|
-
'sup',
|
|
87
|
-
'table',
|
|
88
|
-
'tbody',
|
|
89
|
-
'td',
|
|
90
|
-
'textarea',
|
|
91
|
-
'tfoot',
|
|
92
|
-
'th',
|
|
93
|
-
'thead',
|
|
94
|
-
'time',
|
|
95
|
-
'tr',
|
|
96
|
-
'u',
|
|
97
|
-
'ul',
|
|
98
|
-
'var',
|
|
99
|
-
'wbr',
|
|
100
|
-
]);
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Explicitly dangerous tags that should never be allowed.
|
|
104
|
-
* These are checked even if somehow added to allowTags.
|
|
105
|
-
*/
|
|
106
|
-
export const DANGEROUS_TAGS = new Set([
|
|
107
|
-
'script',
|
|
108
|
-
'iframe',
|
|
109
|
-
'frame',
|
|
110
|
-
'frameset',
|
|
111
|
-
'object',
|
|
112
|
-
'embed',
|
|
113
|
-
'applet',
|
|
114
|
-
'link',
|
|
115
|
-
'meta',
|
|
116
|
-
'style',
|
|
117
|
-
'base',
|
|
118
|
-
'template',
|
|
119
|
-
'slot'
|
|
120
|
-
'
|
|
121
|
-
|
|
122
|
-
'
|
|
123
|
-
'
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
'
|
|
135
|
-
'
|
|
136
|
-
'
|
|
137
|
-
'
|
|
138
|
-
'
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
'
|
|
142
|
-
|
|
143
|
-
'
|
|
144
|
-
|
|
145
|
-
'
|
|
146
|
-
'
|
|
147
|
-
'
|
|
148
|
-
|
|
149
|
-
'
|
|
150
|
-
|
|
151
|
-
'
|
|
152
|
-
'
|
|
153
|
-
'
|
|
154
|
-
'
|
|
155
|
-
'
|
|
156
|
-
'
|
|
157
|
-
'
|
|
158
|
-
|
|
159
|
-
'
|
|
160
|
-
|
|
161
|
-
'
|
|
162
|
-
'
|
|
163
|
-
|
|
164
|
-
'
|
|
165
|
-
|
|
166
|
-
'
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* -
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
'
|
|
182
|
-
'
|
|
183
|
-
'
|
|
184
|
-
'
|
|
185
|
-
'
|
|
186
|
-
'
|
|
187
|
-
'
|
|
188
|
-
'
|
|
189
|
-
'
|
|
190
|
-
'
|
|
191
|
-
'
|
|
192
|
-
'
|
|
193
|
-
'
|
|
194
|
-
'
|
|
195
|
-
'
|
|
196
|
-
'
|
|
197
|
-
'
|
|
198
|
-
'
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Security constants and safe lists.
|
|
3
|
+
*
|
|
4
|
+
* @module bquery/security
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Trusted Types policy name.
|
|
9
|
+
*/
|
|
10
|
+
export const POLICY_NAME = 'bquery-sanitizer';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Default allowed HTML tags considered safe.
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_ALLOWED_TAGS = new Set([
|
|
16
|
+
'a',
|
|
17
|
+
'abbr',
|
|
18
|
+
'address',
|
|
19
|
+
'article',
|
|
20
|
+
'aside',
|
|
21
|
+
'b',
|
|
22
|
+
'bdi',
|
|
23
|
+
'bdo',
|
|
24
|
+
'blockquote',
|
|
25
|
+
'br',
|
|
26
|
+
'button',
|
|
27
|
+
'caption',
|
|
28
|
+
'cite',
|
|
29
|
+
'code',
|
|
30
|
+
'col',
|
|
31
|
+
'colgroup',
|
|
32
|
+
'data',
|
|
33
|
+
'dd',
|
|
34
|
+
'del',
|
|
35
|
+
'details',
|
|
36
|
+
'dfn',
|
|
37
|
+
'div',
|
|
38
|
+
'dl',
|
|
39
|
+
'dt',
|
|
40
|
+
'em',
|
|
41
|
+
'figcaption',
|
|
42
|
+
'figure',
|
|
43
|
+
'footer',
|
|
44
|
+
'form',
|
|
45
|
+
'h1',
|
|
46
|
+
'h2',
|
|
47
|
+
'h3',
|
|
48
|
+
'h4',
|
|
49
|
+
'h5',
|
|
50
|
+
'h6',
|
|
51
|
+
'header',
|
|
52
|
+
'hgroup',
|
|
53
|
+
'hr',
|
|
54
|
+
'i',
|
|
55
|
+
'img',
|
|
56
|
+
'input',
|
|
57
|
+
'ins',
|
|
58
|
+
'kbd',
|
|
59
|
+
'label',
|
|
60
|
+
'legend',
|
|
61
|
+
'li',
|
|
62
|
+
'main',
|
|
63
|
+
'mark',
|
|
64
|
+
'nav',
|
|
65
|
+
'ol',
|
|
66
|
+
'optgroup',
|
|
67
|
+
'option',
|
|
68
|
+
'p',
|
|
69
|
+
'picture',
|
|
70
|
+
'pre',
|
|
71
|
+
'progress',
|
|
72
|
+
'q',
|
|
73
|
+
'rp',
|
|
74
|
+
'rt',
|
|
75
|
+
'ruby',
|
|
76
|
+
's',
|
|
77
|
+
'samp',
|
|
78
|
+
'section',
|
|
79
|
+
'select',
|
|
80
|
+
'small',
|
|
81
|
+
'source',
|
|
82
|
+
'span',
|
|
83
|
+
'strong',
|
|
84
|
+
'sub',
|
|
85
|
+
'summary',
|
|
86
|
+
'sup',
|
|
87
|
+
'table',
|
|
88
|
+
'tbody',
|
|
89
|
+
'td',
|
|
90
|
+
'textarea',
|
|
91
|
+
'tfoot',
|
|
92
|
+
'th',
|
|
93
|
+
'thead',
|
|
94
|
+
'time',
|
|
95
|
+
'tr',
|
|
96
|
+
'u',
|
|
97
|
+
'ul',
|
|
98
|
+
'var',
|
|
99
|
+
'wbr',
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Explicitly dangerous tags that should never be allowed.
|
|
104
|
+
* These are checked even if somehow added to allowTags.
|
|
105
|
+
*/
|
|
106
|
+
export const DANGEROUS_TAGS = new Set([
|
|
107
|
+
'script',
|
|
108
|
+
'iframe',
|
|
109
|
+
'frame',
|
|
110
|
+
'frameset',
|
|
111
|
+
'object',
|
|
112
|
+
'embed',
|
|
113
|
+
'applet',
|
|
114
|
+
'link',
|
|
115
|
+
'meta',
|
|
116
|
+
'style',
|
|
117
|
+
'base',
|
|
118
|
+
'template',
|
|
119
|
+
// 'slot' is intentionally excluded here so component shadow markup can opt in
|
|
120
|
+
// via sanitizeHtml(..., { allowTags: ['slot'] }). It remains disallowed by default
|
|
121
|
+
// for general HTML writes, because DEFAULT_ALLOWED_TAGS does not include it.
|
|
122
|
+
'math',
|
|
123
|
+
'svg',
|
|
124
|
+
'foreignobject',
|
|
125
|
+
'noscript',
|
|
126
|
+
]);
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Reserved IDs that could cause DOM clobbering attacks.
|
|
130
|
+
* These are prevented to avoid overwriting global browser objects.
|
|
131
|
+
*/
|
|
132
|
+
export const RESERVED_IDS = new Set([
|
|
133
|
+
// Global objects
|
|
134
|
+
'document',
|
|
135
|
+
'window',
|
|
136
|
+
'location',
|
|
137
|
+
'top',
|
|
138
|
+
'self',
|
|
139
|
+
'parent',
|
|
140
|
+
'frames',
|
|
141
|
+
'history',
|
|
142
|
+
'navigator',
|
|
143
|
+
'screen',
|
|
144
|
+
// Dangerous functions
|
|
145
|
+
'alert',
|
|
146
|
+
'confirm',
|
|
147
|
+
'prompt',
|
|
148
|
+
'eval',
|
|
149
|
+
'function',
|
|
150
|
+
// Document properties
|
|
151
|
+
'cookie',
|
|
152
|
+
'domain',
|
|
153
|
+
'referrer',
|
|
154
|
+
'body',
|
|
155
|
+
'head',
|
|
156
|
+
'forms',
|
|
157
|
+
'images',
|
|
158
|
+
'links',
|
|
159
|
+
'scripts',
|
|
160
|
+
// DOM traversal properties
|
|
161
|
+
'children',
|
|
162
|
+
'parentnode',
|
|
163
|
+
'firstchild',
|
|
164
|
+
'lastchild',
|
|
165
|
+
// Content manipulation
|
|
166
|
+
'innerhtml',
|
|
167
|
+
'outerhtml',
|
|
168
|
+
'textcontent',
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Default allowed attributes considered safe.
|
|
173
|
+
* Note: 'style' is excluded by default because inline CSS can be abused for:
|
|
174
|
+
* - UI redressing attacks
|
|
175
|
+
* - Data exfiltration via url() in CSS
|
|
176
|
+
* - CSS injection vectors
|
|
177
|
+
* If you need to allow inline styles, add 'style' to allowAttributes in your
|
|
178
|
+
* sanitizeHtml options, but ensure you implement proper CSS value validation.
|
|
179
|
+
*/
|
|
180
|
+
export const DEFAULT_ALLOWED_ATTRIBUTES = new Set([
|
|
181
|
+
'alt',
|
|
182
|
+
'class',
|
|
183
|
+
'dir',
|
|
184
|
+
'height',
|
|
185
|
+
'hidden',
|
|
186
|
+
'href',
|
|
187
|
+
'id',
|
|
188
|
+
'lang',
|
|
189
|
+
'loading',
|
|
190
|
+
'name',
|
|
191
|
+
'rel',
|
|
192
|
+
'role',
|
|
193
|
+
'src',
|
|
194
|
+
'srcset',
|
|
195
|
+
'tabindex',
|
|
196
|
+
'target',
|
|
197
|
+
'title',
|
|
198
|
+
'type',
|
|
199
|
+
'width',
|
|
200
|
+
'aria-*',
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Dangerous attribute prefixes to always remove.
|
|
205
|
+
*/
|
|
206
|
+
export const DANGEROUS_ATTR_PREFIXES = ['on', 'formaction', 'xlink:', 'xmlns:'];
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Dangerous URL protocols to block.
|
|
210
|
+
*/
|
|
211
|
+
export const DANGEROUS_PROTOCOLS = ['javascript:', 'data:', 'vbscript:', 'file:'];
|
|
@@ -80,6 +80,21 @@ const isSafeUrl = (value: string): boolean => {
|
|
|
80
80
|
return true;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Check if a srcset attribute value is safe.
|
|
85
|
+
* srcset contains comma-separated entries of "url [descriptor]".
|
|
86
|
+
* Each individual URL must be validated.
|
|
87
|
+
* @internal
|
|
88
|
+
*/
|
|
89
|
+
const isSafeSrcset = (value: string): boolean => {
|
|
90
|
+
const entries = value.split(',');
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
const url = entry.trim().split(/\s+/)[0];
|
|
93
|
+
if (url && !isSafeUrl(url)) return false;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
};
|
|
97
|
+
|
|
83
98
|
/**
|
|
84
99
|
* Check if a URL is external (different origin).
|
|
85
100
|
* @internal
|
|
@@ -275,10 +290,16 @@ export const sanitizeHtmlCore = (html: string, options: SanitizeOptions = {}): s
|
|
|
275
290
|
|
|
276
291
|
// Validate URL attributes
|
|
277
292
|
if (
|
|
278
|
-
(attrName === 'href' || attrName === 'src' || attrName === '
|
|
293
|
+
(attrName === 'href' || attrName === 'src' || attrName === 'action') &&
|
|
279
294
|
!isSafeUrl(attr.value)
|
|
280
295
|
) {
|
|
281
296
|
attrsToRemove.push(attr.name);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Validate srcset URLs individually
|
|
301
|
+
if (attrName === 'srcset' && !isSafeSrcset(attr.value)) {
|
|
302
|
+
attrsToRemove.push(attr.name);
|
|
282
303
|
}
|
|
283
304
|
}
|
|
284
305
|
|
package/src/view/evaluate.ts
CHANGED
|
@@ -188,14 +188,23 @@ export const parseObjectExpression = (expression: string): Record<string, string
|
|
|
188
188
|
|
|
189
189
|
for (let i = 0; i < inner.length; i++) {
|
|
190
190
|
const char = inner[i];
|
|
191
|
-
const prevChar = i > 0 ? inner[i - 1] : '';
|
|
192
191
|
|
|
193
|
-
// Handle string literals
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
192
|
+
// Handle string literals: count consecutive backslashes before a quote
|
|
193
|
+
// to correctly distinguish escaped quotes from end-of-string
|
|
194
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
195
|
+
let backslashCount = 0;
|
|
196
|
+
let j = i - 1;
|
|
197
|
+
while (j >= 0 && inner[j] === '\\') {
|
|
198
|
+
backslashCount++;
|
|
199
|
+
j--;
|
|
200
|
+
}
|
|
201
|
+
// Quote is escaped only if preceded by an odd number of backslashes
|
|
202
|
+
if (backslashCount % 2 === 0) {
|
|
203
|
+
if (inString === null) {
|
|
204
|
+
inString = char;
|
|
205
|
+
} else if (inString === char) {
|
|
206
|
+
inString = null;
|
|
207
|
+
}
|
|
199
208
|
}
|
|
200
209
|
current += char;
|
|
201
210
|
continue;
|
|
@@ -237,13 +246,20 @@ export const parseObjectExpression = (expression: string): Record<string, string
|
|
|
237
246
|
|
|
238
247
|
for (let i = 0; i < part.length; i++) {
|
|
239
248
|
const char = part[i];
|
|
240
|
-
const prevChar = i > 0 ? part[i - 1] : '';
|
|
241
249
|
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
250
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
251
|
+
let backslashCount = 0;
|
|
252
|
+
let j = i - 1;
|
|
253
|
+
while (j >= 0 && part[j] === '\\') {
|
|
254
|
+
backslashCount++;
|
|
255
|
+
j--;
|
|
256
|
+
}
|
|
257
|
+
if (backslashCount % 2 === 0) {
|
|
258
|
+
if (partInString === null) {
|
|
259
|
+
partInString = char;
|
|
260
|
+
} else if (partInString === char) {
|
|
261
|
+
partInString = null;
|
|
262
|
+
}
|
|
247
263
|
}
|
|
248
264
|
continue;
|
|
249
265
|
}
|
package/dist/batch-4LAvfLE7.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"batch-4LAvfLE7.js","sources":["../src/reactive/batch.ts"],"sourcesContent":["/**\n * Batched reactive updates.\n */\n\nimport { beginBatch, endBatch } from './internals';\n\n/**\n * Batches multiple signal updates into a single notification cycle.\n *\n * Updates made inside the batch function are deferred until the batch\n * completes, preventing intermediate re-renders and improving performance.\n *\n * @param fn - Function containing multiple signal updates\n */\nexport const batch = (fn: () => void): void => {\n beginBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n};\n"],"names":["batch","fn","beginBatch","endBatch"],"mappings":";AAcO,MAAMA,IAAQ,CAACC,MAAyB;AAC7C,EAAAC,EAAA;AACA,MAAI;AACF,IAAAD,EAAA;AAAA,EACF,UAAA;AACE,IAAAE,EAAA;AAAA,EACF;AACF;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"component.es.mjs","sources":["../src/component/props.ts","../src/component/component.ts","../src/component/html.ts"],"sourcesContent":["/**\n * Prop coercion utilities.\n *\n * @module bquery/component\n */\n\nimport type { PropDefinition } from './types';\n\n/**\n * Coerces a string attribute value into a typed prop value.\n * Supports String, Number, Boolean, Object, Array, and custom converters.\n *\n * @internal\n * @template T - The target type\n * @param rawValue - The raw string value from the attribute\n * @param config - The prop definition with type information\n * @returns The coerced value of type T\n */\nexport const coercePropValue = <T>(rawValue: string, config: PropDefinition<T>): T => {\n const { type } = config;\n\n if (type === String) return rawValue as T;\n\n if (type === Number) {\n return Number(rawValue) as T;\n }\n\n if (type === Boolean) {\n const normalized = rawValue.trim().toLowerCase();\n if (normalized === '' || normalized === 'true' || normalized === '1') {\n return true as T;\n }\n if (normalized === 'false' || normalized === '0') {\n return false as T;\n }\n return Boolean(rawValue) as T;\n }\n\n if (type === Object || type === Array) {\n try {\n return JSON.parse(rawValue) as T;\n } catch {\n return rawValue as T;\n }\n }\n\n if (typeof type === 'function') {\n const callable = type as (value: unknown) => T;\n const constructable = type as new (value: unknown) => T;\n\n // Explicit construct mode takes precedence\n if (config.construct === true) {\n return Reflect.construct(constructable, [rawValue]) as T;\n }\n if (config.construct === false) {\n return callable(rawValue);\n }\n\n // Auto-detect: Check if type is constructable\n // A function is considered constructable if:\n // 1. It has a prototype with properties beyond just constructor, OR\n // 2. Its prototype.constructor is not itself (inherited), OR\n // 3. It's a class (toString starts with \"class\")\n const hasPrototype = type.prototype !== undefined && type.prototype !== null;\n const prototypeProps = hasPrototype ? Object.getOwnPropertyNames(type.prototype) : [];\n const hasPrototypeMethods = prototypeProps.length > 1;\n const hasInheritedConstructor = hasPrototype && type.prototype.constructor !== type;\n const isClassSyntax = /^class\\s/.test(Function.prototype.toString.call(type));\n\n const isConstructable = hasPrototypeMethods || hasInheritedConstructor || isClassSyntax;\n\n // For constructable types (e.g. Date, custom classes), prefer `new` to avoid\n // silent wrong-type returns (Date() returns string, new Date() returns Date)\n if (isConstructable) {\n try {\n return Reflect.construct(constructable, [rawValue]) as T;\n } catch {\n // Fall back to calling as function if construction fails\n return callable(rawValue);\n }\n }\n\n // For non-constructable types (arrow functions, plain functions), call directly\n // but fall back to constructor if result is undefined (common for function constructors)\n try {\n const result = callable(rawValue);\n\n // If calling without `new` returned undefined and the function has a prototype,\n // it's likely a function constructor that should be called with `new`\n if (result === undefined && hasPrototype) {\n try {\n return Reflect.construct(constructable, [rawValue]) as T;\n } catch {\n // Construction also failed, return the undefined\n return result as T;\n }\n }\n\n return result as T;\n } catch (error) {\n // Fall back to constructor if error indicates 'new' is required\n const isNewRequired =\n error instanceof TypeError &&\n /cannot be invoked without 'new'|is not a function/i.test(error.message);\n\n if (isNewRequired) {\n return Reflect.construct(constructable, [rawValue]) as T;\n }\n\n // Rethrow original error for non-constructable converters\n throw error;\n }\n }\n\n return rawValue as T;\n};\n","/**\n * Web Component factory and registry.\n *\n * @module bquery/component\n */\n\nimport { sanitizeHtml } from '../security/sanitize';\nimport { coercePropValue } from './props';\nimport type { ComponentDefinition, PropDefinition } from './types';\n\n/**\n * Creates a custom element class for a component definition.\n *\n * This is useful when you want to extend or register the class manually\n * (e.g. with different tag names in tests or custom registries).\n *\n * @template TProps - Type of the component's props\n * @param tagName - The custom element tag name (used for diagnostics)\n * @param definition - The component configuration\n */\nexport const defineComponent = <TProps extends Record<string, unknown>>(\n tagName: string,\n definition: ComponentDefinition<TProps>\n): typeof HTMLElement => {\n class BQueryComponent extends HTMLElement {\n /** Internal state object for the component */\n private readonly state = { ...(definition.state ?? {}) };\n /** Typed props object populated from attributes */\n private props = {} as TProps;\n /** Tracks missing required props for validation during connectedCallback */\n private missingRequiredProps = new Set<string>();\n /** Tracks whether the component has completed its initial mount */\n private hasMounted = false;\n\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n this.syncProps();\n }\n\n /**\n * Returns the list of attributes to observe for changes.\n */\n static get observedAttributes(): string[] {\n return Object.keys(definition.props ?? {});\n }\n\n /**\n * Called when the element is added to the DOM.\n */\n connectedCallback(): void {\n try {\n // Defer initial render until all required props are present\n // This allows attributes to be set after element creation\n if (this.missingRequiredProps.size > 0) {\n // Component will mount once all required props are satisfied\n // via attributeChangedCallback\n return;\n }\n this.mount();\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n\n /**\n * Performs the initial mount of the component.\n * Called when the element is connected and all required props are present.\n * @internal\n */\n private mount(): void {\n if (this.hasMounted) return;\n definition.beforeMount?.call(this);\n definition.connected?.call(this);\n this.render();\n this.hasMounted = true;\n }\n\n /**\n * Called when the element is removed from the DOM.\n */\n disconnectedCallback(): void {\n try {\n definition.disconnected?.call(this);\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n\n /**\n * Called when an observed attribute changes.\n */\n attributeChangedCallback(\n _name: string,\n _oldValue: string | null,\n _newValue: string | null\n ): void {\n try {\n this.syncProps();\n\n if (this.hasMounted) {\n // Component already mounted - trigger update render\n this.render(true);\n } else if (this.isConnected && this.missingRequiredProps.size === 0) {\n // All required props are now satisfied and element is connected\n // Trigger the deferred initial mount\n this.mount();\n }\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n\n /**\n * Handles errors during component lifecycle.\n * @internal\n */\n private handleError(error: Error): void {\n if (definition.onError) {\n definition.onError.call(this, error);\n } else {\n console.error(`bQuery component error in <${tagName}>:`, error);\n }\n }\n\n /**\n * Updates a state property and triggers a re-render.\n *\n * @param key - The state property key\n * @param value - The new value\n */\n setState(key: string, value: unknown): void {\n this.state[key] = value;\n this.render(true);\n }\n\n /**\n * Gets a state property value.\n *\n * @param key - The state property key\n * @returns The current value\n */\n getState<T = unknown>(key: string): T {\n return this.state[key] as T;\n }\n\n /**\n * Synchronizes props from attributes.\n * @internal\n */\n private syncProps(): void {\n const props = definition.props ?? {};\n for (const [key, config] of Object.entries(props) as [string, PropDefinition][]) {\n const attrValue = this.getAttribute(key);\n let value: unknown;\n\n if (attrValue == null) {\n if (config.required && config.default === undefined) {\n // Mark as missing instead of throwing - validate during connectedCallback\n this.missingRequiredProps.add(key);\n value = undefined;\n } else {\n value = config.default ?? undefined;\n }\n } else {\n // Attribute is present, remove from missing set if it was there\n if (this.missingRequiredProps.has(key)) {\n this.missingRequiredProps.delete(key);\n }\n value = coercePropValue(attrValue, config);\n }\n\n if (config.validator && value !== undefined) {\n const isValid = config.validator(value);\n if (!isValid) {\n throw new Error(\n `bQuery component: validation failed for prop \"${key}\" with value ${JSON.stringify(value)}`\n );\n }\n }\n\n (this.props as Record<string, unknown>)[key] = value;\n }\n }\n\n /**\n * Renders the component to its shadow root.\n * @internal\n */\n private render(triggerUpdated = false): void {\n try {\n if (triggerUpdated && definition.beforeUpdate) {\n const shouldUpdate = definition.beforeUpdate.call(this, this.props);\n if (shouldUpdate === false) return;\n }\n\n const emit = (event: string, detail?: unknown): void => {\n this.dispatchEvent(new CustomEvent(event, { detail, bubbles: true, composed: true }));\n };\n\n if (!this.shadowRoot) return;\n\n const markup = definition.render({\n props: this.props,\n state: this.state,\n emit,\n });\n\n const sanitizedMarkup = sanitizeHtml(markup);\n this.shadowRoot.innerHTML = sanitizedMarkup;\n\n if (definition.styles) {\n const styleElement = document.createElement('style');\n styleElement.textContent = definition.styles;\n this.shadowRoot.prepend(styleElement);\n }\n\n if (triggerUpdated) {\n definition.updated?.call(this);\n }\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n }\n\n return BQueryComponent;\n};\n\n/**\n * Defines and registers a custom Web Component.\n *\n * This function creates a new custom element with the given tag name\n * and configuration. The component uses Shadow DOM for encapsulation\n * and automatically re-renders when observed attributes change.\n *\n * @template TProps - Type of the component's props\n * @param tagName - The custom element tag name (must contain a hyphen)\n * @param definition - The component configuration\n *\n * @example\n * ```ts\n * component('counter-button', {\n * props: {\n * start: { type: Number, default: 0 },\n * },\n * state: { count: 0 },\n * styles: `\n * button { padding: 0.5rem 1rem; }\n * `,\n * connected() {\n * // Use event delegation on shadow root so handler survives re-renders\n * const handleClick = (event: Event) => {\n * const target = event.target as HTMLElement | null;\n * if (target?.matches('button')) {\n * this.setState('count', (this.getState('count') as number) + 1);\n * }\n * };\n * this.shadowRoot?.addEventListener('click', handleClick);\n * // Store handler for cleanup\n * (this as any)._handleClick = handleClick;\n * },\n * disconnected() {\n * // Clean up event listener to prevent memory leaks\n * const handleClick = (this as any)._handleClick;\n * if (handleClick) {\n * this.shadowRoot?.removeEventListener('click', handleClick);\n * }\n * },\n * render({ props, state }) {\n * return html`\n * <button>\n * Count: ${state.count}\n * </button>\n * `;\n * },\n * });\n * ```\n */\nexport const component = <TProps extends Record<string, unknown>>(\n tagName: string,\n definition: ComponentDefinition<TProps>\n): void => {\n const elementClass = defineComponent(tagName, definition);\n\n if (!customElements.get(tagName)) {\n customElements.define(tagName, elementClass);\n }\n};\n","/**\n * Tagged template literal for creating HTML strings.\n *\n * This function handles interpolation of values into HTML templates,\n * converting null/undefined to empty strings.\n *\n * @param strings - Template literal string parts\n * @param values - Interpolated values\n * @returns Combined HTML string\n *\n * @example\n * ```ts\n * const name = 'World';\n * const greeting = html`<h1>Hello, ${name}!</h1>`;\n * // Result: '<h1>Hello, World!</h1>'\n * ```\n */\nexport const html = (strings: TemplateStringsArray, ...values: unknown[]): string => {\n return strings.reduce((acc, part, index) => `${acc}${part}${values[index] ?? ''}`, '');\n};\n\n/**\n * Escapes HTML entities in interpolated values for XSS prevention.\n * Use this when you need to safely embed user content in templates.\n *\n * @param strings - Template literal string parts\n * @param values - Interpolated values to escape\n * @returns Combined HTML string with escaped values\n *\n * @example\n * ```ts\n * const userInput = '<script>alert(\"xss\")</script>';\n * const safe = safeHtml`<div>${userInput}</div>`;\n * // Result: '<div><script>alert(\"xss\")</script></div>'\n * ```\n */\nexport const safeHtml = (strings: TemplateStringsArray, ...values: unknown[]): string => {\n const escapeMap: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '`': '`',\n };\n\n const escape = (value: unknown): string => {\n const str = String(value ?? '');\n return str.replace(/[&<>\"'`]/g, (char) => escapeMap[char]);\n };\n\n return strings.reduce((acc, part, index) => `${acc}${part}${escape(values[index])}`, '');\n};\n"],"names":["coercePropValue","rawValue","config","type","normalized","callable","constructable","hasPrototype","hasPrototypeMethods","hasInheritedConstructor","isClassSyntax","result","error","defineComponent","tagName","definition","BQueryComponent","_name","_oldValue","_newValue","key","value","props","attrValue","triggerUpdated","emit","event","detail","markup","sanitizedMarkup","sanitizeHtml","styleElement","component","elementClass","html","strings","values","acc","part","index","safeHtml","escapeMap","escape","char"],"mappings":"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"}
|