create-plasmic-app 0.0.166 → 0.0.168
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/cpa-out/nextjs-app-codegen-js/app/dynamic/[slug]/page.jsx +5 -5
- package/cpa-out/nextjs-app-codegen-js/app/robots.js +24 -0
- package/cpa-out/nextjs-app-codegen-js/app/sitemap.js +38 -0
- package/cpa-out/nextjs-app-codegen-js/components/plasmic/create_plasmic_app/PlasmicDynamicPage.jsx +2 -2
- package/cpa-out/nextjs-app-codegen-js/components/plasmic/create_plasmic_app/PlasmicDynamicPageServer.jsx +2 -2
- package/cpa-out/nextjs-app-codegen-js/components/plasmic/create_plasmic_app/plasmic.css +16 -0
- package/cpa-out/nextjs-app-codegen-js/components/plasmic/plasmic__default_style.css +16 -0
- package/cpa-out/nextjs-app-codegen-js/package.json +6 -6
- package/cpa-out/nextjs-app-codegen-js/plasmic.json +2 -6
- package/cpa-out/nextjs-app-codegen-ts/app/dynamic/[slug]/page.tsx +8 -11
- package/cpa-out/nextjs-app-codegen-ts/app/page.tsx +4 -4
- package/cpa-out/nextjs-app-codegen-ts/app/robots.ts +25 -0
- package/cpa-out/nextjs-app-codegen-ts/app/sitemap.ts +41 -0
- package/cpa-out/nextjs-app-codegen-ts/components/plasmic/create_plasmic_app/PlasmicDynamicPage.tsx +2 -2
- package/cpa-out/nextjs-app-codegen-ts/components/plasmic/create_plasmic_app/PlasmicDynamicPageServer.tsx +7 -13
- package/cpa-out/nextjs-app-codegen-ts/components/plasmic/create_plasmic_app/PlasmicHomepageServer.tsx +5 -11
- package/cpa-out/nextjs-app-codegen-ts/components/plasmic/create_plasmic_app/plasmic.css +16 -0
- package/cpa-out/nextjs-app-codegen-ts/components/plasmic/plasmic__default_style.css +16 -0
- package/cpa-out/nextjs-app-codegen-ts/package.json +6 -6
- package/cpa-out/nextjs-app-codegen-ts/plasmic.json +2 -6
- package/cpa-out/nextjs-app-loader-js/app/robots.js +24 -0
- package/cpa-out/nextjs-app-loader-js/app/sitemap.js +29 -0
- package/cpa-out/nextjs-app-loader-js/package.json +5 -5
- package/cpa-out/nextjs-app-loader-ts/app/layout.tsx +1 -5
- package/cpa-out/nextjs-app-loader-ts/app/robots.ts +25 -0
- package/cpa-out/nextjs-app-loader-ts/app/sitemap.ts +30 -0
- package/cpa-out/nextjs-app-loader-ts/package.json +5 -5
- package/cpa-out/nextjs-pages-codegen-js/pages/robots.txt.js +25 -0
- package/cpa-out/nextjs-pages-codegen-js/pages/sitemap.xml.js +53 -0
- package/cpa-out/nextjs-pages-codegen-ts/pages/robots.txt.ts +27 -0
- package/cpa-out/nextjs-pages-codegen-ts/pages/sitemap.xml.ts +56 -0
- package/cpa-out/nextjs-pages-loader-js/pages/robots.txt.js +25 -0
- package/cpa-out/nextjs-pages-loader-js/pages/sitemap.xml.js +46 -0
- package/cpa-out/nextjs-pages-loader-ts/pages/robots.txt.ts +27 -0
- package/cpa-out/nextjs-pages-loader-ts/pages/sitemap.xml.ts +47 -0
- package/dist/nextjs/nextjs.js +14 -0
- package/dist/nextjs/templates/app-seo.d.ts +4 -0
- package/dist/nextjs/templates/app-seo.js +92 -0
- package/dist/nextjs/templates/pages-seo.d.ts +4 -0
- package/dist/nextjs/templates/pages-seo.js +121 -0
- package/package.json +3 -3
- package/src/nextjs/nextjs.ts +46 -0
- package/src/nextjs/templates/app-seo.ts +104 -0
- package/src/nextjs/templates/pages-seo.ts +131 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeRobots_pages = exports.makeSitemap_pages_codegen = exports.makeSitemap_pages_loader = void 0;
|
|
4
|
+
const file_utils_1 = require("../../utils/file-utils");
|
|
5
|
+
const siteUrl = ` // Set NEXT_PUBLIC_SITE_URL to pin the origin;
|
|
6
|
+
// otherwise it is derived per-request from the request headers.
|
|
7
|
+
const siteUrl =
|
|
8
|
+
process.env.NEXT_PUBLIC_SITE_URL ??
|
|
9
|
+
(process.env.VERCEL_PROJECT_PRODUCTION_URL
|
|
10
|
+
? \`https://\${process.env.VERCEL_PROJECT_PRODUCTION_URL}\`
|
|
11
|
+
: \`\${req.headers["x-forwarded-proto"] ?? "http"}://\${
|
|
12
|
+
req.headers["x-forwarded-host"] ?? req.headers.host
|
|
13
|
+
}\`);`;
|
|
14
|
+
function makeHeader(jsOrTs) {
|
|
15
|
+
return (0, file_utils_1.ifTs)(jsOrTs, `import type { GetServerSideProps } from "next";\n`);
|
|
16
|
+
}
|
|
17
|
+
function makeSignature(jsOrTs) {
|
|
18
|
+
return `export const getServerSideProps${(0, file_utils_1.ifTs)(jsOrTs, ": GetServerSideProps")} = async ({ req, res }) => {`;
|
|
19
|
+
}
|
|
20
|
+
function makeSitemapXml(jsOrTs) {
|
|
21
|
+
return `function escapeXml(str${(0, file_utils_1.ifTs)(jsOrTs, ": string")}) {
|
|
22
|
+
return str
|
|
23
|
+
.replace(/&/g, "&")
|
|
24
|
+
.replace(/</g, "<")
|
|
25
|
+
.replace(/>/g, ">")
|
|
26
|
+
.replace(/"/g, """)
|
|
27
|
+
.replace(/'/g, "'");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function makeSitemapXml(urls${(0, file_utils_1.ifTs)(jsOrTs, ": string[]")}) {
|
|
31
|
+
const entries = urls.map(
|
|
32
|
+
(url) => \` <url><loc>\${escapeXml(url)}</loc></url>\`
|
|
33
|
+
);
|
|
34
|
+
return \`<?xml version="1.0" encoding="UTF-8"?>
|
|
35
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
36
|
+
\${entries.join("\\n")}
|
|
37
|
+
</urlset>
|
|
38
|
+
\`;
|
|
39
|
+
}`;
|
|
40
|
+
}
|
|
41
|
+
function makeSitemap_pages_loader(jsOrTs) {
|
|
42
|
+
return `import { PLASMIC } from "@/plasmic-init";
|
|
43
|
+
${makeHeader(jsOrTs)}
|
|
44
|
+
${makeSitemapXml(jsOrTs)}
|
|
45
|
+
|
|
46
|
+
${makeSignature(jsOrTs)}
|
|
47
|
+
${siteUrl}
|
|
48
|
+
|
|
49
|
+
// fetchPages() drops pages whose path takes a param, e.g. "/blog/[slug]".
|
|
50
|
+
const pages = await PLASMIC.fetchPages();
|
|
51
|
+
const urls = pages.map((page) => new URL(page.path, siteUrl).toString());
|
|
52
|
+
|
|
53
|
+
res.setHeader("Content-Type", "application/xml; charset=utf-8");
|
|
54
|
+
res.write(makeSitemapXml(urls));
|
|
55
|
+
res.end();
|
|
56
|
+
return { props: {} };
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default function Sitemap() {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
exports.makeSitemap_pages_loader = makeSitemap_pages_loader;
|
|
65
|
+
function makeSitemap_pages_codegen(jsOrTs) {
|
|
66
|
+
const projects = jsOrTs === "ts"
|
|
67
|
+
? `(plasmicJson.projects as {
|
|
68
|
+
components: { componentType: string; path?: string }[];
|
|
69
|
+
}[])`
|
|
70
|
+
: "plasmicJson.projects";
|
|
71
|
+
return `${makeHeader(jsOrTs)}import plasmicJson from "../plasmic.json";
|
|
72
|
+
|
|
73
|
+
${makeSitemapXml(jsOrTs)}
|
|
74
|
+
|
|
75
|
+
${makeSignature(jsOrTs)}
|
|
76
|
+
${siteUrl}
|
|
77
|
+
|
|
78
|
+
const urls = ${projects}
|
|
79
|
+
.flatMap((project) => project.components)
|
|
80
|
+
.flatMap((component) =>
|
|
81
|
+
component.componentType === "page" &&
|
|
82
|
+
component.path &&
|
|
83
|
+
!component.path.includes("[")
|
|
84
|
+
? // next.config sets trailingSlash.
|
|
85
|
+
[new URL(component.path.replace(/\\/?$/, "/"), siteUrl).toString()]
|
|
86
|
+
: []
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
res.setHeader("Content-Type", "application/xml; charset=utf-8");
|
|
90
|
+
res.write(makeSitemapXml(urls));
|
|
91
|
+
res.end();
|
|
92
|
+
return { props: {} };
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default function Sitemap() {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
exports.makeSitemap_pages_codegen = makeSitemap_pages_codegen;
|
|
101
|
+
function makeRobots_pages(jsOrTs) {
|
|
102
|
+
return `${(0, file_utils_1.ifTs)(jsOrTs, `import type { GetServerSideProps } from "next";\n\n`)}${makeSignature(jsOrTs)}
|
|
103
|
+
${siteUrl}
|
|
104
|
+
|
|
105
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
106
|
+
res.write(
|
|
107
|
+
\`User-agent: *\\nAllow: /\\n\\nSitemap: \${new URL(
|
|
108
|
+
"/sitemap.xml",
|
|
109
|
+
siteUrl
|
|
110
|
+
).toString()}\\n\`
|
|
111
|
+
);
|
|
112
|
+
res.end();
|
|
113
|
+
return { props: {} };
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export default function Robots() {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
exports.makeRobots_pages = makeRobots_pages;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-plasmic-app",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.168",
|
|
4
4
|
"description": "Create Plasmic-powered React apps",
|
|
5
5
|
"homepage": "https://www.plasmic.app",
|
|
6
6
|
"repository": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"tsx": "^4.23.11"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@plasmicapp/cli": "0.1.
|
|
42
|
+
"@plasmicapp/cli": "0.1.373",
|
|
43
43
|
"@sentry/node": "^6.2.2",
|
|
44
44
|
"chalk": "^4.1.0",
|
|
45
45
|
"execa": "^5.0.0",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"validate-npm-package-name": "^3.0.0",
|
|
54
54
|
"yargs": "^16.2.2"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "f63ae177f15f845faf191d62b25fc3e3e3cfdb95"
|
|
57
57
|
}
|
package/src/nextjs/nextjs.ts
CHANGED
|
@@ -20,11 +20,21 @@ import { makeCatchallPage_app_loader } from "./templates/app-loader/catchall-pag
|
|
|
20
20
|
import { makePlasmicHostPage_app_loader } from "./templates/app-loader/plasmic-host";
|
|
21
21
|
import { makePlasmicInit_app_loader } from "./templates/app-loader/plasmic-init";
|
|
22
22
|
import { makePlasmicInitClient_app_loader } from "./templates/app-loader/plasmic-init-client";
|
|
23
|
+
import {
|
|
24
|
+
makeRobots_app,
|
|
25
|
+
makeSitemap_app_codegen,
|
|
26
|
+
makeSitemap_app_loader,
|
|
27
|
+
} from "./templates/app-seo";
|
|
23
28
|
import { makeCustomApp_pages_codegen } from "./templates/pages-codegen/app";
|
|
24
29
|
import { makePlasmicHostPage_pages_codegen } from "./templates/pages-codegen/plasmic-host";
|
|
25
30
|
import { makeCatchallPage_pages_loader } from "./templates/pages-loader/catchall-page";
|
|
26
31
|
import { makePlasmicHostPage_pages_loader } from "./templates/pages-loader/plasmic-host";
|
|
27
32
|
import { makePlasmicInit_pages_loader } from "./templates/pages-loader/plasmic-init";
|
|
33
|
+
import {
|
|
34
|
+
makeRobots_pages,
|
|
35
|
+
makeSitemap_pages_codegen,
|
|
36
|
+
makeSitemap_pages_loader,
|
|
37
|
+
} from "./templates/pages-seo";
|
|
28
38
|
|
|
29
39
|
export const nextjsStrategy: CPAStrategy = {
|
|
30
40
|
create: async (args) => {
|
|
@@ -124,6 +134,12 @@ async function generateFilesAppDir(args: GenerateFilesArgs) {
|
|
|
124
134
|
// Delete existing pages
|
|
125
135
|
deleteGlob(path.join(projectPath, "app", "page.*"));
|
|
126
136
|
|
|
137
|
+
// ./app/robots.ts
|
|
138
|
+
await fs.writeFile(
|
|
139
|
+
path.join(projectPath, "app", `robots.${jsOrTs}`),
|
|
140
|
+
makeRobots_app(jsOrTs)
|
|
141
|
+
);
|
|
142
|
+
|
|
127
143
|
if (scheme === "loader") {
|
|
128
144
|
// ./plasmic-init.ts
|
|
129
145
|
await fs.writeFile(
|
|
@@ -153,6 +169,12 @@ async function generateFilesAppDir(args: GenerateFilesArgs) {
|
|
|
153
169
|
path.join(projectPath, "app", "[[...catchall]]", `page.${jsOrTs}x`),
|
|
154
170
|
makeCatchallPage_app_loader(jsOrTs)
|
|
155
171
|
);
|
|
172
|
+
|
|
173
|
+
// ./app/sitemap.ts
|
|
174
|
+
await fs.writeFile(
|
|
175
|
+
path.join(projectPath, "app", `sitemap.${jsOrTs}`),
|
|
176
|
+
makeSitemap_app_loader(jsOrTs)
|
|
177
|
+
);
|
|
156
178
|
} else {
|
|
157
179
|
// ./plasmic-init-client.tsx
|
|
158
180
|
await fs.writeFile(
|
|
@@ -177,6 +199,12 @@ async function generateFilesAppDir(args: GenerateFilesArgs) {
|
|
|
177
199
|
projectPath,
|
|
178
200
|
});
|
|
179
201
|
|
|
202
|
+
// ./app/sitemap.ts
|
|
203
|
+
await fs.writeFile(
|
|
204
|
+
path.join(projectPath, "app", `sitemap.${jsOrTs}`),
|
|
205
|
+
makeSitemap_app_codegen(jsOrTs)
|
|
206
|
+
);
|
|
207
|
+
|
|
180
208
|
// Read plasmic.json so we can wire each top-level project's plasmic.css
|
|
181
209
|
// import directly into the root layout template.
|
|
182
210
|
const config = await getPlasmicConfig(projectPath, "nextjs", scheme);
|
|
@@ -216,6 +244,12 @@ async function generateFilesPagesDir(args: GenerateFilesArgs) {
|
|
|
216
244
|
// Delete existing pages
|
|
217
245
|
deleteGlob(path.join(projectPath, "pages", "*.*"));
|
|
218
246
|
|
|
247
|
+
// ./pages/robots.txt.ts
|
|
248
|
+
await fs.writeFile(
|
|
249
|
+
path.join(projectPath, "pages", `robots.txt.${jsOrTs}`),
|
|
250
|
+
makeRobots_pages(jsOrTs)
|
|
251
|
+
);
|
|
252
|
+
|
|
219
253
|
if (scheme === "loader") {
|
|
220
254
|
// ./plasmic-init.ts
|
|
221
255
|
await fs.writeFile(
|
|
@@ -237,6 +271,12 @@ async function generateFilesPagesDir(args: GenerateFilesArgs) {
|
|
|
237
271
|
path.join(projectPath, "pages", `[[...catchall]].${jsOrTs}x`),
|
|
238
272
|
makeCatchallPage_pages_loader(jsOrTs)
|
|
239
273
|
);
|
|
274
|
+
|
|
275
|
+
// ./pages/sitemap.xml.ts
|
|
276
|
+
await fs.writeFile(
|
|
277
|
+
path.join(projectPath, "pages", `sitemap.xml.${jsOrTs}`),
|
|
278
|
+
makeSitemap_pages_loader(jsOrTs)
|
|
279
|
+
);
|
|
240
280
|
} else {
|
|
241
281
|
// ./pages/plasmic-host.tsx
|
|
242
282
|
await fs.writeFile(
|
|
@@ -254,6 +294,12 @@ async function generateFilesPagesDir(args: GenerateFilesArgs) {
|
|
|
254
294
|
projectPath,
|
|
255
295
|
});
|
|
256
296
|
|
|
297
|
+
// ./pages/sitemap.xml.ts
|
|
298
|
+
await fs.writeFile(
|
|
299
|
+
path.join(projectPath, "pages", `sitemap.xml.${jsOrTs}`),
|
|
300
|
+
makeSitemap_pages_codegen(jsOrTs)
|
|
301
|
+
);
|
|
302
|
+
|
|
257
303
|
// Read plasmic.json so we can wire each top-level project's plasmic.css
|
|
258
304
|
// import directly into the _app template.
|
|
259
305
|
const config = await getPlasmicConfig(projectPath, "nextjs", scheme);
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { ifTs } from "../../utils/file-utils";
|
|
2
|
+
import { JsOrTs } from "../../utils/types";
|
|
3
|
+
|
|
4
|
+
const getSiteUrl = `// Set NEXT_PUBLIC_SITE_URL to pin the origin and keep this route static;
|
|
5
|
+
// otherwise it is derived per-request, which opts the route out of prerendering.
|
|
6
|
+
async function getSiteUrl() {
|
|
7
|
+
if (process.env.NEXT_PUBLIC_SITE_URL) {
|
|
8
|
+
return process.env.NEXT_PUBLIC_SITE_URL;
|
|
9
|
+
}
|
|
10
|
+
if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {
|
|
11
|
+
return \`https://\${process.env.VERCEL_PROJECT_PRODUCTION_URL}\`;
|
|
12
|
+
}
|
|
13
|
+
const h = await headers();
|
|
14
|
+
const proto = h.get("x-forwarded-proto") ?? "http";
|
|
15
|
+
return \`\${proto}://\${h.get("x-forwarded-host") ?? h.get("host")}\`;
|
|
16
|
+
}`;
|
|
17
|
+
|
|
18
|
+
function makeHeader(jsOrTs: JsOrTs) {
|
|
19
|
+
return `${ifTs(
|
|
20
|
+
jsOrTs,
|
|
21
|
+
`import type { MetadataRoute } from "next";\n`
|
|
22
|
+
)}import { headers } from "next/headers";\n`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function makeSignature(jsOrTs: JsOrTs) {
|
|
26
|
+
return `export default async function sitemap()${ifTs(
|
|
27
|
+
jsOrTs,
|
|
28
|
+
": Promise<MetadataRoute.Sitemap>"
|
|
29
|
+
)} {`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function makeSitemap_app_loader(jsOrTs: JsOrTs): string {
|
|
33
|
+
return `import { PLASMIC } from "@/plasmic-init";
|
|
34
|
+
${makeHeader(jsOrTs)}
|
|
35
|
+
export const revalidate = 60;
|
|
36
|
+
|
|
37
|
+
${getSiteUrl}
|
|
38
|
+
|
|
39
|
+
${makeSignature(jsOrTs)}
|
|
40
|
+
const siteUrl = await getSiteUrl();
|
|
41
|
+
|
|
42
|
+
// fetchPages() drops pages whose path takes a param, e.g. "/blog/[slug]".
|
|
43
|
+
const pages = await PLASMIC.fetchPages();
|
|
44
|
+
|
|
45
|
+
return pages.map((page) => ({
|
|
46
|
+
url: new URL(page.path, siteUrl).toString(),
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function makeSitemap_app_codegen(jsOrTs: JsOrTs): string {
|
|
53
|
+
const projects =
|
|
54
|
+
jsOrTs === "ts"
|
|
55
|
+
? `(plasmicJson.projects as {
|
|
56
|
+
components: { componentType: string; path?: string }[];
|
|
57
|
+
}[])`
|
|
58
|
+
: "plasmicJson.projects";
|
|
59
|
+
|
|
60
|
+
return `${makeHeader(jsOrTs)}import plasmicJson from "../plasmic.json";
|
|
61
|
+
|
|
62
|
+
${getSiteUrl}
|
|
63
|
+
|
|
64
|
+
${makeSignature(jsOrTs)}
|
|
65
|
+
const siteUrl = await getSiteUrl();
|
|
66
|
+
|
|
67
|
+
return ${projects}
|
|
68
|
+
.flatMap((project) => project.components)
|
|
69
|
+
.flatMap((component) =>
|
|
70
|
+
component.componentType === "page" &&
|
|
71
|
+
component.path &&
|
|
72
|
+
!component.path.includes("[")
|
|
73
|
+
? [
|
|
74
|
+
{
|
|
75
|
+
// next.config sets trailingSlash.
|
|
76
|
+
url: new URL(
|
|
77
|
+
component.path.replace(/\\/?$/, "/"),
|
|
78
|
+
siteUrl
|
|
79
|
+
).toString(),
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
: []
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function makeRobots_app(jsOrTs: JsOrTs): string {
|
|
89
|
+
return `${makeHeader(jsOrTs)}
|
|
90
|
+
${getSiteUrl}
|
|
91
|
+
|
|
92
|
+
export default async function robots()${ifTs(
|
|
93
|
+
jsOrTs,
|
|
94
|
+
": Promise<MetadataRoute.Robots>"
|
|
95
|
+
)} {
|
|
96
|
+
const siteUrl = await getSiteUrl();
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
rules: { userAgent: "*", allow: "/" },
|
|
100
|
+
sitemap: new URL("/sitemap.xml", siteUrl).toString(),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { ifTs } from "../../utils/file-utils";
|
|
2
|
+
import { JsOrTs } from "../../utils/types";
|
|
3
|
+
|
|
4
|
+
const siteUrl = ` // Set NEXT_PUBLIC_SITE_URL to pin the origin;
|
|
5
|
+
// otherwise it is derived per-request from the request headers.
|
|
6
|
+
const siteUrl =
|
|
7
|
+
process.env.NEXT_PUBLIC_SITE_URL ??
|
|
8
|
+
(process.env.VERCEL_PROJECT_PRODUCTION_URL
|
|
9
|
+
? \`https://\${process.env.VERCEL_PROJECT_PRODUCTION_URL}\`
|
|
10
|
+
: \`\${req.headers["x-forwarded-proto"] ?? "http"}://\${
|
|
11
|
+
req.headers["x-forwarded-host"] ?? req.headers.host
|
|
12
|
+
}\`);`;
|
|
13
|
+
|
|
14
|
+
function makeHeader(jsOrTs: JsOrTs) {
|
|
15
|
+
return ifTs(jsOrTs, `import type { GetServerSideProps } from "next";\n`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function makeSignature(jsOrTs: JsOrTs) {
|
|
19
|
+
return `export const getServerSideProps${ifTs(
|
|
20
|
+
jsOrTs,
|
|
21
|
+
": GetServerSideProps"
|
|
22
|
+
)} = async ({ req, res }) => {`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function makeSitemapXml(jsOrTs: JsOrTs) {
|
|
26
|
+
return `function escapeXml(str${ifTs(jsOrTs, ": string")}) {
|
|
27
|
+
return str
|
|
28
|
+
.replace(/&/g, "&")
|
|
29
|
+
.replace(/</g, "<")
|
|
30
|
+
.replace(/>/g, ">")
|
|
31
|
+
.replace(/"/g, """)
|
|
32
|
+
.replace(/'/g, "'");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function makeSitemapXml(urls${ifTs(jsOrTs, ": string[]")}) {
|
|
36
|
+
const entries = urls.map(
|
|
37
|
+
(url) => \` <url><loc>\${escapeXml(url)}</loc></url>\`
|
|
38
|
+
);
|
|
39
|
+
return \`<?xml version="1.0" encoding="UTF-8"?>
|
|
40
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
41
|
+
\${entries.join("\\n")}
|
|
42
|
+
</urlset>
|
|
43
|
+
\`;
|
|
44
|
+
}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function makeSitemap_pages_loader(jsOrTs: JsOrTs): string {
|
|
48
|
+
return `import { PLASMIC } from "@/plasmic-init";
|
|
49
|
+
${makeHeader(jsOrTs)}
|
|
50
|
+
${makeSitemapXml(jsOrTs)}
|
|
51
|
+
|
|
52
|
+
${makeSignature(jsOrTs)}
|
|
53
|
+
${siteUrl}
|
|
54
|
+
|
|
55
|
+
// fetchPages() drops pages whose path takes a param, e.g. "/blog/[slug]".
|
|
56
|
+
const pages = await PLASMIC.fetchPages();
|
|
57
|
+
const urls = pages.map((page) => new URL(page.path, siteUrl).toString());
|
|
58
|
+
|
|
59
|
+
res.setHeader("Content-Type", "application/xml; charset=utf-8");
|
|
60
|
+
res.write(makeSitemapXml(urls));
|
|
61
|
+
res.end();
|
|
62
|
+
return { props: {} };
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default function Sitemap() {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function makeSitemap_pages_codegen(jsOrTs: JsOrTs): string {
|
|
72
|
+
const projects =
|
|
73
|
+
jsOrTs === "ts"
|
|
74
|
+
? `(plasmicJson.projects as {
|
|
75
|
+
components: { componentType: string; path?: string }[];
|
|
76
|
+
}[])`
|
|
77
|
+
: "plasmicJson.projects";
|
|
78
|
+
|
|
79
|
+
return `${makeHeader(jsOrTs)}import plasmicJson from "../plasmic.json";
|
|
80
|
+
|
|
81
|
+
${makeSitemapXml(jsOrTs)}
|
|
82
|
+
|
|
83
|
+
${makeSignature(jsOrTs)}
|
|
84
|
+
${siteUrl}
|
|
85
|
+
|
|
86
|
+
const urls = ${projects}
|
|
87
|
+
.flatMap((project) => project.components)
|
|
88
|
+
.flatMap((component) =>
|
|
89
|
+
component.componentType === "page" &&
|
|
90
|
+
component.path &&
|
|
91
|
+
!component.path.includes("[")
|
|
92
|
+
? // next.config sets trailingSlash.
|
|
93
|
+
[new URL(component.path.replace(/\\/?$/, "/"), siteUrl).toString()]
|
|
94
|
+
: []
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
res.setHeader("Content-Type", "application/xml; charset=utf-8");
|
|
98
|
+
res.write(makeSitemapXml(urls));
|
|
99
|
+
res.end();
|
|
100
|
+
return { props: {} };
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default function Sitemap() {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function makeRobots_pages(jsOrTs: JsOrTs): string {
|
|
110
|
+
return `${ifTs(
|
|
111
|
+
jsOrTs,
|
|
112
|
+
`import type { GetServerSideProps } from "next";\n\n`
|
|
113
|
+
)}${makeSignature(jsOrTs)}
|
|
114
|
+
${siteUrl}
|
|
115
|
+
|
|
116
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
117
|
+
res.write(
|
|
118
|
+
\`User-agent: *\\nAllow: /\\n\\nSitemap: \${new URL(
|
|
119
|
+
"/sitemap.xml",
|
|
120
|
+
siteUrl
|
|
121
|
+
).toString()}\\n\`
|
|
122
|
+
);
|
|
123
|
+
res.end();
|
|
124
|
+
return { props: {} };
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export default function Robots() {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
}
|