Skip to content

Commit

Permalink
ignore templates marked for in platform page sets
Browse files Browse the repository at this point in the history
  • Loading branch information
benlife5 committed Jan 17, 2025
1 parent 58ee9bb commit 2b738cd
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 6 deletions.
15 changes: 15 additions & 0 deletions packages/pages/src/common/src/project/structure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export interface DistConfigFiles {
export interface RootFiles {
/** The config.yaml file */
config: string;
/** The .template-manifest.json file for in-platform page sets */
templateManifest: string;
}

/**
Expand Down Expand Up @@ -180,6 +182,7 @@ const defaultProjectStructureConfig: ProjectStructureConfig = {
},
rootFiles: {
config: "config.yaml",
templateManifest: ".template-manifest.json",
},
envVarConfig: {
envVarDir: "",
Expand Down Expand Up @@ -313,6 +316,18 @@ export class ProjectStructure {
);
};

/**
* @returns the {@link Path} to the .template-manifest.json file, taking scope into account.
*/
getTemplateManifestPath = () => {
return new Path(
pathLib.join(
this.config.scope ?? "",
this.config.rootFiles.templateManifest
)
);
};

/**
* @returns the {@link Path} to the modules folder, taking scope into account.
* If moduleName is provided, returns the path to that modules folder. If a scope is
Expand Down
45 changes: 45 additions & 0 deletions packages/pages/src/common/src/template/loader/loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from "path";
import { loadTemplateModules } from "./loader.js";
import { convertToPosixPath } from "../paths.js";
import { ProjectStructure } from "../../project/structure.js";
import fs from "node:fs";

describe("loadTemplateModules", () => {
it("loads and transpiles raw templates", async () => {
Expand Down Expand Up @@ -35,4 +36,48 @@ describe("loadTemplateModules", () => {

expect(templateModules.get("template")?.config.name).toEqual("template");
});

it("ignores in-platform page set templates", async () => {
try {
const templateFiles = glob.sync([
convertToPosixPath(
path.join(process.cwd(), "tests/fixtures/inPlatformTemplate.tsx")
),
convertToPosixPath(
path.join(process.cwd(), "tests/fixtures/template.tsx")
),
]);

const testTemplateManifest = {
templates: [
{
name: "inPlatformTemplate",
description: "test",
exampleSiteUrl: "",
layoutRequired: true,
defaultLayoutData: '{"root":{}, "zones":{}, "content":[]}',
},
],
};

fs.writeFileSync(
".template-manifest.json",
JSON.stringify(testTemplateManifest)
);

const templateModules = await loadTemplateModules(
templateFiles,
false,
false,
new ProjectStructure()
);

expect(templateModules.get("inPlatformTemplate")).toBeUndefined();
expect(templateModules.get("template")?.config.name).toEqual("template");
} finally {
if (fs.existsSync(".template-manifest.json")) {
fs.unlinkSync(".template-manifest.json");
}
}
});
});
31 changes: 26 additions & 5 deletions packages/pages/src/common/src/template/loader/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { ProjectStructure } from "../../project/structure.js";
import { loadModules } from "../../loader/vite.js";
import { ViteDevServer } from "vite";
import { loadViteModule } from "../../../../dev/server/ssr/loadViteModule.js";
import { TemplateModule } from "../types.js";
import { TemplateManifest, TemplateModule } from "../types.js";
import fs from "node:fs";

/**
* Loads all templates in the project.
Expand All @@ -29,6 +30,21 @@ export const loadTemplateModules = async (
projectStructure
);

const templateManifestPath = projectStructure
.getTemplateManifestPath()
.getAbsolutePath();

let inPlatformTemplateNames: string[] = [];
if (fs.existsSync(templateManifestPath)) {
const templateManifest = JSON.parse(
fs.readFileSync(templateManifestPath, "utf-8")
) as TemplateManifest;

inPlatformTemplateNames = templateManifest.templates.map(
(templateInfo) => templateInfo.name
);
}

const importedTemplateModules = [] as TemplateModuleInternal<any, any>[];
for (const importedModule of importedModules) {
const templateModuleInternal =
Expand All @@ -38,10 +54,15 @@ export const loadTemplateModules = async (
adjustForFingerprintedAsset
);

importedTemplateModules.push({
...templateModuleInternal,
path: importedModule.path,
});
// ignore templates marked for in-platform page set use by .template-manifest.json
if (
!inPlatformTemplateNames.includes(templateModuleInternal.templateName)
) {
importedTemplateModules.push({
...templateModuleInternal,
path: importedModule.path,
});
}
}

return importedTemplateModules.reduce((prev, module) => {
Expand Down
22 changes: 22 additions & 0 deletions packages/pages/src/common/src/template/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,25 @@ export interface PageContext<T extends TemplateRenderProps<T>> {
/** The template to render */
Page: Template<T>;
}

/**
* The type of the .template-manifest.json file,
* which is used to specify in-platform page sets.
*
* @internal
*/
export interface TemplateManifest {
/** The list of templates to use for in-platform page sets. */
templates: {
/** The file name of the template, without the extension */
name: string;
/** A description of the template. */
description: string;
/** A URL of an example site that uses the template. */
exampleSiteUrl: string;
/** Determines if a layout is automatically created during page set creation */
layoutRequired: boolean;
/** Stringified Puck data to use when a new layout is created */
defaultLayoutData: string;
}[];
}
2 changes: 1 addition & 1 deletion packages/pages/src/scaffold/template/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ const addVEDependencies = async () => {
await updatePackageDependency("@yext/visual-editor", null, true);
await updatePackageDependency(
"@measured/puck",
"0.16.0-canary.39e7f40",
{ specificVersion: "0.17.1" },
true
);
await installDependencies();
Expand Down
76 changes: 76 additions & 0 deletions packages/pages/tests/fixtures/inPlatformTemplate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* This is a simple template that can be used for tests.
*/

import * as React from "react";
import {
Template,
GetPath,
GetRedirects,
TemplateConfig,
TemplateProps,
TemplateRenderProps,
GetHeadConfig,
HeadConfig,
} from "@yext/pages";

/**
* Defines the path that the generated file will live at for production.
*
* NOTE: This currently has no impact on the local dev path. Local dev urls currently
* take on the form: featureName/entityId
*/
export const getPath: GetPath<TemplateProps> = ({ document }) => {
return `location/${document.id.toString()}`;
};

/**
* This allows the user to define a function which will take in their template
* data and procude a HeadConfig object. When the site is generated, the HeadConfig
* will be used to generate the inner contents of the HTML document's <head> tag.
* This can include the title, meta tags, script tags, etc.
*/
export const getHeadConfig: GetHeadConfig<TemplateRenderProps> = ({
relativePrefixToRoot,
path,
document,
}): HeadConfig => {
return {
title: document.name,
charset: "UTF-8",
viewport: "width=device-width, initial-scale=1",
tags: [
{
type: "meta",
attributes: {
description: "This site was generated by the Yext SSG",
},
},
],
};
};

/**
* This is the main template. It can have any name as long as it's the default export.
* The props passed in here are the direct stream document defined by `config`.
*/
const Location: Template<TemplateRenderProps> = ({
relativePrefixToRoot,
path,
document,
}) => {
const {
_site,
name,
address,
openTime,
hours,
mainPhone,
geocodedCoordinate,
services,
} = document;

return <>Hello, World</>;
};

export default Location;

0 comments on commit 2b738cd

Please sign in to comment.