11import type { HeadTag , PropResolver , ResolvableHead } from '../types'
22import { walkResolver } from '../utils/walkResolver'
3- import { DupeableTags , TagConfigKeys } from './const'
3+ import { DupeableTags , HasElementTags , TagConfigKeys } from './const'
44
55function normalizeStyleClassProps (
66 key : 'class' | 'style' ,
@@ -59,24 +59,26 @@ export function normalizeProps(tag: HeadTag, input: Record<string, any>): HeadTa
5959 return tag
6060 }
6161
62- Object . entries ( input ) . forEach ( ( [ key , value ] ) => {
63- if ( key === '__proto__' || key === 'constructor' || key === 'prototype' )
62+ const isHtmlTag = HasElementTags . has ( tag . tag ) || tag . tag === 'htmlAttrs' || tag . tag === 'bodyAttrs'
63+
64+ Object . entries ( input ) . forEach ( ( [ prop , value ] ) => {
65+ if ( prop === '__proto__' || prop === 'constructor' || prop === 'prototype' )
6466 return
6567 // if the value is a primitive, return early
6668 if ( value === null ) {
6769 // @ts -expect-error untyped
68- tag . props [ key ] = null
70+ tag . props [ prop ] = null
6971 return
7072 }
7173
72- if ( key === 'class' || key === 'style' ) {
74+ if ( prop === 'class' || prop === 'style' ) {
7375 // @ts -expect-error untyped
74- tag . props [ key ] = normalizeStyleClassProps ( key as 'class' | 'style' , value )
76+ tag . props [ prop ] = normalizeStyleClassProps ( prop as 'class' | 'style' , value )
7577 return
7678 }
7779
78- if ( TagConfigKeys . has ( key ) ) {
79- if ( [ 'textContent' , 'innerHTML' ] . includes ( key ) && typeof value === 'object' ) {
80+ if ( TagConfigKeys . has ( prop ) ) {
81+ if ( ( prop === 'textContent' || prop === 'innerHTML' ) && typeof value === 'object' ) {
8082 let type = input . type
8183 if ( ! input . type ) {
8284 type = 'application/json'
@@ -86,18 +88,21 @@ export function normalizeProps(tag: HeadTag, input: Record<string, any>): HeadTa
8688 }
8789 input . type = type
8890 tag . props . type = type
89- // @ts -expect-error untyped
90- tag [ key ] = JSON . stringify ( value )
91+ tag [ prop ] = JSON . stringify ( value )
9192 }
9293 else {
9394 // @ts -expect-error untyped
94- tag [ key ] = value
95+ tag [ prop ] = value
9596 }
9697 return
9798 }
9899
100+ // Normalize camelCase HTML attributes to lowercase (e.g. hrefLang -> hreflang)
101+ // Only for real HTML element tags, not internal virtual tags like _flatMeta
102+ const isDataKey = prop . startsWith ( 'data-' )
103+ const key = isHtmlTag && ! isDataKey ? prop . toLowerCase ( ) : prop
104+
99105 const strValue = String ( value )
100- const isDataKey = key . startsWith ( 'data-' )
101106 const isMetaContentKey = tag . tag === 'meta' && key === 'content'
102107
103108 if ( strValue === 'true' || strValue === '' ) {
0 commit comments