Add /sitemap endpoint for generating sitemap.xml
Summary: Ref T3045 Reviewers: #testers, kuba-orlik Reviewed By: #testers, kuba-orlik Subscribers: kuba-orlik, jenkins-user Maniphest Tasks: T3045 Differential Revision: https://hub.sealcode.org/D1616
This commit is contained in:
parent
30c6a2f881
commit
7864f5c3cf
@ -8,6 +8,7 @@ import { imageRouter, RESPONSIVE_IMAGES_URL_PATH } from "../image-router.js";
|
|||||||
import { customUrlView } from "./middlewares/customUrlView.js";
|
import { customUrlView } from "./middlewares/customUrlView.js";
|
||||||
import mountAutoRoutes from "./routes.js";
|
import mountAutoRoutes from "./routes.js";
|
||||||
import _locreq from "locreq";
|
import _locreq from "locreq";
|
||||||
|
import sitemapPage from "../sitemap.xml.js";
|
||||||
const locreq = _locreq(new URL("./", import.meta.url).pathname);
|
const locreq = _locreq(new URL("./", import.meta.url).pathname);
|
||||||
|
|
||||||
export const mainRouter = (app: TheApp, koa_app: Koa, router: Router): void => {
|
export const mainRouter = (app: TheApp, koa_app: Koa, router: Router): void => {
|
||||||
@ -41,6 +42,11 @@ export const mainRouter = (app: TheApp, koa_app: Koa, router: Router): void => {
|
|||||||
ctx.body = { status: ctx.$app.status, started_at };
|
ctx.body = { status: ctx.$app.status, started_at };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get("/sitemap.xml", async (ctx) => {
|
||||||
|
ctx.set("Content-Type", "application/xml");
|
||||||
|
ctx.body = await sitemapPage.render(ctx);
|
||||||
|
});
|
||||||
|
|
||||||
router.use(RESPONSIVE_IMAGES_URL_PATH, imageRouter.getRoutes());
|
router.use(RESPONSIVE_IMAGES_URL_PATH, imageRouter.getRoutes());
|
||||||
|
|
||||||
mountAutoRoutes(router);
|
mountAutoRoutes(router);
|
||||||
|
|||||||
29
src/back/sitemap.xml.tsx
Normal file
29
src/back/sitemap.xml.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import type { Context } from "koa";
|
||||||
|
import { Page } from "@sealcode/sealgen";
|
||||||
|
|
||||||
|
export const actionName = "Sitemap";
|
||||||
|
|
||||||
|
async function generateSitemap(ctx: Context) {
|
||||||
|
const pages = await ctx.$app.collections.pages.list(ctx.$context).fetch();
|
||||||
|
|
||||||
|
let xml = `<?xml version="1.0" encoding="UTF-8"?>\n`;
|
||||||
|
xml += `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n`;
|
||||||
|
|
||||||
|
for (const page of pages.items) {
|
||||||
|
xml += ` <url>\n <loc>${ctx.origin.replace(/\/$/, "")}${page.get("url")}</loc>\n </url>\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
xml += `</urlset>\n`;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new (class SitemapPage extends Page {
|
||||||
|
async canAccess() {
|
||||||
|
return { canAccess: true, message: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
async render(ctx: Context) {
|
||||||
|
ctx.set("Content-Type", "application/xml");
|
||||||
|
return generateSitemap(ctx);
|
||||||
|
}
|
||||||
|
})();
|
||||||
54
tests/sitemap.test.ts
Normal file
54
tests/sitemap.test.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import * as assert from "node:assert";
|
||||||
|
import { test, expect } from "./backend-fixture";
|
||||||
|
|
||||||
|
test("sitemap returns expected XML for empty DB", async ({ backend, request }) => {
|
||||||
|
const response = await request.get(`${backend.url}/sitemap.xml`);
|
||||||
|
assert.strictEqual(response.status(), 200);
|
||||||
|
|
||||||
|
const actual = await response.text();
|
||||||
|
const expected = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
<url>
|
||||||
|
<loc>${backend.url}/</loc>
|
||||||
|
</url>
|
||||||
|
</urlset>
|
||||||
|
`;
|
||||||
|
assert.strictEqual(actual, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sitemap returns expected XML after creating a page via UI", async ({
|
||||||
|
page,
|
||||||
|
backend,
|
||||||
|
request,
|
||||||
|
}) => {
|
||||||
|
await page.goto(backend.url);
|
||||||
|
await page.getByRole("link", { name: "Go to Admin" }).click();
|
||||||
|
await page.getByPlaceholder("text").fill("admin");
|
||||||
|
await page.getByPlaceholder("text").press("Tab");
|
||||||
|
await page.getByPlaceholder("password").fill("adminadmin");
|
||||||
|
await page.getByRole("button", { name: "Wyślij" }).click();
|
||||||
|
|
||||||
|
await page.getByRole("link", { name: "Edit Pages" }).click();
|
||||||
|
await page.getByRole("link", { name: "Create" }).click();
|
||||||
|
await page.getByLabel("url").fill("/my-page/");
|
||||||
|
await page.getByLabel("title").fill("My Page");
|
||||||
|
await page.getByLabel("heading").fill("My Heading");
|
||||||
|
await page.getByLabel("description").fill("My Description");
|
||||||
|
await page.getByRole("button", { name: "Wyślij" }).click();
|
||||||
|
|
||||||
|
const response = await request.get(`${backend.url}/sitemap.xml`);
|
||||||
|
assert.strictEqual(response.status(), 200);
|
||||||
|
|
||||||
|
const actual = await response.text();
|
||||||
|
const expected = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
<url>
|
||||||
|
<loc>${backend.url}/</loc>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>${backend.url}/my-page/</loc>
|
||||||
|
</url>
|
||||||
|
</urlset>
|
||||||
|
`;
|
||||||
|
assert.strictEqual(actual, expected);
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user