Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0c8573f

Browse files
authored
fix: stricter type narrowing for head schema (#665)
* fix: stricter type narrowing * fix: suppress eslint empty-object-type for TS utility idioms
1 parent a8bcd0c commit 0c8573f

24 files changed

Lines changed: 388 additions & 194 deletions

File tree

packages/unhead/src/parser/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ export function parseHtmlForUnheadExtraction(html: string): PreparedHtmlTemplate
547547
continue
548548
}
549549
else if (tagId === TAG_BASE && !input.base) {
550-
input.base = attributes
550+
input.base = attributes as any
551551
position = tagEnd
552552
lastCopyPosition = position
553553
continue

packages/unhead/src/scripts/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type {
22
ActiveHeadEntry,
33
DataKeys,
4+
GenericScript,
45
HeadEntryOptions,
56
HttpEventAttributes,
67
MaybeEventFnHandlers,
78
SchemaAugmentations,
8-
ScriptWithoutEvents,
9+
ScriptHttpEvents,
910
} from '../types'
1011

1112
export type UseScriptStatus = 'awaitingLoad' | 'loading' | 'loaded' | 'error' | 'removed'
@@ -14,7 +15,7 @@ export type UseScriptContext<T extends Record<symbol | string, any>> = ScriptIns
1415
/**
1516
* Either a string source for the script or full script properties.
1617
*/
17-
export type UseScriptResolvedInput = Omit<ScriptWithoutEvents, 'src'> & { src: string } & DataKeys & MaybeEventFnHandlers<HttpEventAttributes> & SchemaAugmentations['script']
18+
export type UseScriptResolvedInput = Omit<GenericScript, 'src' | keyof ScriptHttpEvents> & { src: string } & DataKeys & MaybeEventFnHandlers<HttpEventAttributes> & SchemaAugmentations['script']
1819

1920
type BaseScriptApi = Record<symbol | string, any>
2021

packages/unhead/src/types/schema/attributes/global.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export interface GlobalAttributes {
7474
*
7575
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode
7676
*/
77-
inputmode?: string
77+
inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url'
7878
/**
7979
* Allows you to specify that a standard HTML element should behave like a registered custom built-in element.
8080
*
@@ -117,7 +117,7 @@ export interface GlobalAttributes {
117117
*
118118
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
119119
*/
120-
lang?: string
120+
lang?: 'en' | 'en-US' | 'en-GB' | 'de' | 'fr' | 'es' | 'it' | 'ja' | 'ko' | 'nl' | 'pl' | 'pt' | 'pt-BR' | 'ru' | 'zh' | 'zh-CN' | 'zh-TW' | 'ar' | 'hi' | 'id' | 'th' | 'tr' | 'uk' | 'vi' | (string & Record<never, never>)
121121
/**
122122
* A cryptographic nonce ("number used once") which can be used by Content Security Policy to determine whether or not
123123
* a given fetch will be allowed to proceed.

packages/unhead/src/types/schema/base.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export interface Base {
1+
interface BaseFields {
22
/**
33
* The base URL to be used throughout the document for relative URLs. Absolute and relative URLs are allowed.
44
*
@@ -11,5 +11,14 @@ export interface Base {
1111
*
1212
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base#attr-target
1313
*/
14-
target?: string
14+
target?: '_blank' | '_self' | '_parent' | '_top' | (string & Record<never, never>)
1515
}
16+
17+
/**
18+
* The `<base>` HTML element requires at least `href` or `target` to be valid.
19+
*
20+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
21+
*/
22+
export type Base
23+
= | (BaseFields & { href: string })
24+
| (BaseFields & { target: '_blank' | '_self' | '_parent' | '_top' | (string & Record<never, never>) })

packages/unhead/src/types/schema/bodyAttributes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export interface BodyEvents {
6363
onunload?: string
6464
}
6565

66-
export interface BodyAttributesWithoutEvents extends Pick<GlobalAttributes, 'class' | 'style' | 'id'> {
66+
export interface BodyAttributesWithoutEvents extends Pick<GlobalAttributes, 'class' | 'style' | 'id' | 'dir' | 'lang' | 'translate'> {
6767
}
6868

6969
export type BodyAttributes = BodyAttributesWithoutEvents & BodyEvents

packages/unhead/src/types/schema/head.ts

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
import type { InnerContent, ProcessesTemplateParams, ResolvesDuplicates, TagPosition, TagPriority } from '../tags'
1+
import type { InnerContent, ProcessesTemplateParams, ResolvesDuplicates, StringInnerContent, TagPosition, TagPriority } from '../tags'
22
import type { DeepResolvableProperties, ResolvableProperties, ResolvableValue, Stringable } from '../util'
33
import type { DataKeys } from './attributes/data'
44
import type { Base } from './base'
55
import type { BodyAttributesWithoutEvents, BodyEvents } from './bodyAttributes'
66
import type { HtmlAttributes } from './htmlAttributes'
77
import type {
8+
AlternateFeedLink,
9+
AlternateLanguageLink,
810
AlternateLink,
11+
AlternateMediaLink,
12+
AppleTouchIconLink,
913
AuthorLink,
1014
CanonicalLink,
1115
DnsPrefetchLink,
16+
FaviconLink,
1217
GenericLink,
1318
HelpLink,
1419
IconLink,
@@ -17,6 +22,7 @@ import type {
1722
LinkBase,
1823
LinkHttpEvents,
1924
ManifestLink,
25+
MaskIconLink,
2026
ModulepreloadLink,
2127
NextLink,
2228
PingbackLink,
@@ -73,9 +79,9 @@ export interface SchemaAugmentations {
7379
bodyAttrs: ResolvesDuplicates & TagPriority
7480
link: TagPriority & TagPosition & ResolvesDuplicates & ProcessesTemplateParams
7581
meta: TagPriority & ResolvesDuplicates & ProcessesTemplateParams
76-
style: TagPriority & TagPosition & InnerContent & ResolvesDuplicates & ProcessesTemplateParams
82+
style: TagPriority & TagPosition & StringInnerContent & ResolvesDuplicates & ProcessesTemplateParams
7783
script: TagPriority & TagPosition & InnerContent & ResolvesDuplicates & ProcessesTemplateParams
78-
noscript: TagPriority & TagPosition & InnerContent & ResolvesDuplicates & ProcessesTemplateParams
84+
noscript: TagPriority & TagPosition & StringInnerContent & ResolvesDuplicates & ProcessesTemplateParams
7985
}
8086

8187
export type MaybeArray<T> = T | T[]
@@ -114,9 +120,9 @@ export interface UnheadHtmlAttributes extends Omit<HtmlAttributes, 'class' | 'st
114120
* Unhead meta with support for array content values
115121
*/
116122
export type UnheadMeta
117-
= | (Omit<NameMeta, 'content'> & { content?: MaybeArray<Stringable> | null })
118-
| (Omit<PropertyMeta, 'content'> & { content?: MaybeArray<Stringable> | null })
119-
| (Omit<HttpEquivMeta, 'content'> & { content?: MaybeArray<Stringable> | null })
123+
= | (Omit<NameMeta, 'content'> & { content?: MaybeArray<string | number> | null })
124+
| (Omit<PropertyMeta, 'content'> & { content?: MaybeArray<string | number> | null })
125+
| (Omit<HttpEquivMeta, 'content'> & { content?: MaybeArray<string | number> | null })
120126
| CharsetMeta
121127

122128
export type MaybeEventFnHandlers<T> = {
@@ -125,11 +131,17 @@ export type MaybeEventFnHandlers<T> = {
125131

126132
export type ResolvableTitle = ResolvableValue<Stringable> | ResolvableProperties<({ textContent: string } & SchemaAugmentations['title'])>
127133
export type ResolvableTitleTemplate = string | ((title?: string) => string | null) | null | ({ textContent: string | ((title?: string) => string | null) } & SchemaAugmentations['titleTemplate'])
128-
export type ResolvableBase = ResolvableProperties<Base & SchemaAugmentations['base']>
129-
export type ResolvableLink = ResolvableProperties<Link & SchemaAugmentations['link']> & MaybeEventFnHandlers<LinkHttpEvents>
130-
export type ResolvableMeta = ResolvableProperties<UnheadMeta & SchemaAugmentations['meta']>
134+
export type ResolvableBase = DistributeResolvable<Base, SchemaAugmentations['base']>
135+
type DistributeResolvable<T, Aug> = T extends any ? ResolvableProperties<T & Aug> : never
136+
type DistributeResolvableWithEvents<T, Aug, Events> = T extends any
137+
? T extends Events
138+
? ResolvableProperties<Omit<T, keyof Events> & Aug> & MaybeEventFnHandlers<Events>
139+
: ResolvableProperties<T & Aug>
140+
: never
141+
export type ResolvableLink = DistributeResolvableWithEvents<Link, SchemaAugmentations['link'], LinkHttpEvents>
142+
export type ResolvableMeta = DistributeResolvable<UnheadMeta, SchemaAugmentations['meta']>
131143
export type ResolvableStyle = ResolvableProperties<Style & DataKeys & SchemaAugmentations['style']> | string
132-
export type ResolvableScript = ResolvableProperties<Script & SchemaAugmentations['script']> & MaybeEventFnHandlers<ScriptHttpEvents> | string
144+
export type ResolvableScript = DistributeResolvableWithEvents<Script, SchemaAugmentations['script'], ScriptHttpEvents> | string
133145
export type ResolvableNoscript = ResolvableProperties<Noscript & DataKeys & SchemaAugmentations['noscript']> | string
134146
export type ResolvableHtmlAttributes = ResolvableProperties<UnheadHtmlAttributes & DataKeys & SchemaAugmentations['htmlAttrs']>
135147
export type ResolvableBodyAttributes = ResolvableProperties<UnheadBodyAttributesWithoutEvents & DataKeys & SchemaAugmentations['bodyAttrs']> & MaybeEventFnHandlers<BodyEvents>
@@ -243,10 +255,15 @@ export type { BodyAttributesWithoutEvents, BodyEvents } from './bodyAttributes'
243255

244256
// Link types (narrowed)
245257
export type {
258+
AlternateFeedLink,
259+
AlternateLanguageLink,
246260
AlternateLink,
261+
AlternateMediaLink,
262+
AppleTouchIconLink,
247263
AuthorLink,
248264
CanonicalLink,
249265
DnsPrefetchLink,
266+
FaviconLink,
250267
GenericLink,
251268
HelpLink,
252269
IconLink,
@@ -255,6 +272,7 @@ export type {
255272
LinkBase,
256273
LinkHttpEvents,
257274
ManifestLink,
275+
MaskIconLink,
258276
ModulepreloadLink,
259277
NextLink,
260278
PingbackLink,
@@ -302,12 +320,8 @@ export type {
302320
PropertyMeta,
303321
}
304322

305-
// Legacy exports for backwards compatibility
306-
export type { GenericLink as LinkWithoutEvents } from './link'
307323
// Other types
308324
export type { MetaFlat } from './metaFlat'
309-
310-
export type { GenericScript as ScriptWithoutEvents } from './script'
311325
export type { SpeculationRules } from './struct/speculationRules'
312326

313327
// ============================================================================
@@ -325,5 +339,5 @@ export interface MetaGeneric extends MetaBase {
325339
'property'?: MetaProperties | (string & Record<never, never>)
326340
'http-equiv'?: 'content-security-policy' | 'content-type' | 'default-style' | 'x-ua-compatible' | 'refresh' | 'accept-ch' | (string & Record<never, never>)
327341
'charset'?: 'utf-8' | (string & Record<never, never>)
328-
'content'?: Stringable
342+
'content'?: string | number
329343
}

0 commit comments

Comments
 (0)