feat: HTML sitemap pages and footer link
- the module registers seo-sitemap-<locale> at seo.htmlSitemap.paths (defaults pl /mapa-strony, en /sitemap) and seo-sitemap-group-<locale> at <path>/:group (plus <path>/:group/<segment>/:page in the path form); a path an app page already has stays the app's - SeoHtmlSitemapPage (global, overridable): H1, an H2 per non-empty group, categories nested, a large group's link to its group page, sitemap.empty; group pages with a built trail, page suffix and <SeoPagination>; 404 for an unknown group or a page past the last, 301 for ?page=1, 503 when the sitemap API fails - GET /api/__seo__/sitemap proxies the sitemap plugin's HTML API (only while the CMS has the HTML sitemap on for the locale) - <SeoSitemapLink>: the footer link while the HTML sitemap is on - L3 default styles
This commit is contained in:
@@ -19,6 +19,12 @@
|
||||
// GET /_sitemap/files/<file> <dir>/seo/root/<file>, else 404;
|
||||
// sitemap-fail-*.xml answers 500
|
||||
// GET /_sitemap/indexnow/<key>.txt <dir>/seo/indexnow/<key>.txt, else 404
|
||||
// GET /_sitemap/api/v1/html?locale= the HTML sitemap overview from
|
||||
// <dir>/seo/html.json (overview.<locale>),
|
||||
// else 404
|
||||
// GET /_sitemap/api/v1/html/<group> one group page (groups.<locale>.<group>.<page>,
|
||||
// ?locale=&page= page 1 by default), else 404; the
|
||||
// group fail answers 500
|
||||
//
|
||||
// It records every request (with the parsed JSON body of a POST) so a smoke
|
||||
// run can assert header forwarding, resolve counts and the 404 reports.
|
||||
@@ -65,7 +71,10 @@ export function startFixtureApi({ dir, port = 0, token = FIXTURE_NOTFOUND_TOKEN,
|
||||
let answers = {}
|
||||
/** @type {unknown} */
|
||||
let siteAnswer = null
|
||||
/** @type {any} */
|
||||
let html = {}
|
||||
const load = () => {
|
||||
html = readJson(join(dir, 'seo', 'html.json')) ?? {}
|
||||
answers = { ...(readJson(join(dir, 'resolve.json')) ?? {}), ...(readJson(join(dir, 'seo', 'resolve.json')) ?? {}) }
|
||||
siteAnswer = site ? readJson(join(dir, 'seo', siteFile)) : null
|
||||
}
|
||||
@@ -90,6 +99,13 @@ export function startFixtureApi({ dir, port = 0, token = FIXTURE_NOTFOUND_TOKEN,
|
||||
if (files && req.method === 'GET') return fileAnswer(join(dir, 'seo', 'root', files[1]), files[1])
|
||||
const key = /^\/_sitemap\/indexnow\/([A-Za-z0-9-]{8,128}\.txt)$/.exec(url.pathname)
|
||||
if (key && req.method === 'GET') return fileAnswer(join(dir, 'seo', 'indexnow', key[1]), key[1])
|
||||
const htmlGroup = /^\/_sitemap\/api\/v1\/html(?:\/([a-z0-9-]+))?$/.exec(url.pathname)
|
||||
if (htmlGroup && req.method === 'GET') {
|
||||
const locale = url.searchParams.get('locale') ?? ''
|
||||
if (htmlGroup[1] === 'fail') return { status: 500, body: { error: 'backend failure' } }
|
||||
const hit = htmlGroup[1] ? html.groups?.[locale]?.[htmlGroup[1]]?.[url.searchParams.get('page') ?? '1'] : html.overview?.[locale]
|
||||
return hit ? { status: 200, body: hit } : { status: 404, body: { error: 'not_found' } }
|
||||
}
|
||||
if (!url.pathname.startsWith(PREFIX + '/')) return { status: 404, body: { error: 'not_found' } }
|
||||
const path = url.pathname.slice(PREFIX.length)
|
||||
if (path === '/resolve' && req.method === 'GET') {
|
||||
|
||||
Reference in New Issue
Block a user