refactor: better typings (#3634)
This commit is contained in:
parent
d9f6dcf6ea
commit
facfc4682f
5 changed files with 46 additions and 67 deletions
|
@ -141,7 +141,7 @@ export default {
|
|||
|
||||
### entryLimit
|
||||
|
||||
Non-negative `Number` of entries per sitemap file. Default value is 45000. A sitemap index and multiple sitemaps are created if you have more entries. See explanation on [Google](https://developers.google.com/search/docs/advanced/sitemaps/large-sitemaps).
|
||||
Non-negative `Number` of entries per sitemap file. Default value is 45000. A sitemap index and multiple sitemaps are created if you have more entries. See explanation about large sitemaps on [Google](https://developers.google.com/search/docs/advanced/sitemaps/large-sitemaps).
|
||||
|
||||
__astro.config.mjs__
|
||||
|
||||
|
@ -166,7 +166,7 @@ export default {
|
|||
|
||||
`lastmod` - The date of page last modification.
|
||||
|
||||
`changefreq` and `priority` are ignored by Google.
|
||||
The `changefreq` and `priority` are ignored by Google.
|
||||
|
||||
See detailed explanation of sitemap specific options on [sitemap.org](https://www.sitemaps.org/protocol.html).
|
||||
|
||||
|
@ -194,12 +194,12 @@ export default {
|
|||
|
||||
Async or sync function called for each sitemap entry just before writing to a disk.
|
||||
|
||||
It receives as parameter `SitemapItem` object which consists of `url` (required, absolute page URL) and optional `changefreq`, `lastmod`, `priority` and `links` properties.
|
||||
It receives as parameter a `SitemapItem` object which consists of `url` (required, absolute page URL) and optional `changefreq`, `lastmod` (ISO formatted date, `String` type), `priority` and `links` properties.
|
||||
|
||||
Optional `links` property contains a `LinkItem` list of alternate pages including a parent page.
|
||||
`LinkItem` type has two required fields: `url` (the fully-qualified URL for the version of this page for the specified language) and `hreflang` (a supported language code targeted by this version of the page).
|
||||
Optional `links` property contains the `LinkItem` list of alternate pages including a parent page.
|
||||
The `LinkItem` type has two required fields: `url` (the fully-qualified URL for the version of this page for the specified language) and `lang` (a supported language code targeted by this version of the page).
|
||||
|
||||
`serialize` function should return `SitemapItem`, touched or not.
|
||||
The `serialize` function should return `SitemapItem`, touched or not.
|
||||
|
||||
The example below shows the ability to add the sitemap specific properties individually.
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
export const changefreqValues = [
|
||||
'always',
|
||||
'hourly',
|
||||
'daily',
|
||||
'weekly',
|
||||
'monthly',
|
||||
'yearly',
|
||||
'never',
|
||||
] as const;
|
|
@ -1,19 +1,16 @@
|
|||
import { SitemapItemLoose } from 'sitemap';
|
||||
|
||||
import type { SitemapOptions } from './index';
|
||||
import type { SitemapOptions, SitemapItem } from './index';
|
||||
import { parseUrl } from './utils/parse-url';
|
||||
|
||||
const STATUS_CODE_PAGE_REGEXP = /\/[0-9]{3}\/?$/;
|
||||
|
||||
/** Construct sitemap.xml given a set of URLs */
|
||||
export function generateSitemap(pages: string[], finalSiteUrl: string, opts: SitemapOptions) {
|
||||
const { changefreq, priority: prioritySrc, lastmod: lastmodSrc, i18n } = opts || {};
|
||||
const { changefreq, priority, lastmod: lastmodSrc, i18n } = opts!;
|
||||
// TODO: find way to respect <link rel="canonical"> URLs here
|
||||
const urls = [...pages].filter((url) => !STATUS_CODE_PAGE_REGEXP.test(url));
|
||||
urls.sort((a, b) => a.localeCompare(b, 'en', { numeric: true })); // sort alphabetically so sitemap is same each time
|
||||
|
||||
const lastmod = lastmodSrc?.toISOString();
|
||||
const priority = typeof prioritySrc === 'number' ? prioritySrc : undefined;
|
||||
|
||||
const { locales, defaultLocale } = i18n || {};
|
||||
const localeCodes = Object.keys(locales || {});
|
||||
|
@ -27,7 +24,7 @@ export function generateSitemap(pages: string[], finalSiteUrl: string, opts: Sit
|
|||
return result?.locale;
|
||||
};
|
||||
|
||||
const urlData = urls.map((url) => {
|
||||
const urlData: SitemapItem[] = urls.map((url) => {
|
||||
let links;
|
||||
if (defaultLocale && locales) {
|
||||
const currentPath = getPath(url);
|
||||
|
@ -47,8 +44,8 @@ export function generateSitemap(pages: string[], finalSiteUrl: string, opts: Sit
|
|||
links,
|
||||
lastmod,
|
||||
priority,
|
||||
changefreq, // : changefreq as EnumChangefreq,
|
||||
} as SitemapItemLoose;
|
||||
changefreq,
|
||||
};
|
||||
});
|
||||
|
||||
return urlData;
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import type { AstroConfig, AstroIntegration } from 'astro';
|
||||
import { LinkItem as LinkItemBase, simpleSitemapAndIndex, SitemapItemLoose } from 'sitemap';
|
||||
import { LinkItem as LinkItemBase, simpleSitemapAndIndex, SitemapItemLoose, EnumChangefreq } from 'sitemap';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { ZodError } from 'zod';
|
||||
|
||||
import { changefreqValues } from './constants';
|
||||
import { generateSitemap } from './generate-sitemap';
|
||||
import { Logger } from './utils/logger';
|
||||
import { validateOptions } from './validate-options';
|
||||
|
||||
export type ChangeFreq = typeof changefreqValues[number];
|
||||
export type ChangeFreq = EnumChangefreq;
|
||||
export type SitemapItem = Pick<
|
||||
SitemapItemLoose,
|
||||
'url' | 'lastmod' | 'changefreq' | 'priority' | 'links'
|
||||
|
@ -34,7 +33,7 @@ export type SitemapOptions =
|
|||
priority?: number;
|
||||
|
||||
// called for each sitemap item just before to save them on disk, sync or async
|
||||
serialize?(item: SitemapItemLoose): SitemapItemLoose;
|
||||
serialize?(item: SitemapItem): SitemapItem | Promise<SitemapItem>;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
|
@ -103,7 +102,7 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => {
|
|||
|
||||
if (serialize) {
|
||||
try {
|
||||
const serializedUrls: SitemapItemLoose[] = [];
|
||||
const serializedUrls: SitemapItem[] = [];
|
||||
for (const item of urlData) {
|
||||
const serialized = await Promise.resolve(serialize(item));
|
||||
serializedUrls.push(serialized);
|
||||
|
|
|
@ -1,47 +1,39 @@
|
|||
import { z } from 'zod';
|
||||
import { EnumChangefreq as ChangeFreq } from 'sitemap';
|
||||
import { SITEMAP_CONFIG_DEFAULTS } from './config-defaults';
|
||||
import { changefreqValues } from './constants';
|
||||
|
||||
const localeKeySchema = () => z.string().min(1);
|
||||
|
||||
const isFunction = (fn: any) => fn instanceof Function;
|
||||
|
||||
const fnSchema = () =>
|
||||
z
|
||||
.any()
|
||||
.refine((val) => !val || isFunction(val), { message: 'Not a function' })
|
||||
.optional();
|
||||
const localeKeySchema = z.string().min(1);
|
||||
|
||||
export const SitemapOptionsSchema = z
|
||||
.object({
|
||||
filter: fnSchema(),
|
||||
customPages: z.string().url().array().optional(),
|
||||
canonicalURL: z.string().url().optional(),
|
||||
.object({
|
||||
filter: z.function().args(z.string()).returns(z.boolean()).optional(),
|
||||
customPages: z.string().url().array().optional(),
|
||||
canonicalURL: z.string().url().optional(),
|
||||
|
||||
i18n: z
|
||||
.object({
|
||||
defaultLocale: localeKeySchema(),
|
||||
locales: z.record(
|
||||
localeKeySchema(),
|
||||
z
|
||||
.string()
|
||||
.min(2)
|
||||
.regex(/^[a-zA-Z\-]+$/gm, {
|
||||
message: 'Only English alphabet symbols and hyphen allowed',
|
||||
})
|
||||
),
|
||||
})
|
||||
.refine((val) => !val || val.locales[val.defaultLocale], {
|
||||
message: '`defaultLocale` must exists in `locales` keys',
|
||||
})
|
||||
.optional(),
|
||||
i18n: z
|
||||
.object({
|
||||
defaultLocale: localeKeySchema,
|
||||
locales: z.record(
|
||||
localeKeySchema,
|
||||
z
|
||||
.string()
|
||||
.min(2)
|
||||
.regex(/^[a-zA-Z\-]+$/gm, {
|
||||
message: 'Only English alphabet symbols and hyphen allowed',
|
||||
}),
|
||||
),
|
||||
})
|
||||
.refine((val) => !val || val.locales[val.defaultLocale], {
|
||||
message: '`defaultLocale` must exist in `locales` keys',
|
||||
})
|
||||
.optional(),
|
||||
|
||||
entryLimit: z.number().nonnegative().default(SITEMAP_CONFIG_DEFAULTS.entryLimit),
|
||||
serialize: fnSchema(),
|
||||
entryLimit: z.number().nonnegative().optional().default(SITEMAP_CONFIG_DEFAULTS.entryLimit),
|
||||
serialize: z.function().args(z.any()).returns(z.any()).optional(),
|
||||
|
||||
changefreq: z.enum(changefreqValues).optional(),
|
||||
lastmod: z.date().optional(),
|
||||
priority: z.number().min(0).max(1).optional(),
|
||||
})
|
||||
.strict()
|
||||
.default(SITEMAP_CONFIG_DEFAULTS);
|
||||
changefreq: z.nativeEnum(ChangeFreq).optional(),
|
||||
lastmod: z.date().optional(),
|
||||
priority: z.number().min(0).max(1).optional(),
|
||||
})
|
||||
.strict()
|
||||
.default(SITEMAP_CONFIG_DEFAULTS);
|
||||
|
|
Loading…
Reference in a new issue