1
- import type { PropsWithChildren , ReactElement , ReactNode } from 'https://esm.sh/react'
2
- import { Children , createElement , Fragment , isValidElement , useContext , useEffect } from 'https://esm.sh/react'
1
+ import type { PropsWithChildren , ReactNode } from 'https://esm.sh/react'
2
+ import { Children , Fragment , isValidElement , useContext , useEffect } from 'https://esm.sh/react'
3
3
import util from '../../shared/util.ts'
4
4
import { RendererContext } from './context.ts'
5
5
import Script from './script.ts'
@@ -8,7 +8,7 @@ export default function Head(props: PropsWithChildren<{}>) {
8
8
const renderer = useContext ( RendererContext )
9
9
10
10
if ( window . Deno ) {
11
- parse ( props . children ) . forEach ( ( { type, props } , key ) => renderer . cache . headElements . set ( key , { type, props } ) )
11
+ parse ( props . children ) . forEach ( ( { type, props } , key ) => renderer . storage . headElements . set ( key , { type, props } ) )
12
12
}
13
13
14
14
useEffect ( ( ) => {
@@ -62,64 +62,6 @@ export default function Head(props: PropsWithChildren<{}>) {
62
62
return null
63
63
}
64
64
65
- interface SEOProps {
66
- title ?: string
67
- description ?: string
68
- keywords ?: string | string [ ]
69
- url ?: string
70
- image ?: string
71
- twitter ?: {
72
- card ?: 'summary' | 'summary_large_image' | 'app' | 'player'
73
- site ?: string
74
- creator ?: string
75
- }
76
- }
77
-
78
- export function SEO ( props : SEOProps ) {
79
- const { title, description, keywords, url, image, twitter } = props
80
- return createElement (
81
- Head ,
82
- undefined ,
83
- title && createElement ( 'title' , undefined , title ) ,
84
- description && createElement ( 'meta' , { name : 'description' , content : description } ) ,
85
- keywords && createElement ( 'meta' , { name : 'keywords' , content : util . isArray ( keywords ) ? keywords . join ( ',' ) : keywords } ) ,
86
- title && createElement ( 'meta' , { name : 'og:title' , content : title } ) ,
87
- description && createElement ( 'meta' , { name : 'og:description' , content : description } ) ,
88
- title && createElement ( 'meta' , { name : 'twitter:title' , content : title } ) ,
89
- description && createElement ( 'meta' , { name : 'twitter:description' , content : description } ) ,
90
- url && createElement ( 'meta' , { name : 'og:url' , content : url } ) ,
91
- image && createElement ( 'meta' , { name : 'og:image' , content : image } ) ,
92
- image && createElement ( 'meta' , { name : 'twitter:image' , content : image } ) ,
93
- image && createElement ( 'meta' , { name : 'twitter:card' , content : twitter ?. card || 'summary_large_image' } ) ,
94
- twitter ?. site && createElement ( 'meta' , { name : 'twitter:site' , content : twitter . site } ) ,
95
- twitter ?. creator && createElement ( 'meta' , { name : 'twitter:creator' , content : twitter . creator } ) ,
96
- )
97
- }
98
-
99
- interface ViewportProps {
100
- width ?: number | 'device-width'
101
- height ?: number | 'device-height'
102
- initialScale ?: number
103
- minimumScale ?: number
104
- maximumScale ?: number
105
- userScalable ?: 'yes' | 'no'
106
- targetDensitydpi ?: number | 'device-dpi' | 'low-dpi' | 'medium-dpi' | 'high-dpi'
107
- }
108
-
109
- export function Viewport ( props : ViewportProps ) {
110
- const content = Object . entries ( props )
111
- . map ( ( [ key , value ] ) => {
112
- key = key . replace ( / [ A - Z ] / g, c => '-' + c . toLowerCase ( ) )
113
- return `${ key } =${ value } `
114
- } )
115
- . join ( ',' )
116
- return createElement (
117
- Head ,
118
- undefined ,
119
- content && createElement ( 'meta' , { name : 'viewport' , content } )
120
- )
121
- }
122
-
123
65
function parse ( node : ReactNode , els : Map < string , { type : string , props : Record < string , any > } > = new Map ( ) ) {
124
66
Children . forEach ( node , child => {
125
67
if ( ! isValidElement ( child ) ) {
@@ -131,10 +73,6 @@ function parse(node: ReactNode, els: Map<string, { type: string, props: Record<s
131
73
case Fragment :
132
74
parse ( props . children , els )
133
75
break
134
- case SEO :
135
- case Viewport :
136
- parse ( ( type ( props ) as ReactElement ) . props . children , els )
137
- break
138
76
case Script :
139
77
type = "script"
140
78
case 'base' :
@@ -144,32 +82,30 @@ function parse(node: ReactNode, els: Map<string, { type: string, props: Record<s
144
82
case 'style' :
145
83
case 'script' :
146
84
case 'no-script' :
147
- {
148
- let key = type
149
- if ( type === 'meta' ) {
150
- const propKeys = Object . keys ( props ) . map ( k => k . toLowerCase ( ) )
151
- if ( propKeys . includes ( 'charset' ) ) {
152
- return // ignore charset, always use utf-8
153
- }
154
- if ( propKeys . includes ( 'name' ) ) {
155
- key += `[name=${ JSON . stringify ( props [ 'name' ] ) } ]`
156
- } else if ( propKeys . includes ( 'property' ) ) {
157
- key += `[property=${ JSON . stringify ( props [ 'property' ] ) } ]`
158
- } else if ( propKeys . includes ( 'http-equiv' ) ) {
159
- key += `[http-equiv=${ JSON . stringify ( props [ 'http-equiv' ] ) } ]`
160
- } else {
161
- key += Object . keys ( props ) . filter ( k => ! ( / ^ c o n t e n t | c h i l d r e n $ / i. test ( k ) ) ) . map ( k => `[${ k . toLowerCase ( ) } =${ JSON . stringify ( props [ k ] ) } ]` ) . join ( '' )
162
- }
163
- } else if ( type !== 'title' ) {
164
- key += '-' + ( els . size + 1 )
85
+ let key = type
86
+ if ( type === 'meta' ) {
87
+ const propKeys = Object . keys ( props ) . map ( k => k . toLowerCase ( ) )
88
+ if ( propKeys . includes ( 'charset' ) ) {
89
+ return // ignore charset, always use utf-8
165
90
}
166
- // remove the children prop of base/meta/link
167
- if ( [ 'base' , 'meta' , 'link' ] . includes ( type ) && 'children' in props ) {
168
- const { children, ...rest } = props
169
- els . set ( key , { type, props : rest } )
91
+ if ( propKeys . includes ( 'name' ) ) {
92
+ key += `[name=${ JSON . stringify ( props [ 'name' ] ) } ]`
93
+ } else if ( propKeys . includes ( 'property' ) ) {
94
+ key += `[property=${ JSON . stringify ( props [ 'property' ] ) } ]`
95
+ } else if ( propKeys . includes ( 'http-equiv' ) ) {
96
+ key += `[http-equiv=${ JSON . stringify ( props [ 'http-equiv' ] ) } ]`
170
97
} else {
171
- els . set ( key , { type , props } )
98
+ key += Object . keys ( props ) . filter ( k => ! ( / ^ c o n t e n t | c h i l d r e n $ / i . test ( k ) ) ) . map ( k => `[ ${ k . toLowerCase ( ) } = ${ JSON . stringify ( props [ k ] ) } ]` ) . join ( '' )
172
99
}
100
+ } else if ( type !== 'title' ) {
101
+ key += '-' + ( els . size + 1 )
102
+ }
103
+ // remove the children prop of base/meta/link
104
+ if ( [ 'base' , 'meta' , 'link' ] . includes ( type ) && 'children' in props ) {
105
+ const { children, ...rest } = props
106
+ els . set ( key , { type, props : rest } )
107
+ } else {
108
+ els . set ( key , { type, props } )
173
109
}
174
110
break
175
111
}
0 commit comments