@@ -7,8 +7,11 @@ export type Equals<T> = (before: T, after: T) => boolean
7
7
export type Child = HTMLElement | Signal | string | number
8
8
export type Children = Array < Child >
9
9
10
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
10
11
type CSSColor = string
11
12
13
+ type UTF8 = "utf-8" | "UTF-8" // ASCII case-insensitive match for "UTF-8".
14
+
12
15
// ---------- Utils ----------
13
16
14
17
// export type AddBooleanString<T extends object> = {
@@ -35,8 +38,6 @@ type CommonHTMLAttributes = { // use ABC order
35
38
datetime : string
36
39
/** @see https://html.spec.whatwg.org/#fetch-priority-attribute */
37
40
fetchpriority : "high" | "low" | "auto"
38
- /** @see https://html.spec.whatwg.org/#hyperlink */
39
- href : string | URL
40
41
/** @see https://w3c.github.io/webappsec-subresource-integrity/ */
41
42
integrity : string
42
43
lang : string // TODO: Enumeration of all language codes?
@@ -49,8 +50,7 @@ type CommonHTMLAttributes = { // use ABC order
49
50
/** @see https://drafts.csswg.org/mediaqueries/ @see https://html.spec.whatwg.org/#mq */
50
51
media : string // TODO: union
51
52
ping : string // TODO: Allow array and URL
52
- /** MIME type */
53
- type : string
53
+ preload : "auto" | "" | "none" | "metadata"
54
54
referrerpolicy : "" | "no-referrer" | "no-referrer-when-downgrade" | "same-origin" | "origin" | "strict-origin" | "origin-when-cross-origin" | "strict-origin-when-cross-origin" | "unsafe-url"
55
55
/** @see https://html.spec.whatwg.org/#sizes-attribute */
56
56
sizes : string // TODO: type
@@ -59,8 +59,15 @@ type CommonHTMLAttributes = { // use ABC order
59
59
srcset : string // TODO: type
60
60
/** @see https://html.spec.whatwg.org/#navigable-target-names */
61
61
target : "_blank" | "_self" | "_parent" | "_top"
62
+ /** MIME type */
63
+ type : string
64
+ /** @see https://html.spec.whatwg.org/#hyperlink */
65
+ url : string | URL
62
66
}
63
67
68
+ // https://drafts.csswg.org/mediaqueries/
69
+ type MediaQuery = string
70
+
64
71
// based on HTML Living Standard (March 6, 2025)
65
72
// https://html.spec.whatwg.org/multipage/dom.html#global-attributes
66
73
type HTMLElementGlobalAttribute = {
@@ -109,10 +116,16 @@ type HTMLElementAttributeFactory<T extends Record<string, object>> = {
109
116
[ K in keyof T | Exclude < keyof HTMLElementTagNameMap , keyof T > ] : Partial < HTMLElementGlobalAttribute & ( K extends keyof T ? T [ K ] : { } ) >
110
117
}
111
118
119
+ type HTMLMetaElementAttributeFactory < T extends [ string , unknown , object ?] > = {
120
+ name : T [ 0 ]
121
+ content : T [ 1 ]
122
+ } & T [ 2 ]
123
+
124
+ // https://html.spec.whatwg.org/#elements-3
112
125
export type HTMLElementAttributeMap = HTMLElementAttributeFactory < {
113
126
a : {
114
127
// attributionsrc: string // Experimental
115
- href : CommonHTMLAttributes [ "href " ]
128
+ href : CommonHTMLAttributes [ "url " ]
116
129
target : CommonHTMLAttributes [ "target" ]
117
130
| "_unfencedTop" // Non-standard
118
131
download : string | boolean
@@ -126,23 +139,46 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
126
139
alt : string
127
140
coords : string
128
141
shape : "circle" | "circ" | "default" | "poly" | "polygon" | "rect" | "rectangle"
129
- href : CommonHTMLAttributes [ "href " ]
142
+ href : CommonHTMLAttributes [ "url " ]
130
143
target : CommonHTMLAttributes [ "target" ]
131
144
download : string
132
145
ping : CommonHTMLAttributes [ "ping" ]
133
146
rel : CommonHTMLAttributes [ "linkTypes" ] [ "a_area" ]
134
147
referrerpolicy : CommonHTMLAttributes [ "referrerpolicy" ]
135
148
}
136
- audio : { }
149
+ audio : {
150
+ src : CommonHTMLAttributes [ "url" ]
151
+ crossorigin : CommonHTMLAttributes [ "crossorigin" ]
152
+ preload : CommonHTMLAttributes [ "preload" ]
153
+ autoplay : boolean
154
+ loop : boolean
155
+ muted : boolean
156
+ controls : boolean
157
+ }
137
158
base : {
138
- href : CommonHTMLAttributes [ "href " ]
159
+ href : CommonHTMLAttributes [ "url " ]
139
160
target : CommonHTMLAttributes [ "target" ]
140
161
}
141
162
blockquote : {
142
163
cite : string
143
164
}
144
165
body : { }
145
- button : { }
166
+ button : {
167
+ command : "toggle-popover" | "show-popover" | "hide-popover" | "close" | "show-modal" | `--${string } ` // Experimental
168
+ commandfor : string // Experimental
169
+ disabled : boolean
170
+ form : string // form element
171
+ formaction : CommonHTMLAttributes [ "url" ]
172
+ formenctype : "application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain"
173
+ formmethod : "get" | "post" | "dialog"
174
+ formnovalidate : boolean
175
+ formtarget : CommonHTMLAttributes [ "target" ]
176
+ name : string
177
+ popovertarget : string // Popover API
178
+ popovertargetaction : "toggle" | "show" | "hide" // Popover API
179
+ type : "submit" | "reset" | "button"
180
+ value : string
181
+ }
146
182
canvas : {
147
183
width : number
148
184
height : number
@@ -169,7 +205,7 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
169
205
open : boolean
170
206
}
171
207
embed : {
172
- src : CommonHTMLAttributes [ "src " ]
208
+ src : CommonHTMLAttributes [ "url " ]
173
209
type : CommonHTMLAttributes [ "type" ]
174
210
width : number
175
211
height : number
@@ -179,7 +215,17 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
179
215
form : string // a form element
180
216
name : string
181
217
}
182
- form : { }
218
+ form : {
219
+ "accept-charset" : UTF8
220
+ action : CommonHTMLAttributes [ "url" ]
221
+ autocomplete : "on" | "off"
222
+ enctype : "application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain"
223
+ method : "get" | "post" | "dialog"
224
+ name : string
225
+ novalidate : boolean
226
+ target : CommonHTMLAttributes [ "target" ]
227
+ rel : CommonHTMLAttributes [ "linkTypes" ] [ "form" ]
228
+ }
183
229
iframe : { }
184
230
img : { }
185
231
input : { }
@@ -192,7 +238,7 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
192
238
}
193
239
li : { }
194
240
link : {
195
- href : CommonHTMLAttributes [ "href " ]
241
+ href : CommonHTMLAttributes [ "url " ]
196
242
crossorigin : CommonHTMLAttributes [ "crossorigin" ]
197
243
rel : CommonHTMLAttributes [ "linkTypes" ] [ "link" ]
198
244
media : CommonHTMLAttributes [ "media" ]
@@ -214,7 +260,38 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
214
260
map : {
215
261
name : string
216
262
}
217
- meta : { }
263
+ meta : (
264
+ // https://wiki.whatwg.org/wiki/MetaExtensions
265
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name
266
+ // FIXME: (property) content?: string | undefined
267
+ HTMLMetaElementAttributeFactory <
268
+ // Standard metadata names defined in the HTML specification
269
+ [ "application-name" , string ]
270
+ | [ "author" , string ]
271
+ | [ "description" , string ]
272
+ | [ "generator" , string ]
273
+ | [ "keywords" , string ]
274
+ | [ "referrer" , Exclude < CommonHTMLAttributes [ "referrerpolicy" ] , "" | "unsafe-url" > | "unsafe-URL" ]
275
+ | [ "theme-color" , CSSColor , { media : MediaQuery } ]
276
+ | [ "color-scheme" , "normal" | "light" | "dark" | "light dark" | "dark light" | "only light" ]
277
+ // Standard metadata names defined in other specifications
278
+ | [ "viewport" , "width" | "height" | "initial-scale" | "maximum-scale" | "minimum-scale" | "user-scalable" | "viewport-fit" ]
279
+ > // FIXME: enable
280
+ // | ( {
281
+ // name: string
282
+ // content: string
283
+ // /**
284
+ // * This attribute is only relevant when the element's name attribute is set to theme-color.
285
+ // * Otherwise, it has no effect, and should not be included.
286
+ // * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#media
287
+ // */
288
+ // media: never
289
+ // } & {} )
290
+ ) & {
291
+ "http-equiv" : "content-language" | "content-type" | "default-style" | "refresh" | "set-cookie" | "x-ua-compatible" | "content-security-policy"
292
+ charset : UTF8
293
+ media : never
294
+ }
218
295
meter : {
219
296
value : number
220
297
min : number
@@ -223,7 +300,14 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
223
300
high : number
224
301
optimum : number
225
302
}
226
- object : { }
303
+ object : {
304
+ data : CommonHTMLAttributes [ "url" ]
305
+ type : CommonHTMLAttributes [ "type" ]
306
+ name : string
307
+ form : string // form element
308
+ width : number
309
+ height : number
310
+ }
227
311
ol : {
228
312
reversed : boolean
229
313
start : number
@@ -252,7 +336,6 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
252
336
cite : string
253
337
}
254
338
script : { }
255
- section : { }
256
339
select : { }
257
340
slot : {
258
341
name : string
@@ -283,10 +366,22 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
283
366
}
284
367
track : {
285
368
kind : "subtitles" | "captions" | "descriptions" | "chapters" | "metadata"
286
- src : CommonHTMLAttributes [ "src " ]
369
+ src : CommonHTMLAttributes [ "url " ]
287
370
srclang : CommonHTMLAttributes [ "lang" ]
288
371
label : string
289
372
default : boolean
290
373
}
291
- video : { }
374
+ video : {
375
+ src : CommonHTMLAttributes [ "url" ]
376
+ crossorigin : CommonHTMLAttributes [ "crossorigin" ]
377
+ poster : CommonHTMLAttributes [ "url" ]
378
+ preload : CommonHTMLAttributes [ "preload" ]
379
+ autoplay : boolean
380
+ playsinline : boolean
381
+ loop : boolean
382
+ muted : boolean
383
+ controls : boolean
384
+ width : number
385
+ height : number
386
+ }
292
387
} >
0 commit comments