fix(client): resolve SVG links when prefetching (#5442)

pull/5444/head
lllleolin-max 2 weeks ago committed by GitHub
parent f1bcc0d971
commit 6500851eaa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1 @@
# HTML link destination

@ -0,0 +1,15 @@
---
sidebar: false
outline: false
---
# Link prefetching
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="150">
<a href="./svg.html"><text x="10" y="25">SVG link</text></a>
<a href="./svg.html#section"><text x="10" y="50">Same page, another hash</text></a>
<a xlink:href="./xlink.html"><text x="10" y="75">SVG xlink</text></a>
<a href="./new-tab.html" target="_blank"><text x="10" y="100">New tab</text></a>
</svg>
[HTML link](./html.md)

@ -0,0 +1 @@
# New tab destination

@ -0,0 +1,43 @@
test.runIf(process.env.VITE_TEST_BUILD)(
'prefetches SVG links without errors and respects new-tab targets',
async () => {
const errors: string[] = []
const onPageError = (error: Error) => errors.push(error.message)
page.on('pageerror', onPageError)
try {
await goto('/prefetch/')
await expect
.poll(
async () => ({
errors,
pages: await page
.locator('link[rel="prefetch"]')
.evaluateAll((links) =>
links
.map(
(link) =>
link
.getAttribute('href')
?.match(/prefetch_(.*?)\.md\./)?.[1]
)
.filter(Boolean)
.sort()
)
}),
{ timeout: 10_000 }
)
.toEqual({ errors: [], pages: ['html', 'svg', 'xlink'] })
await page.locator('svg a[href="./svg.html"]').click()
await page.waitForSelector('h1', { state: 'visible' })
await expect
.poll(() => page.locator('h1').textContent())
.toContain('SVG link destination')
expect(errors).toEqual([])
} finally {
page.off('pageerror', onPageError)
}
}
)

@ -0,0 +1,3 @@
# SVG link destination
## Section

@ -0,0 +1 @@
# SVG xlink destination

@ -10,6 +10,12 @@ import { inBrowser, pathToFile } from '../utils'
const hasFetched = new Set<string>()
const createLink = () => document.createElement('link')
const getLinkUrl = (link: HTMLAnchorElement | SVGAElement) =>
new URL(
link.href instanceof SVGAnimatedString ? link.href.animVal : link.href,
link.baseURI
)
const viaDOM = (url: string) => {
const link = createLink()
link.rel = `prefetch`
@ -64,9 +70,9 @@ export function usePrefetch() {
observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const link = entry.target as HTMLAnchorElement
const link = entry.target as HTMLAnchorElement | SVGAElement
observer!.unobserve(link)
const { pathname } = link
const { pathname } = getLinkUrl(link)
if (!hasFetched.has(pathname)) {
hasFetched.add(pathname)
const pageChunkPath = pathToFile(pathname)
@ -80,12 +86,7 @@ export function usePrefetch() {
document
.querySelectorAll<HTMLAnchorElement | SVGAElement>('#app a')
.forEach((link) => {
const { hostname, pathname } = new URL(
link.href instanceof SVGAnimatedString
? link.href.animVal
: link.href,
link.baseURI
)
const { hostname, pathname } = getLinkUrl(link)
const extMatch = pathname.match(/\.\w+$/)
if (extMatch && extMatch[0] !== '.html') {
return
@ -94,7 +95,7 @@ export function usePrefetch() {
if (
// only prefetch same tab navigation, since a new tab will load
// the lean js chunk instead.
link.target !== '_blank' &&
link.getAttribute('target') !== '_blank' &&
// only prefetch inbound links
hostname === location.hostname
) {

Loading…
Cancel
Save