Skip to content

Commit

Permalink
fix(kit): support previews using a /preview/ route prefix (#16)
Browse files Browse the repository at this point in the history
* fix(kit): update `redirectToPreviewURL()` to support the route prefix strategy

* fix(kit): update `<PrismicPreview>` to support the route prefix strategy

* fix: correctly remove Prismic toolbar event handlers
  • Loading branch information
angeloashmore committed Oct 13, 2023
1 parent b88da24 commit 56646d1
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 17 deletions.
97 changes: 81 additions & 16 deletions src/kit/PrismicPreview.svelte
Original file line number Diff line number Diff line change
@@ -1,37 +1,102 @@
<script lang="ts">
import { onMount } from "svelte";
import { getToolbarSrc } from "@prismicio/client";
import { invalidateAll } from "$app/navigation";
import { beforeNavigate, goto, invalidateAll } from "$app/navigation";
/**
* The name of your Prismic repository. A Prismic Toolbar will be registered
* using this repository.
*/
export let repositoryName: string;
$: toolbarSrc = getToolbarSrc(repositoryName);
/**
* The route parameter prefixed during preview sessions.
*/
export let routePrefix: string = "preview";
function prismicPreviewEventHandler(event: Event) {
event.preventDefault();
/**
* The name of the preview-specific route parameter prefixed during preview
* sessions.
*
* Only set this value if the route parameter's name differs from the
* parameter's value.
*/
export let routePrefixName: string = routePrefix;
invalidateAll();
}
$: toolbarSrc = getToolbarSrc(repositoryName);
/**
* Set to `true` when the next `beforeNavigate()` call should not prefix the
* route.
*/
let endingPreview = false;
// Register Prismic toolbar event handlers to refresh data on content updates.
onMount(() => {
window.addEventListener("prismicPreviewUpdate", prismicPreviewEventHandler);
window.addEventListener("prismicPreviewEnd", prismicPreviewEventHandler);
const controller = new AbortController();
window.addEventListener(
"prismicPreviewUpdate",
(event) => {
event.preventDefault();
invalidateAll();
},
{ signal: controller.signal },
);
window.addEventListener(
"prismicPreviewEnd",
(event) => {
event.preventDefault();
endingPreview = true;
goto(
new URL(
window.location.pathname.replace(
new RegExp(`^(\/${routePrefix}\/?$|\/${routePrefix}\/)`),
"/",
),
window.location.origin,
),
{
invalidateAll: true,
noScroll: true,
},
);
},
{ signal: controller.signal },
);
return () => {
window.removeEventListener(
"prismicPreviewUpdate",
prismicPreviewEventHandler,
);
window.removeEventListener(
"prismicPreviewEnd",
prismicPreviewEventHandler,
);
controller.abort();
};
});
beforeNavigate((navigation) => {
// Prefix links with the preview route parameter if the current
// route is in a preview session.
if (
navigation.to &&
navigation.from?.params?.[routePrefixName] === routePrefix &&
!(routePrefixName in (navigation.to.params || {}))
) {
// If this callback is called due to a `prismicPreviewEnd`
// event, don't prefix the route. The exception is only
// valid for one call.
if (endingPreview) {
endingPreview = false;
return;
}
navigation.cancel();
goto(
new URL(
routePrefix + navigation.to.url.pathname,
navigation.to.url.origin,
),
);
}
});
</script>

<svelte:head>
Expand Down
25 changes: 24 additions & 1 deletion src/kit/redirectToPreviewURL.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as prismic from "@prismicio/client";
import { Cookies } from "@sveltejs/kit";

export type RedirectToPreviewURLConfig = {
/**
Expand All @@ -16,11 +17,23 @@ export type RedirectToPreviewURLConfig = {
*/
request: Request;

/**
* The `cookies` object from a `+server` file.
*
* @see SvelteKit `+server` docs: \<https://kit.svelte.dev/docs/routing#server\>
*/
cookies: Cookies;

/**
* The default redirect URL if a URL cannot be determined for the previewed
* document.
*/
defaultURL?: string;

/**
* The route parameter prefixed during preview sessions.
*/
routePrefix?: string;
};

/**
Expand Down Expand Up @@ -49,17 +62,27 @@ export const redirectToPreviewURL = async (
new URL(config.request.url).searchParams.get("token") ?? undefined;
const documentID =
new URL(config.request.url).searchParams.get("documentId") ?? undefined;
const routePrefix = config.routePrefix ?? "preview";

const previewURL = await config.client.resolvePreviewURL({
previewToken,
documentID,
defaultURL: config.defaultURL || "/",
});

// Prevent a flash of non-preview content by setting the preview token
// on the initial page load.
if (previewToken) {
config.cookies.set(prismic.cookie.preview, previewToken, {
path: "/",
httpOnly: false,
});
}

return new Response(undefined, {
status: 307,
headers: {
Location: previewURL,
Location: "/" + routePrefix + previewURL,
},
});
};

0 comments on commit 56646d1

Please sign in to comment.