@prismicio/next 2.3.1-pr.147.05dde81 → 2.3.1-pr.147.286b2d0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PrismicPreviewClient.cjs +34 -13
- package/dist/PrismicPreviewClient.cjs.map +1 -1
- package/dist/PrismicPreviewClient.js +34 -13
- package/dist/PrismicPreviewClient.js.map +1 -1
- package/dist/getPreviewRef.cjs +2 -2
- package/dist/getPreviewRef.cjs.map +1 -1
- package/dist/getPreviewRef.d.cts.map +1 -1
- package/dist/getPreviewRef.d.ts.map +1 -1
- package/dist/getPreviewRef.js +2 -2
- package/dist/getPreviewRef.js.map +1 -1
- package/dist/lib/expiredPreviewCookies.cjs +5 -0
- package/dist/lib/expiredPreviewCookies.cjs.map +1 -1
- package/dist/lib/expiredPreviewCookies.js +5 -1
- package/dist/lib/expiredPreviewCookies.js.map +1 -1
- package/dist/lib/previewRefFromCookie.cjs +24 -0
- package/dist/lib/previewRefFromCookie.cjs.map +1 -0
- package/dist/lib/previewRefFromCookie.js +24 -0
- package/dist/lib/previewRefFromCookie.js.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/pages/PrismicPreview.cjs +36 -12
- package/dist/pages/PrismicPreview.cjs.map +1 -1
- package/dist/pages/PrismicPreview.js +36 -12
- package/dist/pages/PrismicPreview.js.map +1 -1
- package/dist/pages/exitPreview.cjs +5 -1
- package/dist/pages/exitPreview.cjs.map +1 -1
- package/dist/pages/exitPreview.d.cts.map +1 -1
- package/dist/pages/exitPreview.d.ts.map +1 -1
- package/dist/pages/exitPreview.js +6 -2
- package/dist/pages/exitPreview.js.map +1 -1
- package/dist/pages/setPreviewData.cjs +8 -2
- package/dist/pages/setPreviewData.cjs.map +1 -1
- package/dist/pages/setPreviewData.d.cts.map +1 -1
- package/dist/pages/setPreviewData.d.ts.map +1 -1
- package/dist/pages/setPreviewData.js +8 -2
- package/dist/pages/setPreviewData.js.map +1 -1
- package/dist/redirectToPreviewURL.cjs +8 -0
- package/dist/redirectToPreviewURL.cjs.map +1 -1
- package/dist/redirectToPreviewURL.js +8 -0
- package/dist/redirectToPreviewURL.js.map +1 -1
- package/package.json +1 -1
- package/src/PrismicPreviewClient.tsx +36 -5
- package/src/getPreviewRef.ts +6 -6
- package/src/lib/expiredPreviewCookies.ts +5 -0
- package/src/lib/previewRefFromCookie.ts +33 -0
- package/src/pages/PrismicPreview.tsx +37 -10
- package/src/pages/exitPreview.ts +12 -2
- package/src/pages/setPreviewData.ts +19 -2
- package/src/redirectToPreviewURL.ts +12 -0
|
@@ -9,34 +9,55 @@ const PrismicPreviewClient = (props) => {
|
|
|
9
9
|
const { refresh } = (0, next_navigation_js.useRouter)();
|
|
10
10
|
(0, react.useEffect)(() => {
|
|
11
11
|
const controller = new AbortController();
|
|
12
|
+
let starting;
|
|
13
|
+
let startController;
|
|
14
|
+
let ending = false;
|
|
12
15
|
window.addEventListener("prismicPreviewUpdate", onUpdate, { signal: controller.signal });
|
|
13
16
|
window.addEventListener("prismicPreviewEnd", onEnd, { signal: controller.signal });
|
|
14
17
|
const cookie = getPrismicPreviewCookie(window.document.cookie);
|
|
15
|
-
if ((cookie ? (decodeURIComponent(cookie).match(/"([^"]+)\.prismic\.io"/) || [])[1] : void 0) === repositoryName && !isDraftMode)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
if ((cookie ? (decodeURIComponent(cookie).match(/"([^"]+)\.prismic\.io"/) || [])[1] : void 0) === repositoryName && !isDraftMode) start();
|
|
19
|
+
function start() {
|
|
20
|
+
if (starting) return;
|
|
21
|
+
startController = new AbortController();
|
|
22
|
+
starting = globalThis.fetch(updatePreviewURL, {
|
|
23
|
+
redirect: "manual",
|
|
24
|
+
signal: startController.signal
|
|
25
|
+
}).then((res) => {
|
|
26
|
+
if (res.type !== "opaqueredirect") {
|
|
27
|
+
console.error(`[<PrismicPreview>] Failed to start the preview using "${updatePreviewURL}". Does it exist?`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
window.location.reload();
|
|
31
|
+
}).catch(() => {}).finally(() => {
|
|
32
|
+
starting = void 0;
|
|
33
|
+
startController = void 0;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
25
36
|
function onUpdate(event) {
|
|
26
37
|
event.preventDefault();
|
|
27
|
-
|
|
38
|
+
if (ending) return;
|
|
39
|
+
if (isDraftMode) refresh();
|
|
40
|
+
else start();
|
|
28
41
|
}
|
|
29
42
|
function onEnd(event) {
|
|
30
43
|
event.preventDefault();
|
|
44
|
+
if (ending) return;
|
|
45
|
+
ending = true;
|
|
46
|
+
startController?.abort();
|
|
31
47
|
globalThis.fetch(exitPreviewURL, { signal: controller.signal }).then((res) => {
|
|
32
48
|
if (!res.ok) {
|
|
33
49
|
console.error(`[<PrismicPreview>] Failed to exit Preview Mode using the "${exitPreviewURL}" API endpoint. Does it exist?`);
|
|
34
50
|
return;
|
|
35
51
|
}
|
|
36
52
|
refresh();
|
|
37
|
-
}).catch(() => {})
|
|
53
|
+
}).catch(() => {}).finally(() => {
|
|
54
|
+
ending = false;
|
|
55
|
+
});
|
|
38
56
|
}
|
|
39
|
-
return () =>
|
|
57
|
+
return () => {
|
|
58
|
+
controller.abort();
|
|
59
|
+
startController?.abort();
|
|
60
|
+
};
|
|
40
61
|
}, [
|
|
41
62
|
repositoryName,
|
|
42
63
|
isDraftMode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrismicPreviewClient.cjs","names":["prismicCookie"],"sources":["../src/PrismicPreviewClient.tsx"],"sourcesContent":["\"use client\"\n\nimport { cookie as prismicCookie } from \"@prismicio/client\"\nimport { useRouter } from \"next/navigation\"\nimport type { FC } from \"react\"\nimport { useEffect } from \"react\"\n\ntype PrismicPreviewClientProps = {\n\trepositoryName: string\n\tisDraftMode: boolean\n\tupdatePreviewURL?: string\n\texitPreviewURL?: string\n}\n\nexport const PrismicPreviewClient: FC<PrismicPreviewClientProps> = (props) => {\n\tconst {\n\t\trepositoryName,\n\t\tisDraftMode,\n\t\tupdatePreviewURL = \"/api/preview\",\n\t\texitPreviewURL = \"/api/exit-preview\",\n\t} = props\n\n\tconst { refresh } = useRouter()\n\n\tuseEffect(() => {\n\t\tconst controller = new AbortController()\n\n\t\twindow.addEventListener(\"prismicPreviewUpdate\", onUpdate, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\twindow.addEventListener(\"prismicPreviewEnd\", onEnd, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\n\t\tconst cookie = getPrismicPreviewCookie(window.document.cookie)\n\t\tconst cookieRepositoryName = cookie\n\t\t\t? (decodeURIComponent(cookie).match(/\"([^\"]+)\\.prismic\\.io\"/) || [])[1]\n\t\t\t: undefined\n\t\tconst hasCookieForRepository = cookieRepositoryName === repositoryName\n\n\t\t// Start the preview for preview share links. Previews from\n\t\t// share links do not go to the `updatePreviewURL` like a normal\n\t\t// preview.\n\t\tif (hasCookieForRepository && !isDraftMode) {\n\t\t\t// We check `opaqueredirect` because we don't care if\n\t\t\t// the redirect was successful or not. As long as it\n\t\t\t// redirects, we know the endpoint exists and draft mode\n\t\t\t// is active.\n\t\t\
|
|
1
|
+
{"version":3,"file":"PrismicPreviewClient.cjs","names":["prismicCookie"],"sources":["../src/PrismicPreviewClient.tsx"],"sourcesContent":["\"use client\"\n\nimport { cookie as prismicCookie } from \"@prismicio/client\"\nimport { useRouter } from \"next/navigation\"\nimport type { FC } from \"react\"\nimport { useEffect } from \"react\"\n\ntype PrismicPreviewClientProps = {\n\trepositoryName: string\n\tisDraftMode: boolean\n\tupdatePreviewURL?: string\n\texitPreviewURL?: string\n}\n\nexport const PrismicPreviewClient: FC<PrismicPreviewClientProps> = (props) => {\n\tconst {\n\t\trepositoryName,\n\t\tisDraftMode,\n\t\tupdatePreviewURL = \"/api/preview\",\n\t\texitPreviewURL = \"/api/exit-preview\",\n\t} = props\n\n\tconst { refresh } = useRouter()\n\n\tuseEffect(() => {\n\t\tconst controller = new AbortController()\n\t\tlet starting: Promise<void> | undefined\n\t\tlet startController: AbortController | undefined\n\t\tlet ending = false\n\n\t\twindow.addEventListener(\"prismicPreviewUpdate\", onUpdate, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\twindow.addEventListener(\"prismicPreviewEnd\", onEnd, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\n\t\tconst cookie = getPrismicPreviewCookie(window.document.cookie)\n\t\tconst cookieRepositoryName = cookie\n\t\t\t? (decodeURIComponent(cookie).match(/\"([^\"]+)\\.prismic\\.io\"/) || [])[1]\n\t\t\t: undefined\n\t\tconst hasCookieForRepository = cookieRepositoryName === repositoryName\n\n\t\t// Start the preview for preview share links. Previews from\n\t\t// share links do not go to the `updatePreviewURL` like a normal\n\t\t// preview.\n\t\tif (hasCookieForRepository && !isDraftMode) {\n\t\t\tstart()\n\t\t}\n\n\t\tfunction start() {\n\t\t\tif (starting) return\n\t\t\tstartController = new AbortController()\n\n\t\t\t// We check `opaqueredirect` because we don't care if\n\t\t\t// the redirect was successful or not. As long as it\n\t\t\t// redirects, we know the endpoint exists and draft mode\n\t\t\t// is active.\n\t\t\tstarting = globalThis\n\t\t\t\t.fetch(updatePreviewURL, {\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\tsignal: startController.signal,\n\t\t\t\t})\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (res.type !== \"opaqueredirect\") {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to start the preview using \"${updatePreviewURL}\". Does it exist?`,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// A soft refresh does not reset Next.js's not-found boundary\n\t\t\t\t\t// when an unpublished page enters Draft Mode at the same URL.\n\t\t\t\t\t// Only this initial activation navigates; active previews stay soft.\n\t\t\t\t\twindow.location.reload()\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// noop\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tstarting = undefined\n\t\t\t\t\tstartController = undefined\n\t\t\t\t})\n\t\t}\n\n\t\tfunction onUpdate(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tif (ending) return\n\t\t\tif (isDraftMode) {\n\t\t\t\trefresh()\n\t\t\t} else {\n\t\t\t\tstart()\n\t\t\t}\n\t\t}\n\n\t\tfunction onEnd(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tif (ending) return\n\t\t\tending = true\n\t\t\tstartController?.abort()\n\t\t\tglobalThis\n\t\t\t\t.fetch(exitPreviewURL, { signal: controller.signal })\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (!res.ok) {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to exit Preview Mode using the \"${exitPreviewURL}\" API endpoint. Does it exist?`,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\trefresh()\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// noop\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tending = false\n\t\t\t\t})\n\t\t}\n\n\t\treturn () => {\n\t\t\tcontroller.abort()\n\t\t\tstartController?.abort()\n\t\t}\n\t}, [repositoryName, isDraftMode, updatePreviewURL, exitPreviewURL, refresh])\n\n\treturn null\n}\n\n/**\n * Returns the value of a cookie from a given cookie store.\n *\n * @param cookieJar - The stringified cookie store from which to read the cookie.\n * @returns The value of the cookie, if it exists.\n */\nfunction getPrismicPreviewCookie(cookieJar: string): string | undefined {\n\tfunction readValue(value: string): string {\n\t\treturn value.replace(/%3B/g, \";\")\n\t}\n\n\tconst cookies = cookieJar.split(\"; \")\n\n\tlet value: string | undefined\n\n\tfor (const cookie of cookies) {\n\t\tconst parts = cookie.split(\"=\")\n\t\tconst name = readValue(parts[0]).replace(/%3D/g, \"=\")\n\n\t\tif (name === prismicCookie.preview) {\n\t\t\tvalue = readValue(parts.slice(1).join(\"=\"))\n\t\t\tcontinue\n\t\t}\n\t}\n\n\treturn value\n}\n"],"mappings":";;;;;;AAcA,MAAa,wBAAuD,UAAU;CAC7E,MAAM,EACL,gBACA,aACA,mBAAmB,gBACnB,iBAAiB,wBACd;CAEJ,MAAM,EAAE,aAAA,GAAA,mBAAA,YAAuB;AAE/B,EAAA,GAAA,MAAA,iBAAgB;EACf,MAAM,aAAa,IAAI,iBAAiB;EACxC,IAAI;EACJ,IAAI;EACJ,IAAI,SAAS;AAEb,SAAO,iBAAiB,wBAAwB,UAAU,EACzD,QAAQ,WAAW,QACnB,CAAC;AACF,SAAO,iBAAiB,qBAAqB,OAAO,EACnD,QAAQ,WAAW,QACnB,CAAC;EAEF,MAAM,SAAS,wBAAwB,OAAO,SAAS,OAAO;AAS9D,OAR6B,UACzB,mBAAmB,OAAO,CAAC,MAAM,yBAAyB,IAAI,EAAE,EAAE,KACnE,KAAA,OACqD,kBAK1B,CAAC,YAC9B,QAAO;EAGR,SAAS,QAAQ;AAChB,OAAI,SAAU;AACd,qBAAkB,IAAI,iBAAiB;AAMvC,cAAW,WACT,MAAM,kBAAkB;IACxB,UAAU;IACV,QAAQ,gBAAgB;IACxB,CAAC,CACD,MAAM,QAAQ;AACd,QAAI,IAAI,SAAS,kBAAkB;AAClC,aAAQ,MACP,yDAAyD,iBAAiB,mBAC1E;AAED;;AAMD,WAAO,SAAS,QAAQ;KACvB,CACD,YAAY,GAEX,CACD,cAAc;AACd,eAAW,KAAA;AACX,sBAAkB,KAAA;KACjB;;EAGJ,SAAS,SAAS,OAAc;AAC/B,SAAM,gBAAgB;AACtB,OAAI,OAAQ;AACZ,OAAI,YACH,UAAS;OAET,QAAO;;EAIT,SAAS,MAAM,OAAc;AAC5B,SAAM,gBAAgB;AACtB,OAAI,OAAQ;AACZ,YAAS;AACT,oBAAiB,OAAO;AACxB,cACE,MAAM,gBAAgB,EAAE,QAAQ,WAAW,QAAQ,CAAC,CACpD,MAAM,QAAQ;AACd,QAAI,CAAC,IAAI,IAAI;AACZ,aAAQ,MACP,6DAA6D,eAAe,gCAC5E;AAED;;AAGD,aAAS;KACR,CACD,YAAY,GAEX,CACD,cAAc;AACd,aAAS;KACR;;AAGJ,eAAa;AACZ,cAAW,OAAO;AAClB,oBAAiB,OAAO;;IAEvB;EAAC;EAAgB;EAAa;EAAkB;EAAgB;EAAQ,CAAC;AAE5E,QAAO;;;;;;;;AASR,SAAS,wBAAwB,WAAuC;CACvE,SAAS,UAAU,OAAuB;AACzC,SAAO,MAAM,QAAQ,QAAQ,IAAI;;CAGlC,MAAM,UAAU,UAAU,MAAM,KAAK;CAErC,IAAI;AAEJ,MAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,QAAQ,OAAO,MAAM,IAAI;AAG/B,MAFa,UAAU,MAAM,GAAG,CAAC,QAAQ,QAAQ,IAAI,KAExCA,kBAAAA,OAAc,SAAS;AACnC,WAAQ,UAAU,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;AAC3C;;;AAIF,QAAO"}
|
|
@@ -8,34 +8,55 @@ const PrismicPreviewClient = (props) => {
|
|
|
8
8
|
const { refresh } = useRouter();
|
|
9
9
|
useEffect(() => {
|
|
10
10
|
const controller = new AbortController();
|
|
11
|
+
let starting;
|
|
12
|
+
let startController;
|
|
13
|
+
let ending = false;
|
|
11
14
|
window.addEventListener("prismicPreviewUpdate", onUpdate, { signal: controller.signal });
|
|
12
15
|
window.addEventListener("prismicPreviewEnd", onEnd, { signal: controller.signal });
|
|
13
16
|
const cookie = getPrismicPreviewCookie(window.document.cookie);
|
|
14
|
-
if ((cookie ? (decodeURIComponent(cookie).match(/"([^"]+)\.prismic\.io"/) || [])[1] : void 0) === repositoryName && !isDraftMode)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
if ((cookie ? (decodeURIComponent(cookie).match(/"([^"]+)\.prismic\.io"/) || [])[1] : void 0) === repositoryName && !isDraftMode) start();
|
|
18
|
+
function start() {
|
|
19
|
+
if (starting) return;
|
|
20
|
+
startController = new AbortController();
|
|
21
|
+
starting = globalThis.fetch(updatePreviewURL, {
|
|
22
|
+
redirect: "manual",
|
|
23
|
+
signal: startController.signal
|
|
24
|
+
}).then((res) => {
|
|
25
|
+
if (res.type !== "opaqueredirect") {
|
|
26
|
+
console.error(`[<PrismicPreview>] Failed to start the preview using "${updatePreviewURL}". Does it exist?`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
window.location.reload();
|
|
30
|
+
}).catch(() => {}).finally(() => {
|
|
31
|
+
starting = void 0;
|
|
32
|
+
startController = void 0;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
24
35
|
function onUpdate(event) {
|
|
25
36
|
event.preventDefault();
|
|
26
|
-
|
|
37
|
+
if (ending) return;
|
|
38
|
+
if (isDraftMode) refresh();
|
|
39
|
+
else start();
|
|
27
40
|
}
|
|
28
41
|
function onEnd(event) {
|
|
29
42
|
event.preventDefault();
|
|
43
|
+
if (ending) return;
|
|
44
|
+
ending = true;
|
|
45
|
+
startController?.abort();
|
|
30
46
|
globalThis.fetch(exitPreviewURL, { signal: controller.signal }).then((res) => {
|
|
31
47
|
if (!res.ok) {
|
|
32
48
|
console.error(`[<PrismicPreview>] Failed to exit Preview Mode using the "${exitPreviewURL}" API endpoint. Does it exist?`);
|
|
33
49
|
return;
|
|
34
50
|
}
|
|
35
51
|
refresh();
|
|
36
|
-
}).catch(() => {})
|
|
52
|
+
}).catch(() => {}).finally(() => {
|
|
53
|
+
ending = false;
|
|
54
|
+
});
|
|
37
55
|
}
|
|
38
|
-
return () =>
|
|
56
|
+
return () => {
|
|
57
|
+
controller.abort();
|
|
58
|
+
startController?.abort();
|
|
59
|
+
};
|
|
39
60
|
}, [
|
|
40
61
|
repositoryName,
|
|
41
62
|
isDraftMode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrismicPreviewClient.js","names":["cookie","prismicCookie"],"sources":["../src/PrismicPreviewClient.tsx"],"sourcesContent":["\"use client\"\n\nimport { cookie as prismicCookie } from \"@prismicio/client\"\nimport { useRouter } from \"next/navigation\"\nimport type { FC } from \"react\"\nimport { useEffect } from \"react\"\n\ntype PrismicPreviewClientProps = {\n\trepositoryName: string\n\tisDraftMode: boolean\n\tupdatePreviewURL?: string\n\texitPreviewURL?: string\n}\n\nexport const PrismicPreviewClient: FC<PrismicPreviewClientProps> = (props) => {\n\tconst {\n\t\trepositoryName,\n\t\tisDraftMode,\n\t\tupdatePreviewURL = \"/api/preview\",\n\t\texitPreviewURL = \"/api/exit-preview\",\n\t} = props\n\n\tconst { refresh } = useRouter()\n\n\tuseEffect(() => {\n\t\tconst controller = new AbortController()\n\n\t\twindow.addEventListener(\"prismicPreviewUpdate\", onUpdate, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\twindow.addEventListener(\"prismicPreviewEnd\", onEnd, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\n\t\tconst cookie = getPrismicPreviewCookie(window.document.cookie)\n\t\tconst cookieRepositoryName = cookie\n\t\t\t? (decodeURIComponent(cookie).match(/\"([^\"]+)\\.prismic\\.io\"/) || [])[1]\n\t\t\t: undefined\n\t\tconst hasCookieForRepository = cookieRepositoryName === repositoryName\n\n\t\t// Start the preview for preview share links. Previews from\n\t\t// share links do not go to the `updatePreviewURL` like a normal\n\t\t// preview.\n\t\tif (hasCookieForRepository && !isDraftMode) {\n\t\t\t// We check `opaqueredirect` because we don't care if\n\t\t\t// the redirect was successful or not. As long as it\n\t\t\t// redirects, we know the endpoint exists and draft mode\n\t\t\t// is active.\n\t\t\
|
|
1
|
+
{"version":3,"file":"PrismicPreviewClient.js","names":["cookie","prismicCookie"],"sources":["../src/PrismicPreviewClient.tsx"],"sourcesContent":["\"use client\"\n\nimport { cookie as prismicCookie } from \"@prismicio/client\"\nimport { useRouter } from \"next/navigation\"\nimport type { FC } from \"react\"\nimport { useEffect } from \"react\"\n\ntype PrismicPreviewClientProps = {\n\trepositoryName: string\n\tisDraftMode: boolean\n\tupdatePreviewURL?: string\n\texitPreviewURL?: string\n}\n\nexport const PrismicPreviewClient: FC<PrismicPreviewClientProps> = (props) => {\n\tconst {\n\t\trepositoryName,\n\t\tisDraftMode,\n\t\tupdatePreviewURL = \"/api/preview\",\n\t\texitPreviewURL = \"/api/exit-preview\",\n\t} = props\n\n\tconst { refresh } = useRouter()\n\n\tuseEffect(() => {\n\t\tconst controller = new AbortController()\n\t\tlet starting: Promise<void> | undefined\n\t\tlet startController: AbortController | undefined\n\t\tlet ending = false\n\n\t\twindow.addEventListener(\"prismicPreviewUpdate\", onUpdate, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\twindow.addEventListener(\"prismicPreviewEnd\", onEnd, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\n\t\tconst cookie = getPrismicPreviewCookie(window.document.cookie)\n\t\tconst cookieRepositoryName = cookie\n\t\t\t? (decodeURIComponent(cookie).match(/\"([^\"]+)\\.prismic\\.io\"/) || [])[1]\n\t\t\t: undefined\n\t\tconst hasCookieForRepository = cookieRepositoryName === repositoryName\n\n\t\t// Start the preview for preview share links. Previews from\n\t\t// share links do not go to the `updatePreviewURL` like a normal\n\t\t// preview.\n\t\tif (hasCookieForRepository && !isDraftMode) {\n\t\t\tstart()\n\t\t}\n\n\t\tfunction start() {\n\t\t\tif (starting) return\n\t\t\tstartController = new AbortController()\n\n\t\t\t// We check `opaqueredirect` because we don't care if\n\t\t\t// the redirect was successful or not. As long as it\n\t\t\t// redirects, we know the endpoint exists and draft mode\n\t\t\t// is active.\n\t\t\tstarting = globalThis\n\t\t\t\t.fetch(updatePreviewURL, {\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\tsignal: startController.signal,\n\t\t\t\t})\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (res.type !== \"opaqueredirect\") {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to start the preview using \"${updatePreviewURL}\". Does it exist?`,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// A soft refresh does not reset Next.js's not-found boundary\n\t\t\t\t\t// when an unpublished page enters Draft Mode at the same URL.\n\t\t\t\t\t// Only this initial activation navigates; active previews stay soft.\n\t\t\t\t\twindow.location.reload()\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// noop\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tstarting = undefined\n\t\t\t\t\tstartController = undefined\n\t\t\t\t})\n\t\t}\n\n\t\tfunction onUpdate(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tif (ending) return\n\t\t\tif (isDraftMode) {\n\t\t\t\trefresh()\n\t\t\t} else {\n\t\t\t\tstart()\n\t\t\t}\n\t\t}\n\n\t\tfunction onEnd(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tif (ending) return\n\t\t\tending = true\n\t\t\tstartController?.abort()\n\t\t\tglobalThis\n\t\t\t\t.fetch(exitPreviewURL, { signal: controller.signal })\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (!res.ok) {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to exit Preview Mode using the \"${exitPreviewURL}\" API endpoint. Does it exist?`,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\trefresh()\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// noop\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tending = false\n\t\t\t\t})\n\t\t}\n\n\t\treturn () => {\n\t\t\tcontroller.abort()\n\t\t\tstartController?.abort()\n\t\t}\n\t}, [repositoryName, isDraftMode, updatePreviewURL, exitPreviewURL, refresh])\n\n\treturn null\n}\n\n/**\n * Returns the value of a cookie from a given cookie store.\n *\n * @param cookieJar - The stringified cookie store from which to read the cookie.\n * @returns The value of the cookie, if it exists.\n */\nfunction getPrismicPreviewCookie(cookieJar: string): string | undefined {\n\tfunction readValue(value: string): string {\n\t\treturn value.replace(/%3B/g, \";\")\n\t}\n\n\tconst cookies = cookieJar.split(\"; \")\n\n\tlet value: string | undefined\n\n\tfor (const cookie of cookies) {\n\t\tconst parts = cookie.split(\"=\")\n\t\tconst name = readValue(parts[0]).replace(/%3D/g, \"=\")\n\n\t\tif (name === prismicCookie.preview) {\n\t\t\tvalue = readValue(parts.slice(1).join(\"=\"))\n\t\t\tcontinue\n\t\t}\n\t}\n\n\treturn value\n}\n"],"mappings":";;;;;AAcA,MAAa,wBAAuD,UAAU;CAC7E,MAAM,EACL,gBACA,aACA,mBAAmB,gBACnB,iBAAiB,wBACd;CAEJ,MAAM,EAAE,YAAY,WAAW;AAE/B,iBAAgB;EACf,MAAM,aAAa,IAAI,iBAAiB;EACxC,IAAI;EACJ,IAAI;EACJ,IAAI,SAAS;AAEb,SAAO,iBAAiB,wBAAwB,UAAU,EACzD,QAAQ,WAAW,QACnB,CAAC;AACF,SAAO,iBAAiB,qBAAqB,OAAO,EACnD,QAAQ,WAAW,QACnB,CAAC;EAEF,MAAM,SAAS,wBAAwB,OAAO,SAAS,OAAO;AAS9D,OAR6B,UACzB,mBAAmB,OAAO,CAAC,MAAM,yBAAyB,IAAI,EAAE,EAAE,KACnE,KAAA,OACqD,kBAK1B,CAAC,YAC9B,QAAO;EAGR,SAAS,QAAQ;AAChB,OAAI,SAAU;AACd,qBAAkB,IAAI,iBAAiB;AAMvC,cAAW,WACT,MAAM,kBAAkB;IACxB,UAAU;IACV,QAAQ,gBAAgB;IACxB,CAAC,CACD,MAAM,QAAQ;AACd,QAAI,IAAI,SAAS,kBAAkB;AAClC,aAAQ,MACP,yDAAyD,iBAAiB,mBAC1E;AAED;;AAMD,WAAO,SAAS,QAAQ;KACvB,CACD,YAAY,GAEX,CACD,cAAc;AACd,eAAW,KAAA;AACX,sBAAkB,KAAA;KACjB;;EAGJ,SAAS,SAAS,OAAc;AAC/B,SAAM,gBAAgB;AACtB,OAAI,OAAQ;AACZ,OAAI,YACH,UAAS;OAET,QAAO;;EAIT,SAAS,MAAM,OAAc;AAC5B,SAAM,gBAAgB;AACtB,OAAI,OAAQ;AACZ,YAAS;AACT,oBAAiB,OAAO;AACxB,cACE,MAAM,gBAAgB,EAAE,QAAQ,WAAW,QAAQ,CAAC,CACpD,MAAM,QAAQ;AACd,QAAI,CAAC,IAAI,IAAI;AACZ,aAAQ,MACP,6DAA6D,eAAe,gCAC5E;AAED;;AAGD,aAAS;KACR,CACD,YAAY,GAEX,CACD,cAAc;AACd,aAAS;KACR;;AAGJ,eAAa;AACZ,cAAW,OAAO;AAClB,oBAAiB,OAAO;;IAEvB;EAAC;EAAgB;EAAa;EAAkB;EAAgB;EAAQ,CAAC;AAE5E,QAAO;;;;;;;;AASR,SAAS,wBAAwB,WAAuC;CACvE,SAAS,UAAU,OAAuB;AACzC,SAAO,MAAM,QAAQ,QAAQ,IAAI;;CAGlC,MAAM,UAAU,UAAU,MAAM,KAAK;CAErC,IAAI;AAEJ,MAAK,MAAMA,YAAU,SAAS;EAC7B,MAAM,QAAQA,SAAO,MAAM,IAAI;AAG/B,MAFa,UAAU,MAAM,GAAG,CAAC,QAAQ,QAAQ,IAAI,KAExCC,OAAc,SAAS;AACnC,WAAQ,UAAU,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;AAC3C;;;AAIF,QAAO"}
|
package/dist/getPreviewRef.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_previewRefFromCookie = require("./lib/previewRefFromCookie.cjs");
|
|
2
3
|
let _prismicio_client = require("@prismicio/client");
|
|
3
4
|
//#region src/getPreviewRef.ts
|
|
4
5
|
/**
|
|
@@ -29,8 +30,7 @@ async function getPreviewRef() {
|
|
|
29
30
|
if (!isDraftModeEnabled) return;
|
|
30
31
|
const cookie = (await cookies()).get(_prismicio_client.cookie.preview)?.value;
|
|
31
32
|
if (!cookie) return;
|
|
32
|
-
|
|
33
|
-
return cookie;
|
|
33
|
+
return require_previewRefFromCookie.previewRefFromCookie(cookie);
|
|
34
34
|
}
|
|
35
35
|
//#endregion
|
|
36
36
|
exports.getPreviewRef = getPreviewRef;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPreviewRef.cjs","names":["prismicCookie"],"sources":["../src/getPreviewRef.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\n/**\n * Reads the Prismic preview ref for the current request when an active preview session exists.\n *\n * This is the read-side counterpart to `redirectToPreviewURL`, which writes the preview cookie. Use\n * it with Next.js Cache Components to read the ref _outside_ a cached function and pass it _in_ as\n * an argument so it becomes part of the cache key:\n *\n * @example\n * \t;```typescript\n * \timport { getPreviewRef } from \"@prismicio/next\"\n *\n * \tconst page = await fetchPage(uid, await getPreviewRef())\n * \t```\n *\n * @returns The active preview ref, or `undefined` if no preview session is active.\n * @experimental\n */\nexport async function getPreviewRef(): Promise<string | undefined> {\n\t// Need this to avoid the following Next.js build-time error:\n\t// You're importing a component that needs next/headers. That only works\n\t// in a Server Component which is not supported in the pages/ directory.\n\tconst { cookies, draftMode } = await import(\"next/headers\")\n\n\tlet isDraftModeEnabled = false\n\ttry {\n\t\tisDraftModeEnabled = (await draftMode()).isEnabled\n\t} catch {\n\t\t// `draftMode()` may have been called in a place that\n\t\t// does not have access to its async storage. This\n\t\t// occurs in places like `generateStaticParams()`. We\n\t\t// can ignore this case.\n\t\treturn\n\t}\n\tif (!isDraftModeEnabled) {\n\t\treturn\n\t}\n\n\tconst cookie = (await cookies()).get(prismicCookie.preview)?.value\n\tif (!cookie) {\n\t\treturn\n\t}\n\n\
|
|
1
|
+
{"version":3,"file":"getPreviewRef.cjs","names":["prismicCookie","previewRefFromCookie"],"sources":["../src/getPreviewRef.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\nimport { previewRefFromCookie } from \"./lib/previewRefFromCookie\"\n\n/**\n * Reads the Prismic preview ref for the current request when an active preview session exists.\n *\n * This is the read-side counterpart to `redirectToPreviewURL`, which writes the preview cookie. Use\n * it with Next.js Cache Components to read the ref _outside_ a cached function and pass it _in_ as\n * an argument so it becomes part of the cache key:\n *\n * @example\n * \t;```typescript\n * \timport { getPreviewRef } from \"@prismicio/next\"\n *\n * \tconst page = await fetchPage(uid, await getPreviewRef())\n * \t```\n *\n * @returns The active preview ref, or `undefined` if no preview session is active.\n * @experimental\n */\nexport async function getPreviewRef(): Promise<string | undefined> {\n\t// Need this to avoid the following Next.js build-time error:\n\t// You're importing a component that needs next/headers. That only works\n\t// in a Server Component which is not supported in the pages/ directory.\n\tconst { cookies, draftMode } = await import(\"next/headers\")\n\n\tlet isDraftModeEnabled = false\n\ttry {\n\t\tisDraftModeEnabled = (await draftMode()).isEnabled\n\t} catch {\n\t\t// `draftMode()` may have been called in a place that\n\t\t// does not have access to its async storage. This\n\t\t// occurs in places like `generateStaticParams()`. We\n\t\t// can ignore this case.\n\t\treturn\n\t}\n\tif (!isDraftModeEnabled) {\n\t\treturn\n\t}\n\n\tconst cookie = (await cookies()).get(prismicCookie.preview)?.value\n\tif (!cookie) {\n\t\treturn\n\t}\n\n\t// Draft Mode gates preview reads. The cookie may be a raw token or the\n\t// toolbar jar (`{ \"<repo>.prismic.io\": { preview } }`). Only `preview` is a\n\t// Content API ref; the jar string is not.\n\treturn previewRefFromCookie(cookie)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqBA,eAAsB,gBAA6C;CAIlE,MAAM,EAAE,SAAS,cAAc,MAAM,OAAO;CAE5C,IAAI,qBAAqB;AACzB,KAAI;AACH,wBAAsB,MAAM,WAAW,EAAE;SAClC;AAKP;;AAED,KAAI,CAAC,mBACJ;CAGD,MAAM,UAAU,MAAM,SAAS,EAAE,IAAIA,kBAAAA,OAAc,QAAQ,EAAE;AAC7D,KAAI,CAAC,OACJ;AAMD,QAAOC,6BAAAA,qBAAqB,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPreviewRef.d.cts","names":[],"sources":["../src/getPreviewRef.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"getPreviewRef.d.cts","names":[],"sources":["../src/getPreviewRef.ts"],"mappings":";;AAqBA;;;;;;;;;;;;;;;;iBAAsB,aAAA,CAAA,GAAiB,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPreviewRef.d.ts","names":[],"sources":["../src/getPreviewRef.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"getPreviewRef.d.ts","names":[],"sources":["../src/getPreviewRef.ts"],"mappings":";;AAqBA;;;;;;;;;;;;;;;;iBAAsB,aAAA,CAAA,GAAiB,OAAA"}
|
package/dist/getPreviewRef.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { previewRefFromCookie } from "./lib/previewRefFromCookie.js";
|
|
1
2
|
import { cookie } from "@prismicio/client";
|
|
2
3
|
//#region src/getPreviewRef.ts
|
|
3
4
|
/**
|
|
@@ -28,8 +29,7 @@ async function getPreviewRef() {
|
|
|
28
29
|
if (!isDraftModeEnabled) return;
|
|
29
30
|
const cookie$1 = (await cookies()).get(cookie.preview)?.value;
|
|
30
31
|
if (!cookie$1) return;
|
|
31
|
-
|
|
32
|
-
return cookie$1;
|
|
32
|
+
return previewRefFromCookie(cookie$1);
|
|
33
33
|
}
|
|
34
34
|
//#endregion
|
|
35
35
|
export { getPreviewRef };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPreviewRef.js","names":["cookie","prismicCookie"],"sources":["../src/getPreviewRef.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\n/**\n * Reads the Prismic preview ref for the current request when an active preview session exists.\n *\n * This is the read-side counterpart to `redirectToPreviewURL`, which writes the preview cookie. Use\n * it with Next.js Cache Components to read the ref _outside_ a cached function and pass it _in_ as\n * an argument so it becomes part of the cache key:\n *\n * @example\n * \t;```typescript\n * \timport { getPreviewRef } from \"@prismicio/next\"\n *\n * \tconst page = await fetchPage(uid, await getPreviewRef())\n * \t```\n *\n * @returns The active preview ref, or `undefined` if no preview session is active.\n * @experimental\n */\nexport async function getPreviewRef(): Promise<string | undefined> {\n\t// Need this to avoid the following Next.js build-time error:\n\t// You're importing a component that needs next/headers. That only works\n\t// in a Server Component which is not supported in the pages/ directory.\n\tconst { cookies, draftMode } = await import(\"next/headers\")\n\n\tlet isDraftModeEnabled = false\n\ttry {\n\t\tisDraftModeEnabled = (await draftMode()).isEnabled\n\t} catch {\n\t\t// `draftMode()` may have been called in a place that\n\t\t// does not have access to its async storage. This\n\t\t// occurs in places like `generateStaticParams()`. We\n\t\t// can ignore this case.\n\t\treturn\n\t}\n\tif (!isDraftModeEnabled) {\n\t\treturn\n\t}\n\n\tconst cookie = (await cookies()).get(prismicCookie.preview)?.value\n\tif (!cookie) {\n\t\treturn\n\t}\n\n\
|
|
1
|
+
{"version":3,"file":"getPreviewRef.js","names":["cookie","prismicCookie"],"sources":["../src/getPreviewRef.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\nimport { previewRefFromCookie } from \"./lib/previewRefFromCookie\"\n\n/**\n * Reads the Prismic preview ref for the current request when an active preview session exists.\n *\n * This is the read-side counterpart to `redirectToPreviewURL`, which writes the preview cookie. Use\n * it with Next.js Cache Components to read the ref _outside_ a cached function and pass it _in_ as\n * an argument so it becomes part of the cache key:\n *\n * @example\n * \t;```typescript\n * \timport { getPreviewRef } from \"@prismicio/next\"\n *\n * \tconst page = await fetchPage(uid, await getPreviewRef())\n * \t```\n *\n * @returns The active preview ref, or `undefined` if no preview session is active.\n * @experimental\n */\nexport async function getPreviewRef(): Promise<string | undefined> {\n\t// Need this to avoid the following Next.js build-time error:\n\t// You're importing a component that needs next/headers. That only works\n\t// in a Server Component which is not supported in the pages/ directory.\n\tconst { cookies, draftMode } = await import(\"next/headers\")\n\n\tlet isDraftModeEnabled = false\n\ttry {\n\t\tisDraftModeEnabled = (await draftMode()).isEnabled\n\t} catch {\n\t\t// `draftMode()` may have been called in a place that\n\t\t// does not have access to its async storage. This\n\t\t// occurs in places like `generateStaticParams()`. We\n\t\t// can ignore this case.\n\t\treturn\n\t}\n\tif (!isDraftModeEnabled) {\n\t\treturn\n\t}\n\n\tconst cookie = (await cookies()).get(prismicCookie.preview)?.value\n\tif (!cookie) {\n\t\treturn\n\t}\n\n\t// Draft Mode gates preview reads. The cookie may be a raw token or the\n\t// toolbar jar (`{ \"<repo>.prismic.io\": { preview } }`). Only `preview` is a\n\t// Content API ref; the jar string is not.\n\treturn previewRefFromCookie(cookie)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,eAAsB,gBAA6C;CAIlE,MAAM,EAAE,SAAS,cAAc,MAAM,OAAO;CAE5C,IAAI,qBAAqB;AACzB,KAAI;AACH,wBAAsB,MAAM,WAAW,EAAE;SAClC;AAKP;;AAED,KAAI,CAAC,mBACJ;CAGD,MAAMA,YAAU,MAAM,SAAS,EAAE,IAAIC,OAAc,QAAQ,EAAE;AAC7D,KAAI,CAACD,SACJ;AAMD,QAAO,qBAAqBA,SAAO"}
|
|
@@ -20,8 +20,13 @@ function expiredDraftModeCookieHeaders() {
|
|
|
20
20
|
const name = "__prerender_bypass";
|
|
21
21
|
return [`${name}=; Path=/; ${expires}; SameSite=Lax; HttpOnly`, `${name}=; Path=/; ${expires}; SameSite=None; Secure; HttpOnly`];
|
|
22
22
|
}
|
|
23
|
+
/** Expire Pages Router's signed preview data in development and production. */
|
|
24
|
+
function expiredPreviewDataCookieHeaders() {
|
|
25
|
+
return expiredPreviewCookieHeaders("__next_preview_data").map((header) => `${header}; HttpOnly`);
|
|
26
|
+
}
|
|
23
27
|
//#endregion
|
|
24
28
|
exports.expiredDraftModeCookieHeaders = expiredDraftModeCookieHeaders;
|
|
25
29
|
exports.expiredPreviewCookieHeaders = expiredPreviewCookieHeaders;
|
|
30
|
+
exports.expiredPreviewDataCookieHeaders = expiredPreviewDataCookieHeaders;
|
|
26
31
|
|
|
27
32
|
//# sourceMappingURL=expiredPreviewCookies.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expiredPreviewCookies.cjs","names":["prismicCookie"],"sources":["../../src/lib/expiredPreviewCookies.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\nconst epoch = new Date(0)\n\nfunction expiresAttr(): string {\n\treturn `Expires=${epoch.toUTCString()}`\n}\n\n/** Expired `Set-Cookie` values for both leftover `io.prismic.preview` shapes. */\nexport function expiredPreviewCookieHeaders(name = prismicCookie.preview): string[] {\n\tconst expires = expiresAttr()\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure`,\n\t]\n}\n\n/**\n * Expired `Set-Cookie` values for the App Router draft-mode cookie that `draftMode().disable()`\n * would clear. Next sets `__prerender_bypass` as Lax (not Secure) in development and SameSite=None;\n * Secure in production.\n */\nexport function expiredDraftModeCookieHeaders(): string[] {\n\tconst expires = expiresAttr()\n\tconst name = \"__prerender_bypass\"\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax; HttpOnly`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure; HttpOnly`,\n\t]\n}\n"],"mappings":";;;AAEA,MAAM,wBAAQ,IAAI,KAAK,EAAE;AAEzB,SAAS,cAAsB;AAC9B,QAAO,WAAW,MAAM,aAAa;;;AAItC,SAAgB,4BAA4B,OAAOA,kBAAAA,OAAc,SAAmB;CACnF,MAAM,UAAU,aAAa;AAE7B,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,iBAC7B,GAAG,KAAK,aAAa,QAAQ,yBAC7B;;;;;;;AAQF,SAAgB,gCAA0C;CACzD,MAAM,UAAU,aAAa;CAC7B,MAAM,OAAO;AAEb,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,2BAC7B,GAAG,KAAK,aAAa,QAAQ,mCAC7B"}
|
|
1
|
+
{"version":3,"file":"expiredPreviewCookies.cjs","names":["prismicCookie"],"sources":["../../src/lib/expiredPreviewCookies.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\nconst epoch = new Date(0)\n\nfunction expiresAttr(): string {\n\treturn `Expires=${epoch.toUTCString()}`\n}\n\n/** Expired `Set-Cookie` values for both leftover `io.prismic.preview` shapes. */\nexport function expiredPreviewCookieHeaders(name = prismicCookie.preview): string[] {\n\tconst expires = expiresAttr()\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure`,\n\t]\n}\n\n/**\n * Expired `Set-Cookie` values for the App Router draft-mode cookie that `draftMode().disable()`\n * would clear. Next sets `__prerender_bypass` as Lax (not Secure) in development and SameSite=None;\n * Secure in production.\n */\nexport function expiredDraftModeCookieHeaders(): string[] {\n\tconst expires = expiresAttr()\n\tconst name = \"__prerender_bypass\"\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax; HttpOnly`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure; HttpOnly`,\n\t]\n}\n\n/** Expire Pages Router's signed preview data in development and production. */\nexport function expiredPreviewDataCookieHeaders(): string[] {\n\treturn expiredPreviewCookieHeaders(\"__next_preview_data\").map((header) => `${header}; HttpOnly`)\n}\n"],"mappings":";;;AAEA,MAAM,wBAAQ,IAAI,KAAK,EAAE;AAEzB,SAAS,cAAsB;AAC9B,QAAO,WAAW,MAAM,aAAa;;;AAItC,SAAgB,4BAA4B,OAAOA,kBAAAA,OAAc,SAAmB;CACnF,MAAM,UAAU,aAAa;AAE7B,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,iBAC7B,GAAG,KAAK,aAAa,QAAQ,yBAC7B;;;;;;;AAQF,SAAgB,gCAA0C;CACzD,MAAM,UAAU,aAAa;CAC7B,MAAM,OAAO;AAEb,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,2BAC7B,GAAG,KAAK,aAAa,QAAQ,mCAC7B;;;AAIF,SAAgB,kCAA4C;AAC3D,QAAO,4BAA4B,sBAAsB,CAAC,KAAK,WAAW,GAAG,OAAO,YAAY"}
|
|
@@ -19,7 +19,11 @@ function expiredDraftModeCookieHeaders() {
|
|
|
19
19
|
const name = "__prerender_bypass";
|
|
20
20
|
return [`${name}=; Path=/; ${expires}; SameSite=Lax; HttpOnly`, `${name}=; Path=/; ${expires}; SameSite=None; Secure; HttpOnly`];
|
|
21
21
|
}
|
|
22
|
+
/** Expire Pages Router's signed preview data in development and production. */
|
|
23
|
+
function expiredPreviewDataCookieHeaders() {
|
|
24
|
+
return expiredPreviewCookieHeaders("__next_preview_data").map((header) => `${header}; HttpOnly`);
|
|
25
|
+
}
|
|
22
26
|
//#endregion
|
|
23
|
-
export { expiredDraftModeCookieHeaders, expiredPreviewCookieHeaders };
|
|
27
|
+
export { expiredDraftModeCookieHeaders, expiredPreviewCookieHeaders, expiredPreviewDataCookieHeaders };
|
|
24
28
|
|
|
25
29
|
//# sourceMappingURL=expiredPreviewCookies.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expiredPreviewCookies.js","names":["prismicCookie"],"sources":["../../src/lib/expiredPreviewCookies.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\nconst epoch = new Date(0)\n\nfunction expiresAttr(): string {\n\treturn `Expires=${epoch.toUTCString()}`\n}\n\n/** Expired `Set-Cookie` values for both leftover `io.prismic.preview` shapes. */\nexport function expiredPreviewCookieHeaders(name = prismicCookie.preview): string[] {\n\tconst expires = expiresAttr()\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure`,\n\t]\n}\n\n/**\n * Expired `Set-Cookie` values for the App Router draft-mode cookie that `draftMode().disable()`\n * would clear. Next sets `__prerender_bypass` as Lax (not Secure) in development and SameSite=None;\n * Secure in production.\n */\nexport function expiredDraftModeCookieHeaders(): string[] {\n\tconst expires = expiresAttr()\n\tconst name = \"__prerender_bypass\"\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax; HttpOnly`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure; HttpOnly`,\n\t]\n}\n"],"mappings":";;AAEA,MAAM,wBAAQ,IAAI,KAAK,EAAE;AAEzB,SAAS,cAAsB;AAC9B,QAAO,WAAW,MAAM,aAAa;;;AAItC,SAAgB,4BAA4B,OAAOA,OAAc,SAAmB;CACnF,MAAM,UAAU,aAAa;AAE7B,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,iBAC7B,GAAG,KAAK,aAAa,QAAQ,yBAC7B;;;;;;;AAQF,SAAgB,gCAA0C;CACzD,MAAM,UAAU,aAAa;CAC7B,MAAM,OAAO;AAEb,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,2BAC7B,GAAG,KAAK,aAAa,QAAQ,mCAC7B"}
|
|
1
|
+
{"version":3,"file":"expiredPreviewCookies.js","names":["prismicCookie"],"sources":["../../src/lib/expiredPreviewCookies.ts"],"sourcesContent":["import { cookie as prismicCookie } from \"@prismicio/client\"\n\nconst epoch = new Date(0)\n\nfunction expiresAttr(): string {\n\treturn `Expires=${epoch.toUTCString()}`\n}\n\n/** Expired `Set-Cookie` values for both leftover `io.prismic.preview` shapes. */\nexport function expiredPreviewCookieHeaders(name = prismicCookie.preview): string[] {\n\tconst expires = expiresAttr()\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure`,\n\t]\n}\n\n/**\n * Expired `Set-Cookie` values for the App Router draft-mode cookie that `draftMode().disable()`\n * would clear. Next sets `__prerender_bypass` as Lax (not Secure) in development and SameSite=None;\n * Secure in production.\n */\nexport function expiredDraftModeCookieHeaders(): string[] {\n\tconst expires = expiresAttr()\n\tconst name = \"__prerender_bypass\"\n\n\treturn [\n\t\t`${name}=; Path=/; ${expires}; SameSite=Lax; HttpOnly`,\n\t\t`${name}=; Path=/; ${expires}; SameSite=None; Secure; HttpOnly`,\n\t]\n}\n\n/** Expire Pages Router's signed preview data in development and production. */\nexport function expiredPreviewDataCookieHeaders(): string[] {\n\treturn expiredPreviewCookieHeaders(\"__next_preview_data\").map((header) => `${header}; HttpOnly`)\n}\n"],"mappings":";;AAEA,MAAM,wBAAQ,IAAI,KAAK,EAAE;AAEzB,SAAS,cAAsB;AAC9B,QAAO,WAAW,MAAM,aAAa;;;AAItC,SAAgB,4BAA4B,OAAOA,OAAc,SAAmB;CACnF,MAAM,UAAU,aAAa;AAE7B,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,iBAC7B,GAAG,KAAK,aAAa,QAAQ,yBAC7B;;;;;;;AAQF,SAAgB,gCAA0C;CACzD,MAAM,UAAU,aAAa;CAC7B,MAAM,OAAO;AAEb,QAAO,CACN,GAAG,KAAK,aAAa,QAAQ,2BAC7B,GAAG,KAAK,aAAa,QAAQ,mCAC7B;;;AAIF,SAAgB,kCAA4C;AAC3D,QAAO,4BAA4B,sBAAsB,CAAC,KAAK,WAAW,GAAG,OAAO,YAAY"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/lib/previewRefFromCookie.ts
|
|
2
|
+
/**
|
|
3
|
+
* Unwraps `io.prismic.preview` to a Content API ref.
|
|
4
|
+
*
|
|
5
|
+
* After toolbar `PreviewCookie.sync` / `upsertPreviewForDomain`, the cookie is
|
|
6
|
+
* `{ [domain]: { preview: string } }`. Returning that jar makes `enableAutoPreviews`
|
|
7
|
+
* / Cache Components send a non-ref (ParsingError / 404). A jar with more than one
|
|
8
|
+
* repository `preview` is ambiguous and is ignored.
|
|
9
|
+
*/
|
|
10
|
+
function previewRefFromCookie(cookie) {
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(cookie);
|
|
13
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return;
|
|
14
|
+
const previewRefs = [];
|
|
15
|
+
for (const value of Object.values(parsed)) if (value !== null && typeof value === "object" && !Array.isArray(value) && "preview" in value && typeof value.preview === "string") previewRefs.push(value.preview);
|
|
16
|
+
return previewRefs.length === 1 ? previewRefs[0] : void 0;
|
|
17
|
+
} catch {
|
|
18
|
+
return cookie;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
exports.previewRefFromCookie = previewRefFromCookie;
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=previewRefFromCookie.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"previewRefFromCookie.cjs","names":[],"sources":["../../src/lib/previewRefFromCookie.ts"],"sourcesContent":["/**\n * Unwraps `io.prismic.preview` to a Content API ref.\n *\n * After toolbar `PreviewCookie.sync` / `upsertPreviewForDomain`, the cookie is\n * `{ [domain]: { preview: string } }`. Returning that jar makes `enableAutoPreviews`\n * / Cache Components send a non-ref (ParsingError / 404). A jar with more than one\n * repository `preview` is ambiguous and is ignored.\n */\nexport function previewRefFromCookie(cookie: string): string | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(cookie)\n\t\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\treturn\n\t\t}\n\n\t\tconst previewRefs: string[] = []\n\t\tfor (const value of Object.values(parsed)) {\n\t\t\tif (\n\t\t\t\tvalue !== null &&\n\t\t\t\ttypeof value === \"object\" &&\n\t\t\t\t!Array.isArray(value) &&\n\t\t\t\t\"preview\" in value &&\n\t\t\t\ttypeof value.preview === \"string\"\n\t\t\t) {\n\t\t\t\tpreviewRefs.push(value.preview)\n\t\t\t}\n\t\t}\n\n\t\treturn previewRefs.length === 1 ? previewRefs[0] : undefined\n\t} catch {\n\t\treturn cookie\n\t}\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,qBAAqB,QAAoC;AACxE,KAAI;EACH,MAAM,SAAkB,KAAK,MAAM,OAAO;AAC1C,MAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,CACzE;EAGD,MAAM,cAAwB,EAAE;AAChC,OAAK,MAAM,SAAS,OAAO,OAAO,OAAO,CACxC,KACC,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,MAAM,IACrB,aAAa,SACb,OAAO,MAAM,YAAY,SAEzB,aAAY,KAAK,MAAM,QAAQ;AAIjC,SAAO,YAAY,WAAW,IAAI,YAAY,KAAK,KAAA;SAC5C;AACP,SAAO"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/lib/previewRefFromCookie.ts
|
|
2
|
+
/**
|
|
3
|
+
* Unwraps `io.prismic.preview` to a Content API ref.
|
|
4
|
+
*
|
|
5
|
+
* After toolbar `PreviewCookie.sync` / `upsertPreviewForDomain`, the cookie is
|
|
6
|
+
* `{ [domain]: { preview: string } }`. Returning that jar makes `enableAutoPreviews`
|
|
7
|
+
* / Cache Components send a non-ref (ParsingError / 404). A jar with more than one
|
|
8
|
+
* repository `preview` is ambiguous and is ignored.
|
|
9
|
+
*/
|
|
10
|
+
function previewRefFromCookie(cookie) {
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(cookie);
|
|
13
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return;
|
|
14
|
+
const previewRefs = [];
|
|
15
|
+
for (const value of Object.values(parsed)) if (value !== null && typeof value === "object" && !Array.isArray(value) && "preview" in value && typeof value.preview === "string") previewRefs.push(value.preview);
|
|
16
|
+
return previewRefs.length === 1 ? previewRefs[0] : void 0;
|
|
17
|
+
} catch {
|
|
18
|
+
return cookie;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { previewRefFromCookie };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=previewRefFromCookie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"previewRefFromCookie.js","names":[],"sources":["../../src/lib/previewRefFromCookie.ts"],"sourcesContent":["/**\n * Unwraps `io.prismic.preview` to a Content API ref.\n *\n * After toolbar `PreviewCookie.sync` / `upsertPreviewForDomain`, the cookie is\n * `{ [domain]: { preview: string } }`. Returning that jar makes `enableAutoPreviews`\n * / Cache Components send a non-ref (ParsingError / 404). A jar with more than one\n * repository `preview` is ambiguous and is ignored.\n */\nexport function previewRefFromCookie(cookie: string): string | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(cookie)\n\t\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\treturn\n\t\t}\n\n\t\tconst previewRefs: string[] = []\n\t\tfor (const value of Object.values(parsed)) {\n\t\t\tif (\n\t\t\t\tvalue !== null &&\n\t\t\t\ttypeof value === \"object\" &&\n\t\t\t\t!Array.isArray(value) &&\n\t\t\t\t\"preview\" in value &&\n\t\t\t\ttypeof value.preview === \"string\"\n\t\t\t) {\n\t\t\t\tpreviewRefs.push(value.preview)\n\t\t\t}\n\t\t}\n\n\t\treturn previewRefs.length === 1 ? previewRefs[0] : undefined\n\t} catch {\n\t\treturn cookie\n\t}\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,qBAAqB,QAAoC;AACxE,KAAI;EACH,MAAM,SAAkB,KAAK,MAAM,OAAO;AAC1C,MAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,CACzE;EAGD,MAAM,cAAwB,EAAE;AAChC,OAAK,MAAM,SAAS,OAAO,OAAO,OAAO,CACxC,KACC,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,MAAM,IACrB,aAAa,SACb,OAAO,MAAM,YAAY,SAEzB,aAAY,KAAK,MAAM,QAAQ;AAIjC,SAAO,YAAY,WAAW,IAAI,YAAY,KAAK,KAAA;SAC5C;AACP,SAAO"}
|
package/dist/package.cjs
CHANGED
package/dist/package.js
CHANGED
|
@@ -20,39 +20,63 @@ const PrismicPreview = (props) => {
|
|
|
20
20
|
const toolbarSrc = (0, _prismicio_client.getToolbarSrc)(repositoryName);
|
|
21
21
|
(0, react.useEffect)(() => {
|
|
22
22
|
const controller = new AbortController();
|
|
23
|
+
let starting;
|
|
24
|
+
let startController;
|
|
25
|
+
let updateRequested = false;
|
|
26
|
+
let ending = false;
|
|
23
27
|
window.addEventListener("prismicPreviewUpdate", onUpdate, { signal: controller.signal });
|
|
24
28
|
window.addEventListener("prismicPreviewEnd", onEnd, { signal: controller.signal });
|
|
25
29
|
if (window.location.href.startsWith(window.location.origin + router.basePath) && getPreviewCookieRepositoryName() === repositoryName && !router.isPreview) start();
|
|
26
30
|
function onEnd(event) {
|
|
27
31
|
event.preventDefault();
|
|
32
|
+
if (ending) return;
|
|
33
|
+
ending = true;
|
|
34
|
+
updateRequested = false;
|
|
35
|
+
startController?.abort();
|
|
28
36
|
fetch(router.basePath + exitPreviewURL, { signal: controller.signal }).then((res) => {
|
|
29
37
|
if (!res.ok) {
|
|
30
38
|
console.error(`[<PrismicPreview>] Failed to exit Preview Mode using the "${exitPreviewURL}" API endpoint. Does it exist?`);
|
|
31
39
|
return;
|
|
32
40
|
}
|
|
33
41
|
refresh();
|
|
34
|
-
}).catch(() => {})
|
|
42
|
+
}).catch(() => {}).finally(() => {
|
|
43
|
+
ending = false;
|
|
44
|
+
});
|
|
35
45
|
}
|
|
36
46
|
function onUpdate(event) {
|
|
37
47
|
event.preventDefault();
|
|
48
|
+
if (ending) return;
|
|
38
49
|
start();
|
|
39
50
|
}
|
|
40
51
|
function start() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
updateRequested = true;
|
|
53
|
+
if (starting) return;
|
|
54
|
+
const requestController = new AbortController();
|
|
55
|
+
startController = requestController;
|
|
56
|
+
starting = (async () => {
|
|
57
|
+
do {
|
|
58
|
+
updateRequested = false;
|
|
59
|
+
if ((await fetch(router.basePath + updatePreviewURL, {
|
|
60
|
+
redirect: "manual",
|
|
61
|
+
signal: requestController.signal
|
|
62
|
+
})).type !== "opaqueredirect") {
|
|
63
|
+
console.error(`[<PrismicPreview>] Failed to start or update the preview using "${updatePreviewURL}". Does it exist?`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
} while (updateRequested && !requestController.signal.aborted);
|
|
67
|
+
if (!requestController.signal.aborted) refresh();
|
|
68
|
+
})().catch(() => {}).finally(() => {
|
|
69
|
+
starting = void 0;
|
|
70
|
+
startController = void 0;
|
|
71
|
+
});
|
|
51
72
|
}
|
|
52
73
|
function refresh() {
|
|
53
74
|
router.replace(router.asPath, void 0, { scroll: false });
|
|
54
75
|
}
|
|
55
|
-
return () =>
|
|
76
|
+
return () => {
|
|
77
|
+
controller.abort();
|
|
78
|
+
startController?.abort();
|
|
79
|
+
};
|
|
56
80
|
}, [
|
|
57
81
|
exitPreviewURL,
|
|
58
82
|
updatePreviewURL,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrismicPreview.cjs","names":["Script","prismicCookie"],"sources":["../../src/pages/PrismicPreview.tsx"],"sourcesContent":["import { getToolbarSrc, cookie as prismicCookie } from \"@prismicio/client\"\nimport { useRouter } from \"next/router\"\nimport Script from \"next/script\"\nimport type { FC } from \"react\"\nimport { type ReactNode, useEffect } from \"react\"\n\n/** Props for `<PrismicPreview>`. */\nexport type PrismicPreviewProps = {\n\t/**\n\t * The name of your Prismic repository. A Prismic Toolbar will be registered using this\n\t * repository.\n\t */\n\trepositoryName: string\n\n\t/**\n\t * The URL of your app's Prismic preview endpoint (default: `/api/preview`). This URL will be\n\t * fetched on preview update events.\n\t */\n\tupdatePreviewURL?: string\n\n\t/**\n\t * The URL of your app's exit preview endpoint (default: `/api/exit-preview`). This URL will be\n\t * fetched on preview exit events.\n\t */\n\texitPreviewURL?: string\n\n\t/** Children to render adjacent to the Prismic Toolbar. */\n\tchildren?: ReactNode\n}\n\n/**\n * React component that sets up Prismic Previews using the Prismic Toolbar. When the Prismic Toolbar\n * send events to the browser, such as on preview updates and exiting, this component will\n * automatically refresh the page with the changes.\n *\n * This component can be wrapped around your app or added anywhere in your app's tree. It must be\n * rendered on every page.\n */\nexport const PrismicPreview: FC<PrismicPreviewProps> = (props) => {\n\tconst {\n\t\trepositoryName,\n\t\tupdatePreviewURL = \"/api/preview\",\n\t\texitPreviewURL = \"/api/exit-preview\",\n\t\tchildren,\n\t} = props\n\n\tconst router = useRouter()\n\n\tconst toolbarSrc = getToolbarSrc(repositoryName)\n\n\tuseEffect(() => {\n\t\tconst controller = new AbortController()\n\n\t\twindow.addEventListener(\"prismicPreviewUpdate\", onUpdate, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\twindow.addEventListener(\"prismicPreviewEnd\", onEnd, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\n\t\t// Start the preview for preview share links. Previews from\n\t\t// share links do not go to the `updatePreviewURL` like a normal\n\t\t// preview.\n\t\t//\n\t\t// We check that the current URL is a descendant of the base\n\t\t// path to prevent infinite refrehes.\n\t\tif (\n\t\t\twindow.location.href.startsWith(window.location.origin + router.basePath) &&\n\t\t\tgetPreviewCookieRepositoryName() === repositoryName &&\n\t\t\t!router.isPreview\n\t\t) {\n\t\t\tstart()\n\t\t}\n\n\t\tfunction onEnd(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tfetch(router.basePath + exitPreviewURL, { signal: controller.signal })\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (!res.ok) {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to exit Preview Mode using the \"${exitPreviewURL}\" API endpoint. Does it exist?`,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\trefresh()\n\t\t\t\t})\n\t\t\t\t.catch(() => {})\n\t\t}\n\n\t\tfunction onUpdate(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tstart()\n\t\t}\n\n\t\tfunction start() {\n\t\t\t// We check `opaqueredirect` because we don't care if\n\t\t\t// the redirect was successful or not. As long as it\n\t\t\t// redirects, we know the endpoint exists and at least\n\t\t\t// attempted to set preview data.\n\t\t\
|
|
1
|
+
{"version":3,"file":"PrismicPreview.cjs","names":["Script","prismicCookie"],"sources":["../../src/pages/PrismicPreview.tsx"],"sourcesContent":["import { getToolbarSrc, cookie as prismicCookie } from \"@prismicio/client\"\nimport { useRouter } from \"next/router\"\nimport Script from \"next/script\"\nimport type { FC } from \"react\"\nimport { type ReactNode, useEffect } from \"react\"\n\n/** Props for `<PrismicPreview>`. */\nexport type PrismicPreviewProps = {\n\t/**\n\t * The name of your Prismic repository. A Prismic Toolbar will be registered using this\n\t * repository.\n\t */\n\trepositoryName: string\n\n\t/**\n\t * The URL of your app's Prismic preview endpoint (default: `/api/preview`). This URL will be\n\t * fetched on preview update events.\n\t */\n\tupdatePreviewURL?: string\n\n\t/**\n\t * The URL of your app's exit preview endpoint (default: `/api/exit-preview`). This URL will be\n\t * fetched on preview exit events.\n\t */\n\texitPreviewURL?: string\n\n\t/** Children to render adjacent to the Prismic Toolbar. */\n\tchildren?: ReactNode\n}\n\n/**\n * React component that sets up Prismic Previews using the Prismic Toolbar. When the Prismic Toolbar\n * send events to the browser, such as on preview updates and exiting, this component will\n * automatically refresh the page with the changes.\n *\n * This component can be wrapped around your app or added anywhere in your app's tree. It must be\n * rendered on every page.\n */\nexport const PrismicPreview: FC<PrismicPreviewProps> = (props) => {\n\tconst {\n\t\trepositoryName,\n\t\tupdatePreviewURL = \"/api/preview\",\n\t\texitPreviewURL = \"/api/exit-preview\",\n\t\tchildren,\n\t} = props\n\n\tconst router = useRouter()\n\n\tconst toolbarSrc = getToolbarSrc(repositoryName)\n\n\tuseEffect(() => {\n\t\tconst controller = new AbortController()\n\t\tlet starting: Promise<void> | undefined\n\t\tlet startController: AbortController | undefined\n\t\tlet updateRequested = false\n\t\tlet ending = false\n\n\t\twindow.addEventListener(\"prismicPreviewUpdate\", onUpdate, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\twindow.addEventListener(\"prismicPreviewEnd\", onEnd, {\n\t\t\tsignal: controller.signal,\n\t\t})\n\n\t\t// Start the preview for preview share links. Previews from\n\t\t// share links do not go to the `updatePreviewURL` like a normal\n\t\t// preview.\n\t\t//\n\t\t// We check that the current URL is a descendant of the base\n\t\t// path to prevent infinite refrehes.\n\t\tif (\n\t\t\twindow.location.href.startsWith(window.location.origin + router.basePath) &&\n\t\t\tgetPreviewCookieRepositoryName() === repositoryName &&\n\t\t\t!router.isPreview\n\t\t) {\n\t\t\tstart()\n\t\t}\n\n\t\tfunction onEnd(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tif (ending) return\n\t\t\tending = true\n\t\t\tupdateRequested = false\n\t\t\tstartController?.abort()\n\t\t\tfetch(router.basePath + exitPreviewURL, { signal: controller.signal })\n\t\t\t\t.then((res) => {\n\t\t\t\t\tif (!res.ok) {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to exit Preview Mode using the \"${exitPreviewURL}\" API endpoint. Does it exist?`,\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\trefresh()\n\t\t\t\t})\n\t\t\t\t.catch(() => {})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tending = false\n\t\t\t\t})\n\t\t}\n\n\t\tfunction onUpdate(event: Event) {\n\t\t\tevent.preventDefault()\n\t\t\tif (ending) return\n\t\t\tstart()\n\t\t}\n\n\t\tfunction start() {\n\t\t\tupdateRequested = true\n\t\t\tif (starting) return\n\t\t\tconst requestController = new AbortController()\n\t\t\tstartController = requestController\n\n\t\t\t// We check `opaqueredirect` because we don't care if\n\t\t\t// the redirect was successful or not. As long as it\n\t\t\t// redirects, we know the endpoint exists and at least\n\t\t\t// attempted to set preview data.\n\t\t\tstarting = (async () => {\n\t\t\t\tdo {\n\t\t\t\t\tupdateRequested = false\n\t\t\t\t\tconst res = await fetch(router.basePath + updatePreviewURL, {\n\t\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\t\tsignal: requestController.signal,\n\t\t\t\t\t})\n\t\t\t\t\tif (res.type !== \"opaqueredirect\") {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`[<PrismicPreview>] Failed to start or update the preview using \"${updatePreviewURL}\". Does it exist?`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// Preview Data captures the cookie when the request starts.\n\t\t\t\t\t// If edits arrived meanwhile, store the latest ref before rendering.\n\t\t\t\t} while (updateRequested && !requestController.signal.aborted)\n\t\t\t\tif (!requestController.signal.aborted) refresh()\n\t\t\t})()\n\t\t\t\t.catch(() => {})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tstarting = undefined\n\t\t\t\t\tstartController = undefined\n\t\t\t\t})\n\t\t}\n\n\t\tfunction refresh() {\n\t\t\trouter.replace(router.asPath, undefined, { scroll: false })\n\t\t}\n\n\t\treturn () => {\n\t\t\tcontroller.abort()\n\t\t\tstartController?.abort()\n\t\t}\n\t}, [exitPreviewURL, updatePreviewURL, repositoryName, router])\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\t\t\t<Script src={toolbarSrc} strategy=\"lazyOnload\" />\n\t\t</>\n\t)\n}\n\nfunction getPreviewCookieRepositoryName() {\n\tconst cookie = window.document.cookie\n\t\t.split(\"; \")\n\t\t.find((row) => row.startsWith(`${prismicCookie.preview}=`))\n\t\t?.split(\"=\")[1]\n\n\treturn (decodeURIComponent(cookie ?? \"\").match(/\"([^\"]+)\\.prismic\\.io\"/) || [])[1]\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAsCA,MAAa,kBAA2C,UAAU;CACjE,MAAM,EACL,gBACA,mBAAmB,gBACnB,iBAAiB,qBACjB,aACG;CAEJ,MAAM,UAAA,GAAA,eAAA,YAAoB;CAE1B,MAAM,cAAA,GAAA,kBAAA,eAA2B,eAAe;AAEhD,EAAA,GAAA,MAAA,iBAAgB;EACf,MAAM,aAAa,IAAI,iBAAiB;EACxC,IAAI;EACJ,IAAI;EACJ,IAAI,kBAAkB;EACtB,IAAI,SAAS;AAEb,SAAO,iBAAiB,wBAAwB,UAAU,EACzD,QAAQ,WAAW,QACnB,CAAC;AACF,SAAO,iBAAiB,qBAAqB,OAAO,EACnD,QAAQ,WAAW,QACnB,CAAC;AAQF,MACC,OAAO,SAAS,KAAK,WAAW,OAAO,SAAS,SAAS,OAAO,SAAS,IACzE,gCAAgC,KAAK,kBACrC,CAAC,OAAO,UAER,QAAO;EAGR,SAAS,MAAM,OAAc;AAC5B,SAAM,gBAAgB;AACtB,OAAI,OAAQ;AACZ,YAAS;AACT,qBAAkB;AAClB,oBAAiB,OAAO;AACxB,SAAM,OAAO,WAAW,gBAAgB,EAAE,QAAQ,WAAW,QAAQ,CAAC,CACpE,MAAM,QAAQ;AACd,QAAI,CAAC,IAAI,IAAI;AACZ,aAAQ,MACP,6DAA6D,eAAe,gCAC5E;AAED;;AAGD,aAAS;KACR,CACD,YAAY,GAAG,CACf,cAAc;AACd,aAAS;KACR;;EAGJ,SAAS,SAAS,OAAc;AAC/B,SAAM,gBAAgB;AACtB,OAAI,OAAQ;AACZ,UAAO;;EAGR,SAAS,QAAQ;AAChB,qBAAkB;AAClB,OAAI,SAAU;GACd,MAAM,oBAAoB,IAAI,iBAAiB;AAC/C,qBAAkB;AAMlB,eAAY,YAAY;AACvB,OAAG;AACF,uBAAkB;AAKlB,UAJY,MAAM,MAAM,OAAO,WAAW,kBAAkB;MAC3D,UAAU;MACV,QAAQ,kBAAkB;MAC1B,CAAC,EACM,SAAS,kBAAkB;AAClC,cAAQ,MACP,mEAAmE,iBAAiB,mBACpF;AACD;;aAIO,mBAAmB,CAAC,kBAAkB,OAAO;AACtD,QAAI,CAAC,kBAAkB,OAAO,QAAS,UAAS;OAC7C,CACF,YAAY,GAAG,CACf,cAAc;AACd,eAAW,KAAA;AACX,sBAAkB,KAAA;KACjB;;EAGJ,SAAS,UAAU;AAClB,UAAO,QAAQ,OAAO,QAAQ,KAAA,GAAW,EAAE,QAAQ,OAAO,CAAC;;AAG5D,eAAa;AACZ,cAAW,OAAO;AAClB,oBAAiB,OAAO;;IAEvB;EAAC;EAAgB;EAAkB;EAAgB;EAAO,CAAC;AAE9D,QACC,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA,CACE,UACD,iBAAA,GAAA,kBAAA,KAACA,eAAAA,SAAD;EAAQ,KAAK;EAAY,UAAS;EAAe,CAAA,CAC/C,EAAA,CAAA;;AAIL,SAAS,iCAAiC;CACzC,MAAM,SAAS,OAAO,SAAS,OAC7B,MAAM,KAAK,CACX,MAAM,QAAQ,IAAI,WAAW,GAAGC,kBAAAA,OAAc,QAAQ,GAAG,CAAC,EACzD,MAAM,IAAI,CAAC;AAEd,SAAQ,mBAAmB,UAAU,GAAG,CAAC,MAAM,yBAAyB,IAAI,EAAE,EAAE"}
|
|
@@ -18,39 +18,63 @@ const PrismicPreview = (props) => {
|
|
|
18
18
|
const toolbarSrc = getToolbarSrc(repositoryName);
|
|
19
19
|
useEffect(() => {
|
|
20
20
|
const controller = new AbortController();
|
|
21
|
+
let starting;
|
|
22
|
+
let startController;
|
|
23
|
+
let updateRequested = false;
|
|
24
|
+
let ending = false;
|
|
21
25
|
window.addEventListener("prismicPreviewUpdate", onUpdate, { signal: controller.signal });
|
|
22
26
|
window.addEventListener("prismicPreviewEnd", onEnd, { signal: controller.signal });
|
|
23
27
|
if (window.location.href.startsWith(window.location.origin + router.basePath) && getPreviewCookieRepositoryName() === repositoryName && !router.isPreview) start();
|
|
24
28
|
function onEnd(event) {
|
|
25
29
|
event.preventDefault();
|
|
30
|
+
if (ending) return;
|
|
31
|
+
ending = true;
|
|
32
|
+
updateRequested = false;
|
|
33
|
+
startController?.abort();
|
|
26
34
|
fetch(router.basePath + exitPreviewURL, { signal: controller.signal }).then((res) => {
|
|
27
35
|
if (!res.ok) {
|
|
28
36
|
console.error(`[<PrismicPreview>] Failed to exit Preview Mode using the "${exitPreviewURL}" API endpoint. Does it exist?`);
|
|
29
37
|
return;
|
|
30
38
|
}
|
|
31
39
|
refresh();
|
|
32
|
-
}).catch(() => {})
|
|
40
|
+
}).catch(() => {}).finally(() => {
|
|
41
|
+
ending = false;
|
|
42
|
+
});
|
|
33
43
|
}
|
|
34
44
|
function onUpdate(event) {
|
|
35
45
|
event.preventDefault();
|
|
46
|
+
if (ending) return;
|
|
36
47
|
start();
|
|
37
48
|
}
|
|
38
49
|
function start() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
updateRequested = true;
|
|
51
|
+
if (starting) return;
|
|
52
|
+
const requestController = new AbortController();
|
|
53
|
+
startController = requestController;
|
|
54
|
+
starting = (async () => {
|
|
55
|
+
do {
|
|
56
|
+
updateRequested = false;
|
|
57
|
+
if ((await fetch(router.basePath + updatePreviewURL, {
|
|
58
|
+
redirect: "manual",
|
|
59
|
+
signal: requestController.signal
|
|
60
|
+
})).type !== "opaqueredirect") {
|
|
61
|
+
console.error(`[<PrismicPreview>] Failed to start or update the preview using "${updatePreviewURL}". Does it exist?`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
} while (updateRequested && !requestController.signal.aborted);
|
|
65
|
+
if (!requestController.signal.aborted) refresh();
|
|
66
|
+
})().catch(() => {}).finally(() => {
|
|
67
|
+
starting = void 0;
|
|
68
|
+
startController = void 0;
|
|
69
|
+
});
|
|
49
70
|
}
|
|
50
71
|
function refresh() {
|
|
51
72
|
router.replace(router.asPath, void 0, { scroll: false });
|
|
52
73
|
}
|
|
53
|
-
return () =>
|
|
74
|
+
return () => {
|
|
75
|
+
controller.abort();
|
|
76
|
+
startController?.abort();
|
|
77
|
+
};
|
|
54
78
|
}, [
|
|
55
79
|
exitPreviewURL,
|
|
56
80
|
updatePreviewURL,
|