-
Notifications
You must be signed in to change notification settings - Fork 327
/
Copy pathswap-document.ts
61 lines (53 loc) · 2.04 KB
/
swap-document.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const PERSIST_ATTR = 'data-astro-transition-persist';
const EMOTION_ATTR = 'data-emotion';
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
type SwapFunctions = typeof import('astro:transitions/client').swapFunctions;
/**
* @internal
* Custom swap function to make mounting and styling
* of Clerk components work with View Transitions in Astro.
*
* See https://docs.astro.build/en/guides/view-transitions/#building-a-custom-swap-function
*/
export function swapDocument(swapFunctions: SwapFunctions, doc: Document) {
swapFunctions.deselectScripts(doc);
swapFunctions.swapRootAttributes(doc);
// Keep the elements created by `@emotion/cache`
const emotionElements = document.querySelectorAll(`style[${EMOTION_ATTR}]`);
swapHeadElements(doc, Array.from(emotionElements));
const restoreFocusFunction = swapFunctions.saveFocus();
swapFunctions.swapBodyElement(doc.body, document.body);
restoreFocusFunction();
}
/**
* This function is a copy of the original `swapHeadElements` function from `astro:transitions/client`.
* The difference is that you can pass a list of elements that should not be removed
* in the new document.
*
* See https://github.com/withastro/astro/blob/d6f17044d3873df77cfbc73230cb3194b5a7d82a/packages/astro/src/transitions/swap-functions.ts#L51
*/
function swapHeadElements(doc: Document, ignoredElements: Element[]) {
for (const el of Array.from(document.head.children)) {
const newEl = persistedHeadElement(el, doc);
if (newEl) {
newEl.remove();
} else {
if (!ignoredElements.includes(el)) {
el.remove();
}
}
}
document.head.append(...doc.head.children);
}
function persistedHeadElement(el: Element, newDoc: Document) {
const id = el.getAttribute(PERSIST_ATTR);
const newEl = id && newDoc.head.querySelector(`[${PERSIST_ATTR}="${id}"]`);
if (newEl) {
return newEl;
}
if (el.matches('link[rel=stylesheet]')) {
const href = el.getAttribute('href');
return newDoc.head.querySelector(`link[rel=stylesheet][href="${href}"]`);
}
return null;
}