Skip to content

Commit f99c226

Browse files
authored
wip: HTMLElementAttributeMap 5
1 parent 83332aa commit f99c226

File tree

1 file changed

+112
-17
lines changed

1 file changed

+112
-17
lines changed

src/types.ts

+112-17
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ export type Equals<T> = (before: T, after: T) => boolean
77
export type Child = HTMLElement | Signal | string | number
88
export type Children = Array<Child>
99

10+
// https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
1011
type CSSColor = string
1112

13+
type UTF8 = "utf-8" | "UTF-8" // ASCII case-insensitive match for "UTF-8".
14+
1215
// ---------- Utils ----------
1316

1417
// export type AddBooleanString<T extends object> = {
@@ -35,8 +38,6 @@ type CommonHTMLAttributes = { // use ABC order
3538
datetime: string
3639
/** @see https://html.spec.whatwg.org/#fetch-priority-attribute */
3740
fetchpriority: "high" | "low" | "auto"
38-
/** @see https://html.spec.whatwg.org/#hyperlink */
39-
href: string | URL
4041
/** @see https://w3c.github.io/webappsec-subresource-integrity/ */
4142
integrity: string
4243
lang: string // TODO: Enumeration of all language codes?
@@ -49,8 +50,7 @@ type CommonHTMLAttributes = { // use ABC order
4950
/** @see https://drafts.csswg.org/mediaqueries/ @see https://html.spec.whatwg.org/#mq */
5051
media: string // TODO: union
5152
ping: string // TODO: Allow array and URL
52-
/** MIME type */
53-
type: string
53+
preload: "auto" | "" | "none" | "metadata"
5454
referrerpolicy: "" | "no-referrer" | "no-referrer-when-downgrade" | "same-origin" | "origin" | "strict-origin" | "origin-when-cross-origin" | "strict-origin-when-cross-origin" | "unsafe-url"
5555
/** @see https://html.spec.whatwg.org/#sizes-attribute */
5656
sizes: string // TODO: type
@@ -59,8 +59,15 @@ type CommonHTMLAttributes = { // use ABC order
5959
srcset: string // TODO: type
6060
/** @see https://html.spec.whatwg.org/#navigable-target-names */
6161
target: "_blank" | "_self" | "_parent" | "_top"
62+
/** MIME type */
63+
type: string
64+
/** @see https://html.spec.whatwg.org/#hyperlink */
65+
url: string | URL
6266
}
6367

68+
// https://drafts.csswg.org/mediaqueries/
69+
type MediaQuery = string
70+
6471
// based on HTML Living Standard (March 6, 2025)
6572
// https://html.spec.whatwg.org/multipage/dom.html#global-attributes
6673
type HTMLElementGlobalAttribute = {
@@ -109,10 +116,16 @@ type HTMLElementAttributeFactory<T extends Record<string, object>> = {
109116
[K in keyof T | Exclude<keyof HTMLElementTagNameMap, keyof T>]: Partial<HTMLElementGlobalAttribute & (K extends keyof T ? T[K] : {})>
110117
}
111118

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
112125
export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
113126
a: {
114127
// attributionsrc: string // Experimental
115-
href: CommonHTMLAttributes["href"]
128+
href: CommonHTMLAttributes["url"]
116129
target: CommonHTMLAttributes["target"]
117130
| "_unfencedTop" // Non-standard
118131
download: string | boolean
@@ -126,23 +139,46 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
126139
alt: string
127140
coords: string
128141
shape: "circle" | "circ" | "default" | "poly" | "polygon" | "rect" | "rectangle"
129-
href: CommonHTMLAttributes["href"]
142+
href: CommonHTMLAttributes["url"]
130143
target: CommonHTMLAttributes["target"]
131144
download: string
132145
ping: CommonHTMLAttributes["ping"]
133146
rel: CommonHTMLAttributes["linkTypes"]["a_area"]
134147
referrerpolicy: CommonHTMLAttributes["referrerpolicy"]
135148
}
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+
}
137158
base: {
138-
href: CommonHTMLAttributes["href"]
159+
href: CommonHTMLAttributes["url"]
139160
target: CommonHTMLAttributes["target"]
140161
}
141162
blockquote: {
142163
cite: string
143164
}
144165
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+
}
146182
canvas: {
147183
width: number
148184
height: number
@@ -169,7 +205,7 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
169205
open: boolean
170206
}
171207
embed: {
172-
src: CommonHTMLAttributes["src"]
208+
src: CommonHTMLAttributes["url"]
173209
type: CommonHTMLAttributes["type"]
174210
width: number
175211
height: number
@@ -179,7 +215,17 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
179215
form: string // a form element
180216
name: string
181217
}
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+
}
183229
iframe: {}
184230
img: {}
185231
input: {}
@@ -192,7 +238,7 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
192238
}
193239
li: {}
194240
link: {
195-
href: CommonHTMLAttributes["href"]
241+
href: CommonHTMLAttributes["url"]
196242
crossorigin: CommonHTMLAttributes["crossorigin"]
197243
rel: CommonHTMLAttributes["linkTypes"]["link"]
198244
media: CommonHTMLAttributes["media"]
@@ -214,7 +260,38 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
214260
map: {
215261
name: string
216262
}
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+
}
218295
meter: {
219296
value: number
220297
min: number
@@ -223,7 +300,14 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
223300
high: number
224301
optimum: number
225302
}
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+
}
227311
ol: {
228312
reversed: boolean
229313
start: number
@@ -252,7 +336,6 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
252336
cite: string
253337
}
254338
script: {}
255-
section: {}
256339
select: {}
257340
slot: {
258341
name: string
@@ -283,10 +366,22 @@ export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
283366
}
284367
track: {
285368
kind: "subtitles" | "captions" | "descriptions" | "chapters" | "metadata"
286-
src: CommonHTMLAttributes["src"]
369+
src: CommonHTMLAttributes["url"]
287370
srclang: CommonHTMLAttributes["lang"]
288371
label: string
289372
default: boolean
290373
}
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+
}
292387
}>

0 commit comments

Comments
 (0)