diff --git a/.changeset/sixty-beds-give.md b/.changeset/sixty-beds-give.md new file mode 100644 index 000000000..d1a7711ff --- /dev/null +++ b/.changeset/sixty-beds-give.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +bugfix checking media-type in client-side router diff --git a/packages/astro/components/ViewTransitions.astro b/packages/astro/components/ViewTransitions.astro index 77d56e652..9c0a9dfdd 100644 --- a/packages/astro/components/ViewTransitions.astro +++ b/packages/astro/components/ViewTransitions.astro @@ -65,19 +65,19 @@ const { fallback = 'animate' } = Astro.props as Props; }; async function getHTML(href: string) { - let res; try { - res = await fetch(href); + const res = await fetch(href); + const html = await res.text(); + return { + ok: res.ok, + html, + redirected: res.redirected ? res.url : undefined, + // drop potential charset (+ other name/value pairs) as parser needs the mediaType + mediaType: res.headers.get('content-type')?.replace(/;.*$/, ''), + }; } catch (err) { return { ok: false }; } - const html = await res.text(); - return { - ok: res.ok, - html, - redirected: res.redirected ? res.url : undefined, - contentType: res.headers.get('content-type'), - }; } function getFallback(): Fallback { @@ -126,13 +126,13 @@ const { fallback = 'animate' } = Astro.props as Props; // A noop element used to prevent styles from being removed if (import.meta.env.DEV) { - var noopEl: string | undefined = document.createElement('div'); + var noopEl = document.createElement('div'); } async function updateDOM(doc: Document, loc: URL, state?: State, fallback?: Fallback) { // Check for a head element that should persist, either because it has the data // attribute or is a link el. - const persistedHeadElement = (el: Element): Element | null => { + const persistedHeadElement = (el: HTMLElement): Element | null => { const id = el.getAttribute(PERSIST_ATTR); const newEl = id && doc.head.querySelector(`[${PERSIST_ATTR}="${id}"]`); if (newEl) { @@ -189,7 +189,7 @@ const { fallback = 'animate' } = Astro.props as Props; // Swap head for (const el of Array.from(document.head.children)) { - const newEl = persistedHeadElement(el); + const newEl = persistedHeadElement(el as HTMLElement); // If the element exists in the document already, remove it // from the new document and leave the current node alone if (newEl) { @@ -290,16 +290,16 @@ const { fallback = 'animate' } = Astro.props as Props; async function navigate(dir: Direction, loc: URL, state?: State) { let finished: Promise; const href = loc.href; - const { html, ok, contentType, redirected } = await getHTML(href); + const { html, ok, mediaType, redirected } = await getHTML(href); // if there was a redirection, show the final URL in the browser's address bar redirected && (loc = new URL(redirected)); // If there is a problem fetching the new page, just do an MPA navigation to it. - if (!ok || contentType !== 'text/html') { + if (!ok || !(mediaType === 'text/html' || mediaType === 'application/xhtml+xml')) { location.href = href; return; } - const doc = parser.parseFromString(html, contentType); + const doc = parser.parseFromString(html, mediaType); if (!doc.querySelector('[name="astro-view-transitions-enabled"]')) { location.href = href; return;