@@ -48,6 +48,14 @@ import { EntryHeader } from "./header"
48
48
import { EntryContentLoading } from "./loading"
49
49
import { EntryContentProvider } from "./provider"
50
50
51
+ const safeUrl = ( url : string , baseUrl : string ) => {
52
+ try {
53
+ return new URL ( url , baseUrl ) . href
54
+ } catch {
55
+ return url
56
+ }
57
+ }
58
+
51
59
export const EntryContent = ( { entryId } : { entryId : ActiveEntryId } ) => {
52
60
const title = useFeedHeaderTitle ( )
53
61
const { feedId, view } = useRouteParms ( )
@@ -150,6 +158,17 @@ export const EntryContentRender: Component<{ entryId: string }> = ({ entryId, cl
150
158
: undefined ,
151
159
[ readerFontFamily ] ,
152
160
)
161
+
162
+ const populatedFullHref = useMemo ( ( ) => {
163
+ const href = entry ?. entries . url
164
+ if ( ! href ) return "#"
165
+
166
+ if ( href . startsWith ( "http" ) ) return href
167
+ const feedSiteUrl = feed ?. siteUrl
168
+ if ( href . startsWith ( "/" ) && feedSiteUrl ) return safeUrl ( href , feedSiteUrl )
169
+ return href
170
+ } , [ entry ?. entries . url , feed ?. siteUrl ] )
171
+
153
172
if ( ! entry ) return null
154
173
155
174
const content = entry ?. entries . content ?? data ?. entries . content
@@ -184,7 +203,7 @@ export const EntryContentRender: Component<{ entryId: string }> = ({ entryId, cl
184
203
className = "relative m-auto min-w-0 max-w-[550px] @3xl:max-w-[70ch]"
185
204
>
186
205
< a
187
- href = { entry . entries . url || void 0 }
206
+ href = { populatedFullHref || void 0 }
188
207
target = "_blank"
189
208
className = "-mx-6 block cursor-default rounded-lg p-6 transition-colors hover:bg-theme-item-hover focus-visible:bg-theme-item-hover focus-visible:!outline-none @sm:-mx-3 @sm:p-3"
190
209
rel = "noreferrer"
0 commit comments