Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 28 additions & 93 deletions src/adapters/sveltekit.templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,8 @@ export function prismicIOFileTemplate({ typescript }: { typescript: boolean }):
`;
}

export function sliceSimulatorPageTemplate({ version }: { version: number }): string {
const v5 = dedent`
<script>
import { SliceSimulator, SliceZone } from '@prismicio/svelte';
import { components } from '$lib/slices';
</script>

<!-- Slot syntax is used for backward compatibility with Svelte <=4. -->
<SliceSimulator let:slices>
<SliceZone {slices} {components} />
</SliceSimulator>
`;

const v4 = dedent`
export function sliceSimulatorPageTemplate(): string {
return dedent`
<script>
import { SliceSimulator, SliceZone } from '@prismicio/svelte';
import { components } from '$lib/slices';
Expand All @@ -90,8 +78,6 @@ export function sliceSimulatorPageTemplate({ version }: { version: number }): st
<SliceZone {slices} {components} />
</SliceSimulator>
`;

return version <= 4 ? v4 : v5;
}

export function previewAPIRouteTemplate({ typescript }: { typescript: boolean }): string {
Expand Down Expand Up @@ -122,20 +108,6 @@ export function previewAPIRouteTemplate({ typescript }: { typescript: boolean })
`;
}

const HEAD_MARKUP = dedent`
<svelte:head>
<title>{page.data.page?.data.meta_title}</title>
<meta property="og:title" content={page.data.page?.data.meta_title} />
{#if isFilled.keyText(page.data.page?.data.meta_description)}
<meta name="description" content={page.data.page.data.meta_description} />
<meta property="og:description" content={page.data.page.data.meta_description} />
{/if}
{#if isFilled.image(page.data.page?.data.meta_image)}
<meta property="og:image" content={asImageSrc(page.data.page.data.meta_image)} />
{/if}
</svelte:head>
`;

export function layoutServerTemplate(): string {
return dedent`
import { repositoryName } from "$lib/prismicio";
Expand All @@ -148,8 +120,8 @@ export function layoutServerTemplate(): string {
`;
}

export function rootLayoutTemplate({ version }: { version: number }): string {
const v5 = dedent`
export function rootLayoutTemplate(): string {
return dedent`
<script>
import { isFilled, asImageSrc } from '@prismicio/client';
import { PrismicPreview } from '@prismicio/svelte/kit';
Expand All @@ -158,26 +130,20 @@ export function rootLayoutTemplate({ version }: { version: number }): string {
const { data, children } = $props();
</script>

${HEAD_MARKUP}
<svelte:head>
<title>{page.data.page?.data.meta_title}</title>
<meta property="og:title" content={page.data.page?.data.meta_title} />
{#if isFilled.keyText(page.data.page?.data.meta_description)}
<meta name="description" content={page.data.page.data.meta_description} />
<meta property="og:description" content={page.data.page.data.meta_description} />
{/if}
{#if isFilled.image(page.data.page?.data.meta_image)}
<meta property="og:image" content={asImageSrc(page.data.page.data.meta_image)} />
{/if}
</svelte:head>
{@render children()}
<PrismicPreview repositoryName={data.repositoryName} />
`;

const v4 = dedent`
<script>
import { isFilled, asImageSrc } from '@prismicio/client';
import { PrismicPreview } from '@prismicio/svelte/kit';
import { page } from '$app/state';

export let data;
</script>

${HEAD_MARKUP}
<slot />
<PrismicPreview repositoryName={data.repositoryName} />
`;

return version <= 4 ? v4 : v5;
}

export function pageTemplate({ typescript }: { typescript: boolean }): string {
Expand Down Expand Up @@ -277,31 +243,25 @@ const SLICE_MARKUP = dedent`
</section>
`;

export function sliceTemplate({
name,
typescript,
version,
}: {
name: string;
typescript: boolean;
version: number;
}): string {
export function sliceTemplate({ name, typescript }: { name: string; typescript: boolean }): string {
const pascalName = pascalCase(name);

const v5TS = dedent`
<script lang="ts">
import type { Content } from '@prismicio/client';
import type { SliceComponentProps } from '@prismicio/svelte';
if (typescript) {
return dedent`
<script lang="ts">
import type { Content } from '@prismicio/client';
import type { SliceComponentProps } from '@prismicio/svelte';

type Props = SliceComponentProps<Content.${pascalName}Slice>;
type Props = SliceComponentProps<Content.${pascalName}Slice>;

const { slice }: Props = $props();
</script>
const { slice }: Props = $props();
</script>

${SLICE_MARKUP}
`;
${SLICE_MARKUP}
`;
}

const v5JS = dedent`
return dedent`
<script>
/* @typedef {import("@prismicio/client").Content} Content */
/* @typedef {import("@prismicio/svelte").SliceComponentProps} SliceComponentProps */
Expand All @@ -312,29 +272,4 @@ export function sliceTemplate({

${SLICE_MARKUP}
`;

const v4TS = dedent`
<script lang="ts">
import type { Content } from '@prismicio/client';

export let slice: Content.${pascalName}Slice;
</script>

${SLICE_MARKUP}
`;

const v4JS = dedent`
<script>
/** @type {import("@prismicio/client").Content.${pascalName}Slice} */
export let slice;
</script>

${SLICE_MARKUP}
`;

if (typescript) {
return version <= 4 ? v4TS : v5TS;
}

return version <= 4 ? v4JS : v5JS;
}
48 changes: 14 additions & 34 deletions src/adapters/sveltekit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { pascalCase } from "change-case";
import {
Adapter,
checkSourceContains,
getInstalledMajor,
getJsFileExtension,
type PageFile,
writeFileIfMissing,
Expand Down Expand Up @@ -54,15 +53,14 @@ export class SvelteKitAdapter extends Adapter {
const projectRoot = await findProjectRoot();
const extension = await getJsFileExtension();
const typescript = await checkIsTypeScriptProject();
const version = await getInstalledMajor("svelte");

await writeFileIfMissing(
new URL(`src/lib/prismicio.${extension}`, projectRoot),
prismicIOFileTemplate({ typescript }),
);
await writeFileIfMissing(
new URL("src/routes/slice-simulator/+page.svelte", projectRoot),
sliceSimulatorPageTemplate({ version }),
sliceSimulatorPageTemplate(),
);
await writeFileIfMissing(
new URL(`src/params/preview.${extension}`, projectRoot),
Expand Down Expand Up @@ -104,7 +102,7 @@ export class SvelteKitAdapter extends Adapter {
if (returnsRepositoryName) {
await writeFileIfMissing(
new URL("src/routes/+layout.svelte", projectRoot),
rootLayoutTemplate({ version }),
rootLayoutTemplate(),
);
}
await deleteStarterHomePage();
Expand Down Expand Up @@ -132,34 +130,6 @@ export class SvelteKitAdapter extends Adapter {
private async getPreviewStep(): Promise<string | undefined> {
if (await checkSourceContains("PrismicPreview")) return;

const layoutStep =
(await getInstalledMajor("svelte")) <= 4
? dedent`
Add the lines marked + to src/routes/+layout.svelte:

<script>
+ import { PrismicPreview } from "@prismicio/svelte/kit";
+
+ export let data;
</script>

<slot />
+ <PrismicPreview repositoryName={data.repositoryName} />
`
: dedent`
Change the lines marked - and + in src/routes/+layout.svelte:

<script>
+ import { PrismicPreview } from "@prismicio/svelte/kit";

- let { children } = $props();
+ let { data, children } = $props();
</script>

{@render children()}
+ <PrismicPreview repositoryName={data.repositoryName} />
`;

// The layout reads repositoryName from the server layout's data.
const serverLayoutPath =
(await findServerLayout()) ?? `src/routes/+layout.server.${await getJsFileExtension()}`;
Expand All @@ -177,8 +147,19 @@ export class SvelteKitAdapter extends Adapter {

Previews do not work until you do this, and the CLI cannot edit your
layout for you. Make the change now.

Change the lines marked - and + in src/routes/+layout.svelte:

<script>
+ import { PrismicPreview } from "@prismicio/svelte/kit";

- let { children } = $props();
+ let { data, children } = $props();
</script>

{@render children()}
+ <PrismicPreview repositoryName={data.repositoryName} />
`,
layoutStep,
serverLayoutStep,
"Run `prismic docs view sveltekit` for details.",
]
Expand Down Expand Up @@ -215,7 +196,6 @@ export class SvelteKitAdapter extends Adapter {
const contents = sliceTemplate({
name: model.name,
typescript: await checkIsTypeScriptProject(),
version: await getInstalledMajor("svelte"),
});
await writeFileRecursive(new URL("index.svelte", directory), contents);
}
Expand Down
63 changes: 2 additions & 61 deletions test/gen-setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,8 @@ it(
"generates valid script tags for SvelteKit",
{ timeout: 30_000 },
async ({ expect, project, prismic }) => {
// Reconfigure the fixture as a SvelteKit project so a file with a <script>
// block is generated (the simulator page).
await writeFile(
new URL("package.json", project),
JSON.stringify({ dependencies: { "@sveltejs/kit": "latest", svelte: "latest" } }),
);
await mkdir(new URL("node_modules/svelte/", project), { recursive: true });
await writeFile(
new URL("node_modules/svelte/package.json", project),
JSON.stringify({ version: "5.0.0" }),
);
// A SvelteKit project generates a file with a <script> block (the simulator page).
await useSvelteKit(project);

const { stderr, exitCode } = await prismic("gen", ["setup", "--no-install"]);
expect(exitCode, stderr).toBe(0);
Expand Down Expand Up @@ -179,21 +170,6 @@ it(
},
);

it(
"passes the repository name to a Svelte 4 layout it generated itself",
{ timeout: 30_000 },
async ({ expect, project, prismic }) => {
await useSvelteKit(project, "4.2.19");

const { stderr, exitCode } = await prismic("gen", ["setup", "--no-install"]);
expect(exitCode, stderr).toBe(0);
const layout = await readFile(new URL("src/routes/+layout.svelte", project), "utf8");
expect(layout).toContain("export let data;");
expect(layout).toContain("<PrismicPreview repositoryName={data.repositoryName} />");
expect(layout).not.toContain("$lib/prismicio");
},
);

it(
"returns the repository name from a SvelteKit server layout",
{ timeout: 30_000 },
Expand Down Expand Up @@ -313,41 +289,6 @@ it("works when Next.js is declared but not installed", async ({ expect, project,
await expect(project).toHaveFile("app/api/revalidate/route.js");
});

it(
"works when Svelte is declared but not installed",
{ timeout: 30_000 },
async ({ expect, project, prismic }) => {
// node_modules is absent, so the Svelte version cannot be read.
await writeFile(
new URL("package.json", project),
JSON.stringify({ dependencies: { "@sveltejs/kit": "latest", svelte: "latest" } }),
);
await mkdir(new URL("src/routes/", project), { recursive: true });
await writeFile(new URL("src/routes/+layout.svelte", project), "{@render children()}");

const { stdout, stderr, exitCode } = await prismic("gen", ["setup", "--no-install"]);
expect(exitCode, stderr).toBe(0);
expect(stdout).toContain("add <PrismicPreview> to your root layout");
},
);

it(
"prints Svelte 4 syntax in the instructions for a Svelte 4 project",
{ timeout: 30_000 },
async ({ expect, project, prismic }) => {
await useSvelteKit(project, "4.2.19");
await mkdir(new URL("src/routes/", project), { recursive: true });
await writeFile(new URL("src/routes/+layout.svelte", project), "<slot />");

const { stdout, stderr, exitCode } = await prismic("gen", ["setup", "--no-install"]);
expect(exitCode, stderr).toBe(0);
expect(stdout).toContain("+ export let data;");
expect(stdout).toContain("<slot />");
expect(stdout).not.toContain("{@render children()}");
expect(stdout).not.toContain("$props()");
},
);

it(
"prints SvelteKit instructions when the project already has a root layout",
{ timeout: 30_000 },
Expand Down
7 changes: 1 addition & 6 deletions test/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,18 +196,13 @@ export const it = test.extend<Fixtures>({
},
});

export async function useSvelteKit(project: URL, version = "5.0.0"): Promise<void> {
export async function useSvelteKit(project: URL): Promise<void> {
await rm(new URL("node_modules/next/", project), { recursive: true, force: true });
await rm(new URL("app/", project), { recursive: true, force: true });
await writeFile(
new URL("package.json", project),
JSON.stringify({ dependencies: { "@sveltejs/kit": "latest", svelte: "latest" } }),
);
await mkdir(new URL("node_modules/svelte/", project), { recursive: true });
await writeFile(
new URL("node_modules/svelte/package.json", project),
JSON.stringify({ version }),
);
}

// Makes the package manager install fail by shadowing npm in node_modules/.bin.
Expand Down
Loading