From 7ab52d40dbca1858a12204bb29cd31f6ac2a26ce Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Sun, 12 Jun 2022 11:08:00 +0300 Subject: [PATCH 1/8] feat: extended sitemap functionality --- .../integrations-playground/astro.config.mjs | 1 + examples/sitemap/advanced/.gitignore | 18 ++ examples/sitemap/advanced/.npmrc | 2 + examples/sitemap/advanced/.stackblitzrc | 6 + examples/sitemap/advanced/README.md | 3 + examples/sitemap/advanced/astro.config.ts | 8 + examples/sitemap/advanced/package.json | 17 ++ examples/sitemap/advanced/public/favicon.ico | Bin 0 -> 4286 bytes examples/sitemap/advanced/sandbox.config.json | 11 + examples/sitemap/advanced/sitemap.config.ts | 28 +++ examples/sitemap/advanced/src/pages/404.astro | 14 ++ .../advanced/src/pages/exclude-this.astro | 13 + .../sitemap/advanced/src/pages/index.astro | 15 ++ .../advanced/src/pages/second-page.astro | 13 + .../advanced/src/pages/special-page.astro | 13 + examples/sitemap/advanced/tsconfig.json | 15 ++ examples/sitemap/basic/.gitignore | 18 ++ examples/sitemap/basic/.npmrc | 2 + examples/sitemap/basic/.stackblitzrc | 6 + examples/sitemap/basic/README.md | 3 + examples/sitemap/basic/astro.config.ts | 9 + examples/sitemap/basic/package.json | 17 ++ examples/sitemap/basic/public/favicon.ico | Bin 0 -> 4286 bytes examples/sitemap/basic/sandbox.config.json | 11 + examples/sitemap/basic/src/pages/index.astro | 12 + .../sitemap/basic/src/pages/second-page.astro | 13 + examples/sitemap/basic/tsconfig.json | 15 ++ examples/sitemap/i18n/.gitignore | 18 ++ examples/sitemap/i18n/.npmrc | 2 + examples/sitemap/i18n/.stackblitzrc | 6 + examples/sitemap/i18n/README.md | 9 + examples/sitemap/i18n/astro.config.ts | 10 + examples/sitemap/i18n/package.json | 16 ++ examples/sitemap/i18n/sandbox.config.json | 11 + examples/sitemap/i18n/sitemap.config.ts | 15 ++ .../i18n/src/components/LanguageSwitch.astro | 45 ++++ examples/sitemap/i18n/src/i18n.ts | 25 ++ .../i18n/src/images/logomark-light.png | Bin 0 -> 94580 bytes .../i18n/src/images/logomark-light.svg | 15 ++ examples/sitemap/i18n/src/pages/404.astro | 17 ++ .../sitemap/i18n/src/pages/[locale]/404.astro | 32 +++ .../i18n/src/pages/[locale]/index.astro | 38 +++ .../i18n/src/pages/[locale]/second-page.astro | 36 +++ examples/sitemap/i18n/src/pages/index.astro | 21 ++ .../sitemap/i18n/src/pages/second-page.astro | 19 ++ examples/sitemap/i18n/tsconfig.json | 15 ++ package.json | 6 + packages/integrations/sitemap/README.md | 199 ++++++++++++++- packages/integrations/sitemap/package.json | 12 +- .../integrations/sitemap/src/constants.ts | 1 + .../sitemap/src/generate-sitemap.ts | 55 +++++ packages/integrations/sitemap/src/index.ts | 233 +++++++++++------- .../integrations/sitemap/src/process-pages.ts | 39 +++ packages/integrations/sitemap/src/schema.ts | 52 ++++ .../sitemap/src/utils/is-object-empty.ts | 10 + .../sitemap/src/utils/is-valid-url.ts | 13 + .../integrations/sitemap/src/utils/logger.ts | 46 ++++ .../sitemap/src/utils/parse-url.ts | 28 +++ .../integrations/sitemap/src/validate-opts.ts | 16 ++ .../integrations/sitemap/src/with-options.ts | 20 ++ pnpm-lock.yaml | 80 +++++- 61 files changed, 1349 insertions(+), 94 deletions(-) create mode 100644 examples/sitemap/advanced/.gitignore create mode 100644 examples/sitemap/advanced/.npmrc create mode 100644 examples/sitemap/advanced/.stackblitzrc create mode 100644 examples/sitemap/advanced/README.md create mode 100644 examples/sitemap/advanced/astro.config.ts create mode 100644 examples/sitemap/advanced/package.json create mode 100644 examples/sitemap/advanced/public/favicon.ico create mode 100644 examples/sitemap/advanced/sandbox.config.json create mode 100644 examples/sitemap/advanced/sitemap.config.ts create mode 100644 examples/sitemap/advanced/src/pages/404.astro create mode 100644 examples/sitemap/advanced/src/pages/exclude-this.astro create mode 100644 examples/sitemap/advanced/src/pages/index.astro create mode 100644 examples/sitemap/advanced/src/pages/second-page.astro create mode 100644 examples/sitemap/advanced/src/pages/special-page.astro create mode 100644 examples/sitemap/advanced/tsconfig.json create mode 100644 examples/sitemap/basic/.gitignore create mode 100644 examples/sitemap/basic/.npmrc create mode 100644 examples/sitemap/basic/.stackblitzrc create mode 100644 examples/sitemap/basic/README.md create mode 100644 examples/sitemap/basic/astro.config.ts create mode 100644 examples/sitemap/basic/package.json create mode 100644 examples/sitemap/basic/public/favicon.ico create mode 100644 examples/sitemap/basic/sandbox.config.json create mode 100644 examples/sitemap/basic/src/pages/index.astro create mode 100644 examples/sitemap/basic/src/pages/second-page.astro create mode 100644 examples/sitemap/basic/tsconfig.json create mode 100644 examples/sitemap/i18n/.gitignore create mode 100644 examples/sitemap/i18n/.npmrc create mode 100644 examples/sitemap/i18n/.stackblitzrc create mode 100644 examples/sitemap/i18n/README.md create mode 100644 examples/sitemap/i18n/astro.config.ts create mode 100644 examples/sitemap/i18n/package.json create mode 100644 examples/sitemap/i18n/sandbox.config.json create mode 100644 examples/sitemap/i18n/sitemap.config.ts create mode 100644 examples/sitemap/i18n/src/components/LanguageSwitch.astro create mode 100644 examples/sitemap/i18n/src/i18n.ts create mode 100644 examples/sitemap/i18n/src/images/logomark-light.png create mode 100644 examples/sitemap/i18n/src/images/logomark-light.svg create mode 100644 examples/sitemap/i18n/src/pages/404.astro create mode 100644 examples/sitemap/i18n/src/pages/[locale]/404.astro create mode 100644 examples/sitemap/i18n/src/pages/[locale]/index.astro create mode 100644 examples/sitemap/i18n/src/pages/[locale]/second-page.astro create mode 100644 examples/sitemap/i18n/src/pages/index.astro create mode 100644 examples/sitemap/i18n/src/pages/second-page.astro create mode 100644 examples/sitemap/i18n/tsconfig.json create mode 100644 packages/integrations/sitemap/src/constants.ts create mode 100644 packages/integrations/sitemap/src/generate-sitemap.ts create mode 100644 packages/integrations/sitemap/src/process-pages.ts create mode 100644 packages/integrations/sitemap/src/schema.ts create mode 100644 packages/integrations/sitemap/src/utils/is-object-empty.ts create mode 100644 packages/integrations/sitemap/src/utils/is-valid-url.ts create mode 100644 packages/integrations/sitemap/src/utils/logger.ts create mode 100644 packages/integrations/sitemap/src/utils/parse-url.ts create mode 100644 packages/integrations/sitemap/src/validate-opts.ts create mode 100644 packages/integrations/sitemap/src/with-options.ts diff --git a/examples/integrations-playground/astro.config.mjs b/examples/integrations-playground/astro.config.mjs index a7c3d4a0b7a2..939d228669c3 100644 --- a/examples/integrations-playground/astro.config.mjs +++ b/examples/integrations-playground/astro.config.mjs @@ -9,5 +9,6 @@ import solid from '@astrojs/solid-js'; // https://astro.build/config export default defineConfig({ + site: 'https://example.com', integrations: [lit(), react(), tailwind(), turbolinks(), partytown(), sitemap(), solid()], }); diff --git a/examples/sitemap/advanced/.gitignore b/examples/sitemap/advanced/.gitignore new file mode 100644 index 000000000000..6e9005893238 --- /dev/null +++ b/examples/sitemap/advanced/.gitignore @@ -0,0 +1,18 @@ +# build output +dist/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/examples/sitemap/advanced/.npmrc b/examples/sitemap/advanced/.npmrc new file mode 100644 index 000000000000..ef83021af3ec --- /dev/null +++ b/examples/sitemap/advanced/.npmrc @@ -0,0 +1,2 @@ +# Expose Astro dependencies for `pnpm` users +shamefully-hoist=true diff --git a/examples/sitemap/advanced/.stackblitzrc b/examples/sitemap/advanced/.stackblitzrc new file mode 100644 index 000000000000..0dfa8f1e0565 --- /dev/null +++ b/examples/sitemap/advanced/.stackblitzrc @@ -0,0 +1,6 @@ +{ + "startCommand": "npm start", + "env": { + "ENABLE_CJS_IMPORTS": true + } +} diff --git a/examples/sitemap/advanced/README.md b/examples/sitemap/advanced/README.md new file mode 100644 index 000000000000..ab7786383aa4 --- /dev/null +++ b/examples/sitemap/advanced/README.md @@ -0,0 +1,3 @@ +# Demo for @astrojs/sitemap integration + +Play this demo [online](https://stackblitz.com/fork/github/withastro/astro/tree/main/examples/sitemap/advanced). diff --git a/examples/sitemap/advanced/astro.config.ts b/examples/sitemap/advanced/astro.config.ts new file mode 100644 index 000000000000..b45aa1c588e0 --- /dev/null +++ b/examples/sitemap/advanced/astro.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'astro/config'; +import sitemap from '@astrojs/sitemap'; +import sitemapConfig from './sitemap.config'; + +// https://astro.build/config +export default defineConfig({ + integrations: [sitemap(sitemapConfig)], +}); diff --git a/examples/sitemap/advanced/package.json b/examples/sitemap/advanced/package.json new file mode 100644 index 000000000000..c1174a3dee5b --- /dev/null +++ b/examples/sitemap/advanced/package.json @@ -0,0 +1,17 @@ +{ + "name": "@example/sitemap-advanced", + "version": "0.0.1", + "private": true, + "license": "MIT", + "type": "module", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview" + }, + "devDependencies": { + "astro": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/examples/sitemap/advanced/public/favicon.ico b/examples/sitemap/advanced/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..578ad458b8906c08fbed84f42b045fea04db89d1 GIT binary patch literal 4286 zcmchZF=!M)6ox0}Fc8GdTHG!cdIY>nA!3n2f|wxIl0rn}Hl#=uf>?-!2r&jMEF^_k zh**lGut*gwBmoNv7AaB&2~nbzULg{WBhPQ{ZVzvF_HL8Cb&hv$_s#qN|IO^o>?+mA zuTW6tU%k~z<&{z+7$G%*nRsTcEO|90xy<-G5&JTt%CgZZCDT4%R?+{Vd^wh>P8_)} z`+dF$HQb9!>1o`Ivn;GInlCw{9T@Rt%q+d^T3Ke%cxkk;$v`{s^zCB9nHAv6w$Vbn z8fb<+eQTNM`;rf9#obfGnV#3+OQEUv4gU;{oA@zol%keY9-e>4W>p7AHmH~&!P7f7!Uj` zwgFeQ=<3G4O;mwWO`L!=R-=y3_~-DPjH3W^3f&jjCfC$o#|oGaahSL`_=f?$&Aa+W z2h8oZ+@?NUcjGW|aWJfbM*ZzxzmCPY`b~RobNrrj=rd`=)8-j`iSW64@0_b6?;GYk zNB+-fzOxlqZ?`y{OA$WigtZXa8)#p#=DPYxH=VeC_Q5q9Cv`mvW6*zU&Gnp1;oPM6 zaK_B3j(l^FyJgYeE9RrmDyhE7W2}}nW%ic#0v@i1E!yTey$W)U>fyd+!@2hWQ!Wa==NAtKoj`f3tp4y$Al`e;?)76?AjdaRR>|?&r)~3Git> zb1)a?uiv|R0_{m#A9c;7)eZ1y6l@yQ#oE*>(Z2fG-&&smPa2QTW>m*^K65^~`coP$ z8y5Y?iS<4Gz{Zg##$1mk)u-0;X|!xu^FCr;ce~X<&UWE&pBgqfYmEJTzpK9I%vr%b z3Ksd6qlPJLI%HFfeXK_^|BXiKZC>Ocu(Kk6hD3G-8usLzVG^q00Qh gz)s7ge@$ApxGu7=(6IGIk+uG&HTev01^#CH3$(Wk5&!@I literal 0 HcmV?d00001 diff --git a/examples/sitemap/advanced/sandbox.config.json b/examples/sitemap/advanced/sandbox.config.json new file mode 100644 index 000000000000..9178af77d7de --- /dev/null +++ b/examples/sitemap/advanced/sandbox.config.json @@ -0,0 +1,11 @@ +{ + "infiniteLoopProtection": true, + "hardReloadOnChange": false, + "view": "browser", + "template": "node", + "container": { + "port": 3000, + "startScript": "start", + "node": "14" + } +} diff --git a/examples/sitemap/advanced/sitemap.config.ts b/examples/sitemap/advanced/sitemap.config.ts new file mode 100644 index 000000000000..6ddea6f3d1f7 --- /dev/null +++ b/examples/sitemap/advanced/sitemap.config.ts @@ -0,0 +1,28 @@ +const canonicalURL = 'https://example.com'; + +const sitemapConfig = { + filter: (page) => !/exclude-this/.test(page), // exclude pages from sitemap + customPages: [`${canonicalURL}/virtual-one.html`, `${canonicalURL}/virtual-two.html`], + canonicalURL, + + createLinkInHead: true, + + serialize(item) { + if (/special-page/.test(item.url)) { + item.changefreq = 'daily'; + item.lastmod = new Date(); + item.priority = 0.9; + } + return item; + }, + + // The integration creates a separate `sitemap-${i}.xml` file for each batch of 2, then adds this file to index - `sitemap-index.xml`. + entryLimit: 2, // default - 45000 + + // sitemap specific + changefreq: 'yearly', + lastmod: new Date('2019-12-31'), + priority: 0.4, +}; + +export default sitemapConfig; diff --git a/examples/sitemap/advanced/src/pages/404.astro b/examples/sitemap/advanced/src/pages/404.astro new file mode 100644 index 000000000000..6abd145f8c4b --- /dev/null +++ b/examples/sitemap/advanced/src/pages/404.astro @@ -0,0 +1,14 @@ +--- +--- + + + + + 404 + + +

404

+

Not Found

+ Back to Home + + diff --git a/examples/sitemap/advanced/src/pages/exclude-this.astro b/examples/sitemap/advanced/src/pages/exclude-this.astro new file mode 100644 index 000000000000..e7b23e2d997c --- /dev/null +++ b/examples/sitemap/advanced/src/pages/exclude-this.astro @@ -0,0 +1,13 @@ +--- +--- + + + + + Exclude this page + + +

Exclude this pade

+ Back to Home + + diff --git a/examples/sitemap/advanced/src/pages/index.astro b/examples/sitemap/advanced/src/pages/index.astro new file mode 100644 index 000000000000..bd25ea7e2b42 --- /dev/null +++ b/examples/sitemap/advanced/src/pages/index.astro @@ -0,0 +1,15 @@ +--- +--- + + + + + Astro + + +

Astro

+ Second page + Special page + Exclude this page + + diff --git a/examples/sitemap/advanced/src/pages/second-page.astro b/examples/sitemap/advanced/src/pages/second-page.astro new file mode 100644 index 000000000000..77cfad9f8550 --- /dev/null +++ b/examples/sitemap/advanced/src/pages/second-page.astro @@ -0,0 +1,13 @@ +--- +--- + + + + + Second page + + +

Second page

+ Back to Home + + diff --git a/examples/sitemap/advanced/src/pages/special-page.astro b/examples/sitemap/advanced/src/pages/special-page.astro new file mode 100644 index 000000000000..54b3bcce1825 --- /dev/null +++ b/examples/sitemap/advanced/src/pages/special-page.astro @@ -0,0 +1,13 @@ +--- +--- + + + + + Special page + + +

Special page

+ Back to Home + + diff --git a/examples/sitemap/advanced/tsconfig.json b/examples/sitemap/advanced/tsconfig.json new file mode 100644 index 000000000000..7ac81809afda --- /dev/null +++ b/examples/sitemap/advanced/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + // Enable top-level await, and other modern ESM features. + "target": "ESNext", + "module": "ESNext", + // Enable node-style module resolution, for things like npm package imports. + "moduleResolution": "node", + // Enable JSON imports. + "resolveJsonModule": true, + // Enable stricter transpilation for better output. + "isolatedModules": true, + // Add type definitions for our Vite runtime. + "types": ["vite/client"] + } +} diff --git a/examples/sitemap/basic/.gitignore b/examples/sitemap/basic/.gitignore new file mode 100644 index 000000000000..6e9005893238 --- /dev/null +++ b/examples/sitemap/basic/.gitignore @@ -0,0 +1,18 @@ +# build output +dist/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/examples/sitemap/basic/.npmrc b/examples/sitemap/basic/.npmrc new file mode 100644 index 000000000000..ef83021af3ec --- /dev/null +++ b/examples/sitemap/basic/.npmrc @@ -0,0 +1,2 @@ +# Expose Astro dependencies for `pnpm` users +shamefully-hoist=true diff --git a/examples/sitemap/basic/.stackblitzrc b/examples/sitemap/basic/.stackblitzrc new file mode 100644 index 000000000000..0dfa8f1e0565 --- /dev/null +++ b/examples/sitemap/basic/.stackblitzrc @@ -0,0 +1,6 @@ +{ + "startCommand": "npm start", + "env": { + "ENABLE_CJS_IMPORTS": true + } +} diff --git a/examples/sitemap/basic/README.md b/examples/sitemap/basic/README.md new file mode 100644 index 000000000000..d690ff6cca7e --- /dev/null +++ b/examples/sitemap/basic/README.md @@ -0,0 +1,3 @@ +# Demo for @astrojs/sitemap integration + +Play this demo [online](https://stackblitz.com/fork/github/withastro/astro/tree/main/examples/sitemap/basic). diff --git a/examples/sitemap/basic/astro.config.ts b/examples/sitemap/basic/astro.config.ts new file mode 100644 index 000000000000..752cf3cfe6f6 --- /dev/null +++ b/examples/sitemap/basic/astro.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'astro/config'; +import sitemap from '@astrojs/sitemap'; + +// https://astro.build/config +export default defineConfig({ + site: 'https://example.com', + base: 'test', + integrations: [sitemap()], +}); diff --git a/examples/sitemap/basic/package.json b/examples/sitemap/basic/package.json new file mode 100644 index 000000000000..b232e45f1c6b --- /dev/null +++ b/examples/sitemap/basic/package.json @@ -0,0 +1,17 @@ +{ + "name": "@example/sitemap-basic", + "version": "0.0.1", + "private": true, + "license": "MIT", + "type": "module", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview" + }, + "devDependencies": { + "astro": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/examples/sitemap/basic/public/favicon.ico b/examples/sitemap/basic/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..578ad458b8906c08fbed84f42b045fea04db89d1 GIT binary patch literal 4286 zcmchZF=!M)6ox0}Fc8GdTHG!cdIY>nA!3n2f|wxIl0rn}Hl#=uf>?-!2r&jMEF^_k zh**lGut*gwBmoNv7AaB&2~nbzULg{WBhPQ{ZVzvF_HL8Cb&hv$_s#qN|IO^o>?+mA zuTW6tU%k~z<&{z+7$G%*nRsTcEO|90xy<-G5&JTt%CgZZCDT4%R?+{Vd^wh>P8_)} z`+dF$HQb9!>1o`Ivn;GInlCw{9T@Rt%q+d^T3Ke%cxkk;$v`{s^zCB9nHAv6w$Vbn z8fb<+eQTNM`;rf9#obfGnV#3+OQEUv4gU;{oA@zol%keY9-e>4W>p7AHmH~&!P7f7!Uj` zwgFeQ=<3G4O;mwWO`L!=R-=y3_~-DPjH3W^3f&jjCfC$o#|oGaahSL`_=f?$&Aa+W z2h8oZ+@?NUcjGW|aWJfbM*ZzxzmCPY`b~RobNrrj=rd`=)8-j`iSW64@0_b6?;GYk zNB+-fzOxlqZ?`y{OA$WigtZXa8)#p#=DPYxH=VeC_Q5q9Cv`mvW6*zU&Gnp1;oPM6 zaK_B3j(l^FyJgYeE9RrmDyhE7W2}}nW%ic#0v@i1E!yTey$W)U>fyd+!@2hWQ!Wa==NAtKoj`f3tp4y$Al`e;?)76?AjdaRR>|?&r)~3Git> zb1)a?uiv|R0_{m#A9c;7)eZ1y6l@yQ#oE*>(Z2fG-&&smPa2QTW>m*^K65^~`coP$ z8y5Y?iS<4Gz{Zg##$1mk)u-0;X|!xu^FCr;ce~X<&UWE&pBgqfYmEJTzpK9I%vr%b z3Ksd6qlPJLI%HFfeXK_^|BXiKZC>Ocu(Kk6hD3G-8usLzVG^q00Qh gz)s7ge@$ApxGu7=(6IGIk+uG&HTev01^#CH3$(Wk5&!@I literal 0 HcmV?d00001 diff --git a/examples/sitemap/basic/sandbox.config.json b/examples/sitemap/basic/sandbox.config.json new file mode 100644 index 000000000000..9178af77d7de --- /dev/null +++ b/examples/sitemap/basic/sandbox.config.json @@ -0,0 +1,11 @@ +{ + "infiniteLoopProtection": true, + "hardReloadOnChange": false, + "view": "browser", + "template": "node", + "container": { + "port": 3000, + "startScript": "start", + "node": "14" + } +} diff --git a/examples/sitemap/basic/src/pages/index.astro b/examples/sitemap/basic/src/pages/index.astro new file mode 100644 index 000000000000..5e6ba1a2b01f --- /dev/null +++ b/examples/sitemap/basic/src/pages/index.astro @@ -0,0 +1,12 @@ +--- +--- + + + + + Astro + + +

Astro

+ + diff --git a/examples/sitemap/basic/src/pages/second-page.astro b/examples/sitemap/basic/src/pages/second-page.astro new file mode 100644 index 000000000000..77cfad9f8550 --- /dev/null +++ b/examples/sitemap/basic/src/pages/second-page.astro @@ -0,0 +1,13 @@ +--- +--- + + + + + Second page + + +

Second page

+ Back to Home + + diff --git a/examples/sitemap/basic/tsconfig.json b/examples/sitemap/basic/tsconfig.json new file mode 100644 index 000000000000..7ac81809afda --- /dev/null +++ b/examples/sitemap/basic/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + // Enable top-level await, and other modern ESM features. + "target": "ESNext", + "module": "ESNext", + // Enable node-style module resolution, for things like npm package imports. + "moduleResolution": "node", + // Enable JSON imports. + "resolveJsonModule": true, + // Enable stricter transpilation for better output. + "isolatedModules": true, + // Add type definitions for our Vite runtime. + "types": ["vite/client"] + } +} diff --git a/examples/sitemap/i18n/.gitignore b/examples/sitemap/i18n/.gitignore new file mode 100644 index 000000000000..6e9005893238 --- /dev/null +++ b/examples/sitemap/i18n/.gitignore @@ -0,0 +1,18 @@ +# build output +dist/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/examples/sitemap/i18n/.npmrc b/examples/sitemap/i18n/.npmrc new file mode 100644 index 000000000000..ef83021af3ec --- /dev/null +++ b/examples/sitemap/i18n/.npmrc @@ -0,0 +1,2 @@ +# Expose Astro dependencies for `pnpm` users +shamefully-hoist=true diff --git a/examples/sitemap/i18n/.stackblitzrc b/examples/sitemap/i18n/.stackblitzrc new file mode 100644 index 000000000000..0dfa8f1e0565 --- /dev/null +++ b/examples/sitemap/i18n/.stackblitzrc @@ -0,0 +1,6 @@ +{ + "startCommand": "npm start", + "env": { + "ENABLE_CJS_IMPORTS": true + } +} diff --git a/examples/sitemap/i18n/README.md b/examples/sitemap/i18n/README.md new file mode 100644 index 000000000000..e053a3191062 --- /dev/null +++ b/examples/sitemap/i18n/README.md @@ -0,0 +1,9 @@ +# Demo for @astrojs/sitemap integration + +This sample demonstrates the localization capabilities of `@astrojs/sitemap` integration. + +The `i18n.mjs` file contains the locales basic info. + +Its data is used for dynamic page generation, for language switch and as a source for the `@astrojs/sitemap` integration config. + +Play this demo [online](https://stackblitz.com/fork/github/withastro/astro/tree/main/examples/sitemap/i18n). diff --git a/examples/sitemap/i18n/astro.config.ts b/examples/sitemap/i18n/astro.config.ts new file mode 100644 index 000000000000..6c2f39556f9b --- /dev/null +++ b/examples/sitemap/i18n/astro.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'astro/config'; +import sitemap from '@astrojs/sitemap'; + +import sitemapConfig from './sitemap.config'; + +// https://astro.build/config +export default defineConfig({ + site: 'https://another.com', + integrations: [sitemap(sitemapConfig)], +}); diff --git a/examples/sitemap/i18n/package.json b/examples/sitemap/i18n/package.json new file mode 100644 index 000000000000..1eba1ccb5a8b --- /dev/null +++ b/examples/sitemap/i18n/package.json @@ -0,0 +1,16 @@ +{ + "name": "@example/sitemap-i18n", + "version": "0.0.1", + "private": true, + "license": "MIT", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview" + }, + "devDependencies": { + "astro": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/examples/sitemap/i18n/sandbox.config.json b/examples/sitemap/i18n/sandbox.config.json new file mode 100644 index 000000000000..9178af77d7de --- /dev/null +++ b/examples/sitemap/i18n/sandbox.config.json @@ -0,0 +1,11 @@ +{ + "infiniteLoopProtection": true, + "hardReloadOnChange": false, + "view": "browser", + "template": "node", + "container": { + "port": 3000, + "startScript": "start", + "node": "14" + } +} diff --git a/examples/sitemap/i18n/sitemap.config.ts b/examples/sitemap/i18n/sitemap.config.ts new file mode 100644 index 000000000000..044c630df53e --- /dev/null +++ b/examples/sitemap/i18n/sitemap.config.ts @@ -0,0 +1,15 @@ +import i18n from './src/i18n.js'; + +/** @type {import('astro-sitemap').SitemapOptions} */ +const sitemapConfig = { + // added + i18n: { + defaultLocale: i18n.defaultLocale, + locales: Object.entries(i18n.locales).reduce((prev, [locale, { lang }]) => { + prev[locale] = lang; + return prev; + }, {}), + }, +}; + +export default sitemapConfig; diff --git a/examples/sitemap/i18n/src/components/LanguageSwitch.astro b/examples/sitemap/i18n/src/components/LanguageSwitch.astro new file mode 100644 index 000000000000..9d25716241e3 --- /dev/null +++ b/examples/sitemap/i18n/src/components/LanguageSwitch.astro @@ -0,0 +1,45 @@ +--- +import i18n from '../i18n'; + +export interface Props { + currentLocale: string; +} + +const { currentLocale } = Astro.props as Props; +const pathname = new URL(Astro.request.url).pathname; + +const getLink = (locale: string) => { + let path: string; + if (pathname === '/') { + path = '/'; + } else { + const a = pathname.split('/'); + if (i18n.locales[a[1]]) { + path = a.slice(2).join('/'); + } else { + path = pathname; + } + } + if (!path.startsWith('/')) { + path = '/' + path; + } + return locale === i18n.defaultLocale ? path : `/${locale}${path}`; +}; +--- +
    +{ + Object.keys(i18n.locales).map((locale) => ( +
  • + {locale === currentLocale ? ( + + {locale} + + ) : ( + + {locale} + + )} +
  • + )) +} +
diff --git a/examples/sitemap/i18n/src/i18n.ts b/examples/sitemap/i18n/src/i18n.ts new file mode 100644 index 000000000000..25015676a31b --- /dev/null +++ b/examples/sitemap/i18n/src/i18n.ts @@ -0,0 +1,25 @@ +const i18n = { + defaultLocale: 'en', + locales: { + en: { + name: 'i18n test', + short_name: 'Test', + description: 'This is the application description', + lang: 'en-US', + }, + es: { + name: 'Prueba i18n', + short_name: 'Prueba', + description: 'Esta es la descripciĆ³n de la aplicaciĆ³n.', + lang: 'es-ES', + }, + fr: { + name: 'Test i18n', + short_name: 'Test', + description: "Ceci est la description de l'application", + lang: 'fr-CA', + }, + }, +}; + +export default i18n; diff --git a/examples/sitemap/i18n/src/images/logomark-light.png b/examples/sitemap/i18n/src/images/logomark-light.png new file mode 100644 index 0000000000000000000000000000000000000000..b77f87fc58e37bf7adf47edf300b603309bedfef GIT binary patch literal 94580 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 + + + + + + + + + + + + + + diff --git a/examples/sitemap/i18n/src/pages/404.astro b/examples/sitemap/i18n/src/pages/404.astro new file mode 100644 index 000000000000..95ef4a175609 --- /dev/null +++ b/examples/sitemap/i18n/src/pages/404.astro @@ -0,0 +1,17 @@ +--- +import i18n from '../i18n'; + +const locale = i18n.defaultLocale; +const { lang } = i18n.locales[locale]; +--- + + + + + 404 + + +

404

+
+ + diff --git a/examples/sitemap/i18n/src/pages/[locale]/404.astro b/examples/sitemap/i18n/src/pages/[locale]/404.astro new file mode 100644 index 000000000000..270790f673b5 --- /dev/null +++ b/examples/sitemap/i18n/src/pages/[locale]/404.astro @@ -0,0 +1,32 @@ +--- +import i18n from '../../i18n'; + +export async function getStaticPaths() { + const items = Object.entries(i18n.locales).filter(([locale]) => locale !== i18n.defaultLocale); + + const paths = items.map(([locale, { lang }]) => ({ + params: { locale }, + props: { lang }, + })); + + return paths; +} + +export interface Props { + lang: string; +} + +const { locale } = Astro.params; +const { lang } = Astro.props as Props; +--- + + + + + 404 + + +

404

+ + + diff --git a/examples/sitemap/i18n/src/pages/[locale]/index.astro b/examples/sitemap/i18n/src/pages/[locale]/index.astro new file mode 100644 index 000000000000..d28571f09723 --- /dev/null +++ b/examples/sitemap/i18n/src/pages/[locale]/index.astro @@ -0,0 +1,38 @@ +--- +import i18n from '../../i18n'; +import LanguageSwitch from '../../components/LanguageSwitch.astro'; + +export async function getStaticPaths() { + const items = Object.entries(i18n.locales).filter(([locale]) => locale !== i18n.defaultLocale); + + const paths = items.map(([locale, { name, lang }]) => ({ + params: { locale }, + props: { name, lang }, + })); + + return paths; +} + +export interface Props { + name: string; + description: string; + lang: string; +} + +const { locale } = Astro.params; +const { name, description, lang } = Astro.props as Props; +--- + + + + + Astro {locale} + + +

Astro {locale}

+

{name}

+

{description}

+ #2 + + + diff --git a/examples/sitemap/i18n/src/pages/[locale]/second-page.astro b/examples/sitemap/i18n/src/pages/[locale]/second-page.astro new file mode 100644 index 000000000000..97f04f58d893 --- /dev/null +++ b/examples/sitemap/i18n/src/pages/[locale]/second-page.astro @@ -0,0 +1,36 @@ +--- +import i18n from '../../i18n'; +import LanguageSwitch from '../../components/LanguageSwitch.astro'; + +export async function getStaticPaths() { + const items = Object.entries(i18n.locales).filter(([locale]) => locale !== i18n.defaultLocale); + + const paths = items.map(([locale, { name, lang }]) => ({ + params: { locale }, + props: { name, lang }, + })); + + return paths; +} + +export interface Props { + name: string; + description: string; + lang: string; +} + +const { locale } = Astro.params; +const { lang } = Astro.props as Props; +--- + + + + + #2 {locale} + + +

#2 {locale}

+ + + + diff --git a/examples/sitemap/i18n/src/pages/index.astro b/examples/sitemap/i18n/src/pages/index.astro new file mode 100644 index 000000000000..71c0e1734255 --- /dev/null +++ b/examples/sitemap/i18n/src/pages/index.astro @@ -0,0 +1,21 @@ +--- +import i18n from '../i18n'; +import LanguageSwitch from '../components/LanguageSwitch.astro'; + +const locale = i18n.defaultLocale; +const { lang, name, description } = i18n.locales[locale]; +--- + + + + + Astro {locale} + + +

Astro {locale}

+

{name}

+

{description}

+ #2 + + + diff --git a/examples/sitemap/i18n/src/pages/second-page.astro b/examples/sitemap/i18n/src/pages/second-page.astro new file mode 100644 index 000000000000..10dc0cac4fdd --- /dev/null +++ b/examples/sitemap/i18n/src/pages/second-page.astro @@ -0,0 +1,19 @@ +--- +import i18n from '../i18n'; +import LanguageSwitch from '../components/LanguageSwitch.astro'; + +const locale = i18n.defaultLocale; +const { lang } = i18n.locales[locale]; +--- + + + + + #2 {locale} + + +

#2 {locale}

+ + + + diff --git a/examples/sitemap/i18n/tsconfig.json b/examples/sitemap/i18n/tsconfig.json new file mode 100644 index 000000000000..7ac81809afda --- /dev/null +++ b/examples/sitemap/i18n/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + // Enable top-level await, and other modern ESM features. + "target": "ESNext", + "module": "ESNext", + // Enable node-style module resolution, for things like npm package imports. + "moduleResolution": "node", + // Enable JSON imports. + "resolveJsonModule": true, + // Enable stricter transpilation for better output. + "isolatedModules": true, + // Add type definitions for our Vite runtime. + "types": ["vite/client"] + } +} diff --git a/package.json b/package.json index 3be9d8e87c05..76339cd09113 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,12 @@ "build": "turbo run build --no-deps --scope=astro --scope=create-astro --scope=\"@astrojs/*\"", "build:ci": "turbo run build:ci --no-deps --scope=astro --scope=create-astro --scope=\"@astrojs/*\"", "build:examples": "turbo run build --scope=\"@example/*\"", + "build:0": "turbo run build --no-deps --scope=@astrojs/sitemap", + "build:ex-a": "turbo run build --no-deps --scope=\"@example/sitemap-*\"", + "build:s": "turbo run build --scope=@example/starter", + "build:a": "turbo run build --scope=@example/sitemap-advanced", + "build:b": "turbo run build --scope=@example/sitemap-basic", + "build:i": "turbo run build --scope=@example/sitemap-i18n", "dev": "turbo run dev --no-deps --no-cache --parallel --scope=astro --scope=create-astro --scope=\"@astrojs/*\"", "format": "pnpm run format:code", "format:ci": "pnpm run format:imports && pnpm run format:code", diff --git a/packages/integrations/sitemap/README.md b/packages/integrations/sitemap/README.md index 9d84cae195d2..1c6cb9fbc90d 100644 --- a/packages/integrations/sitemap/README.md +++ b/packages/integrations/sitemap/README.md @@ -64,7 +64,41 @@ export default { } ``` -Now, [build your site for production](https://docs.astro.build/en/reference/cli-reference/#astro-build) via the `astro build` command. You should find your sitemap under `dist/sitemap.xml`! +Now, [build your site for production](https://docs.astro.build/en/reference/cli-reference/#astro-build) via the `astro build` command. You should find your _sitemap_ under `dist/sitemap-index.xml` and `dist/sitemap-0.xml`! + +Generated sitemap content for two pages website: + +**sitemap-index.xml** + +```xml + + + + https://stargazers.club/sitemap-0.xml + + +``` + +**sitemap-0.xml** + + +```xml + + + + https://stargazers.club/ + + + https://stargazers.club/second-page/ + + +``` + +All pages generated during build will contain in `` section a link to sitemap: + +```html + +``` You can also check our [Astro Integration Documentation][astro-integration] for more on integrations. @@ -111,5 +145,168 @@ 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). + +__astro.config.mjs__ + +```js +import sitemap from '@astrojs/sitemap'; + +export default { + site: 'https://stargazers.club', + integrations: [ + sitemap({ + entryLimit: 10000, + }), + ], +} +``` + +### createLinkInHead + +`Boolean`, default is `true`, create a link on sitemap in `` section of generated pages. + +__astro.config.mjs__ + +```js +import sitemap from '@astrojs/sitemap'; + +export default { + site: 'https://stargazers.club', + integrations: [ + sitemap({ + // disable create links to sitemap in + createLinkInHead: false, + }), + ], +} +``` + +### changefreq, lastmod, priority + +`changefreq` - How frequently the page is likely to change. Available values: `always` \| `hourly` \| `daily` \| `weekly` \| `monthly` \| `yearly` \| `never`. + +`priority` - The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0. + +`lastmod` - The date of page last modification. + +`changefreq` and `priority` are ignored by Google. + +See detailed explanation of sitemap specific options on [sitemap.org](https://www.sitemaps.org/protocol.html). + + +:exclamation: This integration uses 'astro:build:done' hook. The hook exposes only generated page paths. So with present version of Astro the integration has no abilities to analyze a page source, frontmatter etc. The integration can add `changefreq`, `lastmod` and `priority` attributes only in a batch or nothing. + +__astro.config.mjs__ + +```js +import sitemap from '@astrojs/sitemap'; + +export default { + site: 'https://stargazers.club', + integrations: [ + sitemap({ + changefreq: 'weekly', + priority: 0.7, + lastmod: new Date('2022-05-28'), + }), + ], +} +``` + +### serialize + +Async or sync function called for each SiteMap item just before writing to disk. + +__astro.config.mjs__ + +```js +import sitemap from '@astrojs/sitemap'; + +export default { + site: 'https://stargazers.club', + integrations: [ + sitemap({ + serialize(item) { + if (/special-page/.test(item.url)) { + item.changefreq = 'daily'; + item.lastmod = new Date(); + item.priority = 0.9; + } + return item; + }, + }), + ], +} +``` + +### i18n + +To localize sitemap, please, supply the integration config with the `i18n` options. The integration will check generated page paths on presence of locale keys in paths. + +`i18n` oject should have two required properties: + +- `defaultLocale`: `String`. Its value must exist as one of `locales` keys. +- `locales`: `Record`, key/value - pairs. The key is used to look for a locale part in a page path. The value is a language attribute, only English alphabet and hyphen allowed. See more on [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang). + +Read more about localization on Google in [Advanced SEO](https://developers.google.com/search/docs/advanced/crawling/localized-versions#all-method-guidelines). + +__astro.config.mjs__ + +```js +import sitemap from '@astrojs/sitemap'; + +export default { + site: 'https://stargazers.club', + integrations: [ + sitemap({ + i18n: { + defaultLocale: 'en', // All urls that don't contain `es` or `fr` after `https://stargazers.club/` will be treated as default locale, i.e. `en` + locales: { + en: 'en-US', // The `defaultLocale` value must present in `locales` keys + es: 'es-ES', + fr: 'fr-CA', + }, + }, + }), + ], +}; +... + +``` + +The sitemap content will be: + +```xml +... + + https://stargazers.club/ + + + + + + https://stargazers.club/es/ + + + + + + https://stargazers.club/fr/ + + + + + + https://stargazers.club/es/second-page/ + + + + +... +``` + [astro-integration]: https://docs.astro.build/en/guides/integrations-guide/ [astro-ui-frameworks]: https://docs.astro.build/en/core-concepts/framework-components/#using-framework-components diff --git a/packages/integrations/sitemap/package.json b/packages/integrations/sitemap/package.json index 3fbfc2b94b5e..12b49ec4bad2 100644 --- a/packages/integrations/sitemap/package.json +++ b/packages/integrations/sitemap/package.json @@ -13,7 +13,8 @@ }, "keywords": [ "astro-component", - "seo" + "seo", + "sitemap" ], "bugs": "https://github.com/withastro/astro/issues", "homepage": "https://astro.build", @@ -21,12 +22,19 @@ ".": "./dist/index.js", "./package.json": "./package.json" }, + "files": [ + "dist" + ], "scripts": { "build": "astro-scripts build \"src/**/*.ts\" && tsc", "build:ci": "astro-scripts build \"src/**/*.ts\"", "dev": "astro-scripts dev \"src/**/*.ts\"" }, - "dependencies": {}, + "dependencies": { + "node-html-parser": "^5.3.3", + "sitemap": "^7.1.1", + "zod": "^3.17.3" + }, "devDependencies": { "astro": "workspace:*", "astro-scripts": "workspace:*" diff --git a/packages/integrations/sitemap/src/constants.ts b/packages/integrations/sitemap/src/constants.ts new file mode 100644 index 000000000000..c983e1b1c427 --- /dev/null +++ b/packages/integrations/sitemap/src/constants.ts @@ -0,0 +1 @@ +export const changefreqValues = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'] as const; diff --git a/packages/integrations/sitemap/src/generate-sitemap.ts b/packages/integrations/sitemap/src/generate-sitemap.ts new file mode 100644 index 000000000000..f2c2ea7ce7e1 --- /dev/null +++ b/packages/integrations/sitemap/src/generate-sitemap.ts @@ -0,0 +1,55 @@ +import { SitemapItemLoose } from 'sitemap'; + +import type { SitemapOptions } 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 || {}; + // TODO: find way to respect 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 || {}); + + const getPath = (url: string) => { + const result = parseUrl(url, i18n?.defaultLocale || '', localeCodes, finalSiteUrl); + return result?.path; + }; + const getLocale = (url: string) => { + const result = parseUrl(url, i18n?.defaultLocale || '', localeCodes, finalSiteUrl); + return result?.locale; + }; + + const urlData = urls.map((url) => { + let links; + if (defaultLocale && locales) { + const currentPath = getPath(url); + if (currentPath) { + const filtered = urls.filter((subUrl) => getPath(subUrl) === currentPath); + if (filtered.length > 1) { + links = filtered.map((subUrl) => ({ + url: subUrl, + lang: locales[getLocale(subUrl)!], + })); + } + } + } + + return { + url, + links, + lastmod, + priority, + changefreq, // : changefreq as EnumChangefreq, + } as SitemapItemLoose; + }); + + return urlData; +} diff --git a/packages/integrations/sitemap/src/index.ts b/packages/integrations/sitemap/src/index.ts index 169eeb788701..d0004ae91613 100644 --- a/packages/integrations/sitemap/src/index.ts +++ b/packages/integrations/sitemap/src/index.ts @@ -1,91 +1,148 @@ +import path from 'node:path'; +import { fileURLToPath } from 'url'; import type { AstroConfig, AstroIntegration } from 'astro'; -import fs from 'node:fs'; -const STATUS_CODE_PAGE_REGEXP = /\/[0-9]{3}\/?$/; - -type SitemapOptions = - | { - /** - * All pages are included in your sitemap by default. - * With this config option, you can filter included pages by URL. - * - * The `page` function parameter is the full URL of your rendered page, including your `site` domain. - * Return `true` to include a page in your sitemap, and `false` to remove it. - * - * ```js - * filter: (page) => page !== 'http://example.com/secret-page' - * ``` - */ - filter?(page: string): boolean; - - /** - * If you have any URL, not rendered by Astro, that you want to include in your sitemap, - * this config option will help you to include your array of custom pages in your sitemap. - * - * ```js - * customPages: ['http://example.com/custom-page', 'http://example.com/custom-page2'] - * ``` - */ - customPages?: Array; - - /** - * If present, we use the `site` config option as the base for all sitemap URLs - * Use `canonicalURL` to override this - */ - canonicalURL?: string; - } - | undefined; - -/** Construct sitemap.xml given a set of URLs */ -function generateSitemap(pages: string[]) { - // TODO: find way to respect 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 - let sitemap = ``; - for (const url of urls) { - sitemap += `${url}`; - } - sitemap += `\n`; - return sitemap; -} +import { ZodError } from 'zod'; +import { LinkItem as LinkItemBase, SitemapItemLoose, simpleSitemapAndIndex } from 'sitemap'; + +import { Logger } from './utils/logger'; +import { withOptions } from './with-options'; +import { validateOpts } from './validate-opts'; +import { generateSitemap } from './generate-sitemap'; +import { changefreqValues } from './constants'; +import { processPages } from './process-pages'; + +export type ChangeFreq = typeof changefreqValues[number]; +export type SitemapItem = Pick; +export type LinkItem = LinkItemBase; -export default function createPlugin({ - filter, - customPages, - canonicalURL, -}: SitemapOptions = {}): AstroIntegration { - let config: AstroConfig; - return { - name: '@astrojs/sitemap', - hooks: { - 'astro:config:done': async ({ config: _config }) => { - config = _config; - }, - 'astro:build:done': async ({ pages, dir }) => { - let finalSiteUrl: URL; - if (canonicalURL) { - finalSiteUrl = new URL(canonicalURL); - finalSiteUrl.pathname += finalSiteUrl.pathname.endsWith('/') ? '' : '/'; // normalizes the final url since it's provided by user - } else if (config.site) { - finalSiteUrl = new URL(config.base, config.site); - } else { - console.warn( - 'The Sitemap integration requires either the `site` astro.config option or `canonicalURL` integration option. Skipping.' - ); - return; - } - let pageUrls = pages.map((p) => { - const path = finalSiteUrl.pathname + p.pathname; - return new URL(path, finalSiteUrl).href; - }); - if (filter) { - pageUrls = pageUrls.filter((page: string) => filter(page)); - } - if (customPages) { - pageUrls = [...pageUrls, ...customPages]; - } - const sitemapContent = generateSitemap(pageUrls); - fs.writeFileSync(new URL('sitemap.xml', dir), sitemapContent); - }, - }, - }; +export type SitemapOptions = + | { + // the same with official + filter?(page: string): boolean; + customPages?: string[]; + canonicalURL?: string; + // added + i18n?: { + defaultLocale: string; + locales: Record; + }; + entryLimit?: number; + + createLinkInHead?: boolean; + serialize?(item: SitemapItemLoose): SitemapItemLoose; + // sitemap specific + changefreq?: ChangeFreq; + lastmod?: Date; + priority?: number; + } + | undefined; + +function formatConfigErrorMessage(err: ZodError) { + const errorList = err.issues.map((issue) => ` ${issue.path.join('.')} ${issue.message + '.'}`); + return errorList.join('\n'); } + +const PKG_NAME = '@astrojs/sitemap'; +const OUTFILE = 'sitemap-index.xml'; + +const createPlugin = (options?: SitemapOptions): AstroIntegration => { + let config: AstroConfig; + return { + name: PKG_NAME, + + hooks: { + 'astro:config:done': async ({ config: cfg }) => { + config = cfg; + }, + + 'astro:build:done': async ({ dir, pages }) => { + const logger = new Logger(PKG_NAME); + + const opts = withOptions(options || {}); + + try { + validateOpts(config.site, opts); + + const { filter, customPages, canonicalURL, serialize, createLinkInHead, entryLimit } = opts; + + let finalSiteUrl: URL; + if (canonicalURL) { + finalSiteUrl = new URL(canonicalURL); + if (!finalSiteUrl.pathname.endsWith('/')) { + finalSiteUrl.pathname += '/'; // normalizes the final url since it's provided by user + } + } else { + // `validateOpts` forces to provide `canonicalURL` or `config.site` at least. + // So step to check on empty values of `canonicalURL` and `config.site` is dropped. + finalSiteUrl = new URL(config.base, config.site); + } + + let pageUrls = pages.map((p) => { + const path = finalSiteUrl.pathname + p.pathname; + return new URL(path, finalSiteUrl).href; + }); + + try { + if (filter) { + pageUrls = pageUrls.filter((url) => filter(url)); + } + } catch (err) { + logger.error(`Error filtering pages\n${(err as any).toString()}`); + return; + } + + if (customPages) { + pageUrls = [...pageUrls, ...customPages]; + } + + if (pageUrls.length === 0) { + logger.warn(`No data for sitemap.\n\`${OUTFILE}\` is not created.`); + return; + } + + let urlData = generateSitemap(pageUrls, finalSiteUrl.href, opts); + + let serializedUrls: SitemapItemLoose[]; + + if (serialize) { + serializedUrls = []; + try { + for (const item of urlData) { + const serialized = await Promise.resolve(serialize(item)); + serializedUrls.push(serialized); + } + urlData = serializedUrls; + } catch (err) { + logger.error(`Error serializing pages\n${(err as any).toString()}`); + return; + } + } + + await simpleSitemapAndIndex({ + hostname: finalSiteUrl.href, + destinationDir: fileURLToPath(dir), + sourceData: urlData, + limit: entryLimit, + gzip: false, + }); + logger.success(`\`${OUTFILE}\` is created.`); + + if (createLinkInHead) { + const sitemapHref = path.posix.join(config.base, OUTFILE); + const headHTML = ``; + await processPages(pages, dir, headHTML, config.build.format); + logger.success('Sitemap links are created in section of generated pages.'); + } + } catch (err) { + if (err instanceof ZodError) { + logger.warn(formatConfigErrorMessage(err)); + } else { + throw err; + } + } + }, + }, + }; +}; + +export default createPlugin; diff --git a/packages/integrations/sitemap/src/process-pages.ts b/packages/integrations/sitemap/src/process-pages.ts new file mode 100644 index 000000000000..c6a46218c889 --- /dev/null +++ b/packages/integrations/sitemap/src/process-pages.ts @@ -0,0 +1,39 @@ +import { promises as fs } from 'node:fs'; +import { parse, HTMLElement } from 'node-html-parser'; + +const addTailSlash = (s: string) => (s.endsWith('/') ? s : s + '/'); +const removeHeadingSlash = (s: string) => s.replace(/^\/+/, ''); +const removeTrailingSlash = (s: string) => s.replace(/\/+$/, ''); + +const getFileDir = (pathname: string) => { + const name = addTailSlash(pathname); + const file = name === '404/' ? '404.html' : `${name}index.html`; + return removeHeadingSlash(file); +}; + +const getFileFile = (pathname: string) => (pathname ? `${removeTrailingSlash(pathname)}.html` : 'index.html'); + +export async function processPages(pages: { pathname: string }[], dir: URL, headHTML: string, buildFormat: string) { + if (pages.length === 0) { + return; + } + if (buildFormat !== 'directory' && buildFormat !== 'file') { + throw new Error(`Unsupported build.format: '${buildFormat}' in your astro.config`); + } + + for (const page of pages) { + const fileUrl = new URL(buildFormat === 'directory' ? getFileDir(page.pathname) : getFileFile(page.pathname), dir); + + const html = await fs.readFile(fileUrl, 'utf-8'); + const root = parse(html); + let head = root.querySelector('head'); + if (!head) { + head = new HTMLElement('head', {}, '', root); + root.appendChild(head); + console.warn(`No found in \`${fileUrl.pathname}\`. will be created.`); + } + head.innerHTML = head.innerHTML + headHTML; + const inlined = root.toString(); + await fs.writeFile(fileUrl, inlined, 'utf-8'); + } +} diff --git a/packages/integrations/sitemap/src/schema.ts b/packages/integrations/sitemap/src/schema.ts new file mode 100644 index 000000000000..6e58218c751e --- /dev/null +++ b/packages/integrations/sitemap/src/schema.ts @@ -0,0 +1,52 @@ +import { z } from 'zod'; +import { isValidUrl } from './utils/is-valid-url'; +import { changefreqValues } from './constants'; + +const urlSchema = () => + z + .string() + .min(1) + .refine((val) => !val || isValidUrl(val), 'Not valid url'); + +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(); + +export const SitemapOptionsSchema = z.object({ + filter: fnSchema(), + + customPages: urlSchema().array().optional(), + + canonicalURL: urlSchema().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(({ locales, defaultLocale }) => locales[defaultLocale], { + message: '`defaultLocale` must exists in `locales` keys', + }) + .optional(), + + createLinkInHead: z.boolean().optional(), + + entryLimit: z.number().nonnegative().optional(), + + serialize: fnSchema(), + + changefreq: z.enum(changefreqValues).optional(), + lastmod: z.date().optional(), + priority: z.number().min(0).max(1).optional(), +}); diff --git a/packages/integrations/sitemap/src/utils/is-object-empty.ts b/packages/integrations/sitemap/src/utils/is-object-empty.ts new file mode 100644 index 000000000000..2dbc0cfe9378 --- /dev/null +++ b/packages/integrations/sitemap/src/utils/is-object-empty.ts @@ -0,0 +1,10 @@ +// @internal +export const isObjectEmpty = (o: any) => { + if (!o) { + return true; + } + if (Array.isArray(o)) { + return o.length === 0; + } + return Object.keys(o).length === 0 && Object.getPrototypeOf(o) === Object.prototype; +}; diff --git a/packages/integrations/sitemap/src/utils/is-valid-url.ts b/packages/integrations/sitemap/src/utils/is-valid-url.ts new file mode 100644 index 000000000000..4bead70fdf92 --- /dev/null +++ b/packages/integrations/sitemap/src/utils/is-valid-url.ts @@ -0,0 +1,13 @@ +// @internal +export const isValidUrl = (s: any) => { + if (typeof s !== 'string' || !s) { + return false; + } + try { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const dummy = new URL(s); + return true; + } catch { + return false; + } +}; diff --git a/packages/integrations/sitemap/src/utils/logger.ts b/packages/integrations/sitemap/src/utils/logger.ts new file mode 100644 index 000000000000..ff6276a2ed91 --- /dev/null +++ b/packages/integrations/sitemap/src/utils/logger.ts @@ -0,0 +1,46 @@ +// @internal +export interface ILogger { + info(msg: string): void; + success(msg: string): void; + warn(msg: string): void; + error(msg: string): void; +} + +// @internal +export class Logger implements ILogger { + private colors = { + reset: '\x1b[0m', + fg: { + red: '\x1b[31m', + green: '\x1b[32m', + yellow: '\x1b[33m', + }, + } as const; + + private packageName: string; + + constructor(packageName: string) { + this.packageName = packageName; + } + + private log(msg: string, prefix: string = '') { + // eslint-disable-next-line no-console + console.log(`%s${this.packageName}:%s ${msg}\n`, prefix, prefix ? this.colors.reset : ''); + } + + info(msg: string) { + this.log(msg); + } + + success(msg: string) { + this.log(msg, this.colors.fg.green); + } + + warn(msg: string) { + this.log(`Skipped!\n${msg}`, this.colors.fg.yellow); + } + + error(msg: string) { + this.log(`Failed!\n${msg}`, this.colors.fg.red); + } +} diff --git a/packages/integrations/sitemap/src/utils/parse-url.ts b/packages/integrations/sitemap/src/utils/parse-url.ts new file mode 100644 index 000000000000..7d948923a1fb --- /dev/null +++ b/packages/integrations/sitemap/src/utils/parse-url.ts @@ -0,0 +1,28 @@ +export const parseUrl = (url: string, defaultLocale: string, localeCodes: string[], base: string) => { + if (!url || !defaultLocale || localeCodes.length === 0 || localeCodes.some((key) => !key) || !base) { + throw new Error('parseUrl: some parameters are empty'); + } + if (url.indexOf(base) !== 0) { + return undefined; + } + let s = url.replace(base, ''); + if (!s || s === '/') { + return { locale: defaultLocale, path: '/' }; + } + if (!s.startsWith('/')) { + s = '/' + s; + } + const a = s.split('/'); + const locale = a[1]; + if (localeCodes.some((key) => key === locale)) { + let path = a.slice(2).join('/'); + if (path === '//') { + path = '/'; + } + if (path !== '/' && !path.startsWith('/')) { + path = '/' + path; + } + return { locale, path }; + } + return { locale: defaultLocale, path: s }; +}; diff --git a/packages/integrations/sitemap/src/validate-opts.ts b/packages/integrations/sitemap/src/validate-opts.ts new file mode 100644 index 000000000000..2a9bfe66770c --- /dev/null +++ b/packages/integrations/sitemap/src/validate-opts.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; +import type { SitemapOptions } from './index'; +import { SitemapOptionsSchema } from './schema'; + +// @internal +export const validateOpts = (site: string | undefined, opts: SitemapOptions) => { + const schema = SitemapOptionsSchema.extend({ + site: z.string().optional(), + }) + .strict() + .refine(({ site, canonicalURL }) => site || canonicalURL, { + message: 'Required `site` astro.config option or `canonicalURL` integration option', + }); + + schema.parse({ site: site || '', ...(opts || {}) }); +}; diff --git a/packages/integrations/sitemap/src/with-options.ts b/packages/integrations/sitemap/src/with-options.ts new file mode 100644 index 000000000000..6e0982b7b1e4 --- /dev/null +++ b/packages/integrations/sitemap/src/with-options.ts @@ -0,0 +1,20 @@ +import { isObjectEmpty } from './utils/is-object-empty'; +import type { SitemapOptions } from './index'; + +const defaultOptions: Readonly = { + createLinkInHead: true, + entryLimit: 45000, +}; + +// @internal +export const withOptions = (pluginOptions: SitemapOptions) => { + if (isObjectEmpty(pluginOptions)) { + return defaultOptions; + } + const options: SitemapOptions = { + ...pluginOptions, + createLinkInHead: pluginOptions?.createLinkInHead ?? defaultOptions.createLinkInHead, + entryLimit: pluginOptions?.entryLimit || defaultOptions.entryLimit, + }; + return options; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b65f9394b4f2..998afaa6e234 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -246,7 +246,7 @@ importers: '@astrojs/lit': ^0.1.5 '@astrojs/partytown': ^0.1.4 '@astrojs/react': ^0.1.3 - '@astrojs/sitemap': ^0.1.2 + '@astrojs/sitemap': workspace:* '@astrojs/solid-js': 0.1.4 '@astrojs/tailwind': ^0.2.1 '@astrojs/turbolinks': ^0.1.3 @@ -303,6 +303,30 @@ importers: astro: link:../../packages/astro sass: 1.52.2 + examples/sitemap/advanced: + specifiers: + '@astrojs/sitemap': workspace:* + astro: workspace:* + devDependencies: + '@astrojs/sitemap': link:../../../packages/integrations/sitemap + astro: link:../../../packages/astro + + examples/sitemap/basic: + specifiers: + '@astrojs/sitemap': workspace:* + astro: workspace:* + devDependencies: + '@astrojs/sitemap': link:../../../packages/integrations/sitemap + astro: link:../../../packages/astro + + examples/sitemap/i18n: + specifiers: + '@astrojs/sitemap': workspace:* + astro: workspace:* + devDependencies: + '@astrojs/sitemap': link:../../../packages/integrations/sitemap + astro: link:../../../packages/astro + examples/ssr: specifiers: '@astrojs/node': ^0.1.2 @@ -326,8 +350,10 @@ importers: examples/starter: specifiers: + '@astrojs/markdown-remark': ^0.11.2 astro: ^1.0.0-beta.44 devDependencies: + '@astrojs/markdown-remark': link:../../packages/markdown/remark astro: link:../../packages/astro examples/subpath: @@ -1800,6 +1826,13 @@ importers: specifiers: astro: workspace:* astro-scripts: workspace:* + node-html-parser: ^5.3.3 + sitemap: ^7.1.1 + zod: ^3.17.3 + dependencies: + node-html-parser: 5.3.3 + sitemap: 7.1.1 + zod: 3.17.3 devDependencies: astro: link:../../astro astro-scripts: link:../../../scripts @@ -6822,6 +6855,12 @@ packages: '@types/node': 17.0.41 dev: false + /@types/sax/1.2.4: + resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==} + dependencies: + '@types/node': 17.0.41 + dev: false + /@types/scheduler/0.16.2: resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} @@ -8062,6 +8101,16 @@ packages: engines: {node: '>=8'} dev: true + /css-select/4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + dev: false + /css-select/5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} dependencies: @@ -8078,7 +8127,6 @@ packages: /css-what/6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - dev: true /cssesc/3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -8134,6 +8182,11 @@ packages: /debug/3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.1.3 dev: false @@ -9585,7 +9638,6 @@ packages: /he/1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - dev: true /hosted-git-info/2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -11027,6 +11079,8 @@ packages: debug: 3.2.7 iconv-lite: 0.4.24 sax: 1.2.4 + transitivePeerDependencies: + - supports-color dev: false /netmask/2.0.2: @@ -11095,6 +11149,13 @@ packages: hasBin: true dev: false + /node-html-parser/5.3.3: + resolution: {integrity: sha512-ncg1033CaX9UexbyA7e1N0aAoAYRDiV8jkTvzEnfd1GDvzFdrsXLzR4p4ik8mwLgnaKP/jyUFWDy9q3jvRT2Jw==} + dependencies: + css-select: 4.3.0 + he: 1.2.0 + dev: false + /node-pre-gyp/0.13.0: resolution: {integrity: sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==} deprecated: 'Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future' @@ -11110,6 +11171,8 @@ packages: rimraf: 2.7.1 semver: 5.7.1 tar: 4.4.19 + transitivePeerDependencies: + - supports-color dev: false /node-releases/2.0.5: @@ -12436,6 +12499,17 @@ packages: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: false + /sitemap/7.1.1: + resolution: {integrity: sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==} + engines: {node: '>=12.0.0', npm: '>=5.6.0'} + hasBin: true + dependencies: + '@types/node': 17.0.41 + '@types/sax': 1.2.4 + arg: 5.0.2 + sax: 1.2.4 + dev: false + /slash/2.0.0: resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} engines: {node: '>=6'} From 1041a12bc51222aaae2f1091974b07a9b4d8cb0a Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Sun, 12 Jun 2022 11:10:55 +0300 Subject: [PATCH 2/8] docs: del samples --- examples/sitemap/advanced/.gitignore | 18 ------- examples/sitemap/advanced/.npmrc | 2 - examples/sitemap/advanced/.stackblitzrc | 6 --- examples/sitemap/advanced/README.md | 3 -- examples/sitemap/advanced/astro.config.ts | 8 ---- examples/sitemap/advanced/package.json | 17 ------- examples/sitemap/advanced/public/favicon.ico | Bin 4286 -> 0 bytes examples/sitemap/advanced/sandbox.config.json | 11 ----- examples/sitemap/advanced/sitemap.config.ts | 28 ----------- examples/sitemap/advanced/src/pages/404.astro | 14 ------ .../advanced/src/pages/exclude-this.astro | 13 ----- .../sitemap/advanced/src/pages/index.astro | 15 ------ .../advanced/src/pages/second-page.astro | 13 ----- .../advanced/src/pages/special-page.astro | 13 ----- examples/sitemap/advanced/tsconfig.json | 15 ------ examples/sitemap/basic/.gitignore | 18 ------- examples/sitemap/basic/.npmrc | 2 - examples/sitemap/basic/.stackblitzrc | 6 --- examples/sitemap/basic/README.md | 3 -- examples/sitemap/basic/astro.config.ts | 9 ---- examples/sitemap/basic/package.json | 17 ------- examples/sitemap/basic/public/favicon.ico | Bin 4286 -> 0 bytes examples/sitemap/basic/sandbox.config.json | 11 ----- examples/sitemap/basic/src/pages/index.astro | 12 ----- .../sitemap/basic/src/pages/second-page.astro | 13 ----- examples/sitemap/basic/tsconfig.json | 15 ------ examples/sitemap/i18n/.gitignore | 18 ------- examples/sitemap/i18n/.npmrc | 2 - examples/sitemap/i18n/.stackblitzrc | 6 --- examples/sitemap/i18n/README.md | 9 ---- examples/sitemap/i18n/astro.config.ts | 10 ---- examples/sitemap/i18n/package.json | 16 ------- examples/sitemap/i18n/sandbox.config.json | 11 ----- examples/sitemap/i18n/sitemap.config.ts | 15 ------ .../i18n/src/components/LanguageSwitch.astro | 45 ------------------ examples/sitemap/i18n/src/i18n.ts | 25 ---------- .../i18n/src/images/logomark-light.png | Bin 94580 -> 0 bytes .../i18n/src/images/logomark-light.svg | 15 ------ examples/sitemap/i18n/src/pages/404.astro | 17 ------- .../sitemap/i18n/src/pages/[locale]/404.astro | 32 ------------- .../i18n/src/pages/[locale]/index.astro | 38 --------------- .../i18n/src/pages/[locale]/second-page.astro | 36 -------------- examples/sitemap/i18n/src/pages/index.astro | 21 -------- .../sitemap/i18n/src/pages/second-page.astro | 19 -------- examples/sitemap/i18n/tsconfig.json | 15 ------ 45 files changed, 632 deletions(-) delete mode 100644 examples/sitemap/advanced/.gitignore delete mode 100644 examples/sitemap/advanced/.npmrc delete mode 100644 examples/sitemap/advanced/.stackblitzrc delete mode 100644 examples/sitemap/advanced/README.md delete mode 100644 examples/sitemap/advanced/astro.config.ts delete mode 100644 examples/sitemap/advanced/package.json delete mode 100644 examples/sitemap/advanced/public/favicon.ico delete mode 100644 examples/sitemap/advanced/sandbox.config.json delete mode 100644 examples/sitemap/advanced/sitemap.config.ts delete mode 100644 examples/sitemap/advanced/src/pages/404.astro delete mode 100644 examples/sitemap/advanced/src/pages/exclude-this.astro delete mode 100644 examples/sitemap/advanced/src/pages/index.astro delete mode 100644 examples/sitemap/advanced/src/pages/second-page.astro delete mode 100644 examples/sitemap/advanced/src/pages/special-page.astro delete mode 100644 examples/sitemap/advanced/tsconfig.json delete mode 100644 examples/sitemap/basic/.gitignore delete mode 100644 examples/sitemap/basic/.npmrc delete mode 100644 examples/sitemap/basic/.stackblitzrc delete mode 100644 examples/sitemap/basic/README.md delete mode 100644 examples/sitemap/basic/astro.config.ts delete mode 100644 examples/sitemap/basic/package.json delete mode 100644 examples/sitemap/basic/public/favicon.ico delete mode 100644 examples/sitemap/basic/sandbox.config.json delete mode 100644 examples/sitemap/basic/src/pages/index.astro delete mode 100644 examples/sitemap/basic/src/pages/second-page.astro delete mode 100644 examples/sitemap/basic/tsconfig.json delete mode 100644 examples/sitemap/i18n/.gitignore delete mode 100644 examples/sitemap/i18n/.npmrc delete mode 100644 examples/sitemap/i18n/.stackblitzrc delete mode 100644 examples/sitemap/i18n/README.md delete mode 100644 examples/sitemap/i18n/astro.config.ts delete mode 100644 examples/sitemap/i18n/package.json delete mode 100644 examples/sitemap/i18n/sandbox.config.json delete mode 100644 examples/sitemap/i18n/sitemap.config.ts delete mode 100644 examples/sitemap/i18n/src/components/LanguageSwitch.astro delete mode 100644 examples/sitemap/i18n/src/i18n.ts delete mode 100644 examples/sitemap/i18n/src/images/logomark-light.png delete mode 100644 examples/sitemap/i18n/src/images/logomark-light.svg delete mode 100644 examples/sitemap/i18n/src/pages/404.astro delete mode 100644 examples/sitemap/i18n/src/pages/[locale]/404.astro delete mode 100644 examples/sitemap/i18n/src/pages/[locale]/index.astro delete mode 100644 examples/sitemap/i18n/src/pages/[locale]/second-page.astro delete mode 100644 examples/sitemap/i18n/src/pages/index.astro delete mode 100644 examples/sitemap/i18n/src/pages/second-page.astro delete mode 100644 examples/sitemap/i18n/tsconfig.json diff --git a/examples/sitemap/advanced/.gitignore b/examples/sitemap/advanced/.gitignore deleted file mode 100644 index 6e9005893238..000000000000 --- a/examples/sitemap/advanced/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -# build output -dist/ - -# dependencies -node_modules/ - -# logs -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - -# environment variables -.env -.env.production - -# macOS-specific files -.DS_Store diff --git a/examples/sitemap/advanced/.npmrc b/examples/sitemap/advanced/.npmrc deleted file mode 100644 index ef83021af3ec..000000000000 --- a/examples/sitemap/advanced/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -# Expose Astro dependencies for `pnpm` users -shamefully-hoist=true diff --git a/examples/sitemap/advanced/.stackblitzrc b/examples/sitemap/advanced/.stackblitzrc deleted file mode 100644 index 0dfa8f1e0565..000000000000 --- a/examples/sitemap/advanced/.stackblitzrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "startCommand": "npm start", - "env": { - "ENABLE_CJS_IMPORTS": true - } -} diff --git a/examples/sitemap/advanced/README.md b/examples/sitemap/advanced/README.md deleted file mode 100644 index ab7786383aa4..000000000000 --- a/examples/sitemap/advanced/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Demo for @astrojs/sitemap integration - -Play this demo [online](https://stackblitz.com/fork/github/withastro/astro/tree/main/examples/sitemap/advanced). diff --git a/examples/sitemap/advanced/astro.config.ts b/examples/sitemap/advanced/astro.config.ts deleted file mode 100644 index b45aa1c588e0..000000000000 --- a/examples/sitemap/advanced/astro.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from 'astro/config'; -import sitemap from '@astrojs/sitemap'; -import sitemapConfig from './sitemap.config'; - -// https://astro.build/config -export default defineConfig({ - integrations: [sitemap(sitemapConfig)], -}); diff --git a/examples/sitemap/advanced/package.json b/examples/sitemap/advanced/package.json deleted file mode 100644 index c1174a3dee5b..000000000000 --- a/examples/sitemap/advanced/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@example/sitemap-advanced", - "version": "0.0.1", - "private": true, - "license": "MIT", - "type": "module", - "scripts": { - "dev": "astro dev", - "start": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "devDependencies": { - "astro": "workspace:*", - "@astrojs/sitemap": "workspace:*" - } -} diff --git a/examples/sitemap/advanced/public/favicon.ico b/examples/sitemap/advanced/public/favicon.ico deleted file mode 100644 index 578ad458b8906c08fbed84f42b045fea04db89d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmchZF=!M)6ox0}Fc8GdTHG!cdIY>nA!3n2f|wxIl0rn}Hl#=uf>?-!2r&jMEF^_k zh**lGut*gwBmoNv7AaB&2~nbzULg{WBhPQ{ZVzvF_HL8Cb&hv$_s#qN|IO^o>?+mA zuTW6tU%k~z<&{z+7$G%*nRsTcEO|90xy<-G5&JTt%CgZZCDT4%R?+{Vd^wh>P8_)} z`+dF$HQb9!>1o`Ivn;GInlCw{9T@Rt%q+d^T3Ke%cxkk;$v`{s^zCB9nHAv6w$Vbn z8fb<+eQTNM`;rf9#obfGnV#3+OQEUv4gU;{oA@zol%keY9-e>4W>p7AHmH~&!P7f7!Uj` zwgFeQ=<3G4O;mwWO`L!=R-=y3_~-DPjH3W^3f&jjCfC$o#|oGaahSL`_=f?$&Aa+W z2h8oZ+@?NUcjGW|aWJfbM*ZzxzmCPY`b~RobNrrj=rd`=)8-j`iSW64@0_b6?;GYk zNB+-fzOxlqZ?`y{OA$WigtZXa8)#p#=DPYxH=VeC_Q5q9Cv`mvW6*zU&Gnp1;oPM6 zaK_B3j(l^FyJgYeE9RrmDyhE7W2}}nW%ic#0v@i1E!yTey$W)U>fyd+!@2hWQ!Wa==NAtKoj`f3tp4y$Al`e;?)76?AjdaRR>|?&r)~3Git> zb1)a?uiv|R0_{m#A9c;7)eZ1y6l@yQ#oE*>(Z2fG-&&smPa2QTW>m*^K65^~`coP$ z8y5Y?iS<4Gz{Zg##$1mk)u-0;X|!xu^FCr;ce~X<&UWE&pBgqfYmEJTzpK9I%vr%b z3Ksd6qlPJLI%HFfeXK_^|BXiKZC>Ocu(Kk6hD3G-8usLzVG^q00Qh gz)s7ge@$ApxGu7=(6IGIk+uG&HTev01^#CH3$(Wk5&!@I diff --git a/examples/sitemap/advanced/sandbox.config.json b/examples/sitemap/advanced/sandbox.config.json deleted file mode 100644 index 9178af77d7de..000000000000 --- a/examples/sitemap/advanced/sandbox.config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "infiniteLoopProtection": true, - "hardReloadOnChange": false, - "view": "browser", - "template": "node", - "container": { - "port": 3000, - "startScript": "start", - "node": "14" - } -} diff --git a/examples/sitemap/advanced/sitemap.config.ts b/examples/sitemap/advanced/sitemap.config.ts deleted file mode 100644 index 6ddea6f3d1f7..000000000000 --- a/examples/sitemap/advanced/sitemap.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -const canonicalURL = 'https://example.com'; - -const sitemapConfig = { - filter: (page) => !/exclude-this/.test(page), // exclude pages from sitemap - customPages: [`${canonicalURL}/virtual-one.html`, `${canonicalURL}/virtual-two.html`], - canonicalURL, - - createLinkInHead: true, - - serialize(item) { - if (/special-page/.test(item.url)) { - item.changefreq = 'daily'; - item.lastmod = new Date(); - item.priority = 0.9; - } - return item; - }, - - // The integration creates a separate `sitemap-${i}.xml` file for each batch of 2, then adds this file to index - `sitemap-index.xml`. - entryLimit: 2, // default - 45000 - - // sitemap specific - changefreq: 'yearly', - lastmod: new Date('2019-12-31'), - priority: 0.4, -}; - -export default sitemapConfig; diff --git a/examples/sitemap/advanced/src/pages/404.astro b/examples/sitemap/advanced/src/pages/404.astro deleted file mode 100644 index 6abd145f8c4b..000000000000 --- a/examples/sitemap/advanced/src/pages/404.astro +++ /dev/null @@ -1,14 +0,0 @@ ---- ---- - - - - - 404 - - -

404

-

Not Found

- Back to Home - - diff --git a/examples/sitemap/advanced/src/pages/exclude-this.astro b/examples/sitemap/advanced/src/pages/exclude-this.astro deleted file mode 100644 index e7b23e2d997c..000000000000 --- a/examples/sitemap/advanced/src/pages/exclude-this.astro +++ /dev/null @@ -1,13 +0,0 @@ ---- ---- - - - - - Exclude this page - - -

Exclude this pade

- Back to Home - - diff --git a/examples/sitemap/advanced/src/pages/index.astro b/examples/sitemap/advanced/src/pages/index.astro deleted file mode 100644 index bd25ea7e2b42..000000000000 --- a/examples/sitemap/advanced/src/pages/index.astro +++ /dev/null @@ -1,15 +0,0 @@ ---- ---- - - - - - Astro - - -

Astro

- Second page - Special page - Exclude this page - - diff --git a/examples/sitemap/advanced/src/pages/second-page.astro b/examples/sitemap/advanced/src/pages/second-page.astro deleted file mode 100644 index 77cfad9f8550..000000000000 --- a/examples/sitemap/advanced/src/pages/second-page.astro +++ /dev/null @@ -1,13 +0,0 @@ ---- ---- - - - - - Second page - - -

Second page

- Back to Home - - diff --git a/examples/sitemap/advanced/src/pages/special-page.astro b/examples/sitemap/advanced/src/pages/special-page.astro deleted file mode 100644 index 54b3bcce1825..000000000000 --- a/examples/sitemap/advanced/src/pages/special-page.astro +++ /dev/null @@ -1,13 +0,0 @@ ---- ---- - - - - - Special page - - -

Special page

- Back to Home - - diff --git a/examples/sitemap/advanced/tsconfig.json b/examples/sitemap/advanced/tsconfig.json deleted file mode 100644 index 7ac81809afda..000000000000 --- a/examples/sitemap/advanced/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - // Enable top-level await, and other modern ESM features. - "target": "ESNext", - "module": "ESNext", - // Enable node-style module resolution, for things like npm package imports. - "moduleResolution": "node", - // Enable JSON imports. - "resolveJsonModule": true, - // Enable stricter transpilation for better output. - "isolatedModules": true, - // Add type definitions for our Vite runtime. - "types": ["vite/client"] - } -} diff --git a/examples/sitemap/basic/.gitignore b/examples/sitemap/basic/.gitignore deleted file mode 100644 index 6e9005893238..000000000000 --- a/examples/sitemap/basic/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -# build output -dist/ - -# dependencies -node_modules/ - -# logs -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - -# environment variables -.env -.env.production - -# macOS-specific files -.DS_Store diff --git a/examples/sitemap/basic/.npmrc b/examples/sitemap/basic/.npmrc deleted file mode 100644 index ef83021af3ec..000000000000 --- a/examples/sitemap/basic/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -# Expose Astro dependencies for `pnpm` users -shamefully-hoist=true diff --git a/examples/sitemap/basic/.stackblitzrc b/examples/sitemap/basic/.stackblitzrc deleted file mode 100644 index 0dfa8f1e0565..000000000000 --- a/examples/sitemap/basic/.stackblitzrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "startCommand": "npm start", - "env": { - "ENABLE_CJS_IMPORTS": true - } -} diff --git a/examples/sitemap/basic/README.md b/examples/sitemap/basic/README.md deleted file mode 100644 index d690ff6cca7e..000000000000 --- a/examples/sitemap/basic/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Demo for @astrojs/sitemap integration - -Play this demo [online](https://stackblitz.com/fork/github/withastro/astro/tree/main/examples/sitemap/basic). diff --git a/examples/sitemap/basic/astro.config.ts b/examples/sitemap/basic/astro.config.ts deleted file mode 100644 index 752cf3cfe6f6..000000000000 --- a/examples/sitemap/basic/astro.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defineConfig } from 'astro/config'; -import sitemap from '@astrojs/sitemap'; - -// https://astro.build/config -export default defineConfig({ - site: 'https://example.com', - base: 'test', - integrations: [sitemap()], -}); diff --git a/examples/sitemap/basic/package.json b/examples/sitemap/basic/package.json deleted file mode 100644 index b232e45f1c6b..000000000000 --- a/examples/sitemap/basic/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@example/sitemap-basic", - "version": "0.0.1", - "private": true, - "license": "MIT", - "type": "module", - "scripts": { - "dev": "astro dev", - "start": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "devDependencies": { - "astro": "workspace:*", - "@astrojs/sitemap": "workspace:*" - } -} diff --git a/examples/sitemap/basic/public/favicon.ico b/examples/sitemap/basic/public/favicon.ico deleted file mode 100644 index 578ad458b8906c08fbed84f42b045fea04db89d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmchZF=!M)6ox0}Fc8GdTHG!cdIY>nA!3n2f|wxIl0rn}Hl#=uf>?-!2r&jMEF^_k zh**lGut*gwBmoNv7AaB&2~nbzULg{WBhPQ{ZVzvF_HL8Cb&hv$_s#qN|IO^o>?+mA zuTW6tU%k~z<&{z+7$G%*nRsTcEO|90xy<-G5&JTt%CgZZCDT4%R?+{Vd^wh>P8_)} z`+dF$HQb9!>1o`Ivn;GInlCw{9T@Rt%q+d^T3Ke%cxkk;$v`{s^zCB9nHAv6w$Vbn z8fb<+eQTNM`;rf9#obfGnV#3+OQEUv4gU;{oA@zol%keY9-e>4W>p7AHmH~&!P7f7!Uj` zwgFeQ=<3G4O;mwWO`L!=R-=y3_~-DPjH3W^3f&jjCfC$o#|oGaahSL`_=f?$&Aa+W z2h8oZ+@?NUcjGW|aWJfbM*ZzxzmCPY`b~RobNrrj=rd`=)8-j`iSW64@0_b6?;GYk zNB+-fzOxlqZ?`y{OA$WigtZXa8)#p#=DPYxH=VeC_Q5q9Cv`mvW6*zU&Gnp1;oPM6 zaK_B3j(l^FyJgYeE9RrmDyhE7W2}}nW%ic#0v@i1E!yTey$W)U>fyd+!@2hWQ!Wa==NAtKoj`f3tp4y$Al`e;?)76?AjdaRR>|?&r)~3Git> zb1)a?uiv|R0_{m#A9c;7)eZ1y6l@yQ#oE*>(Z2fG-&&smPa2QTW>m*^K65^~`coP$ z8y5Y?iS<4Gz{Zg##$1mk)u-0;X|!xu^FCr;ce~X<&UWE&pBgqfYmEJTzpK9I%vr%b z3Ksd6qlPJLI%HFfeXK_^|BXiKZC>Ocu(Kk6hD3G-8usLzVG^q00Qh gz)s7ge@$ApxGu7=(6IGIk+uG&HTev01^#CH3$(Wk5&!@I diff --git a/examples/sitemap/basic/sandbox.config.json b/examples/sitemap/basic/sandbox.config.json deleted file mode 100644 index 9178af77d7de..000000000000 --- a/examples/sitemap/basic/sandbox.config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "infiniteLoopProtection": true, - "hardReloadOnChange": false, - "view": "browser", - "template": "node", - "container": { - "port": 3000, - "startScript": "start", - "node": "14" - } -} diff --git a/examples/sitemap/basic/src/pages/index.astro b/examples/sitemap/basic/src/pages/index.astro deleted file mode 100644 index 5e6ba1a2b01f..000000000000 --- a/examples/sitemap/basic/src/pages/index.astro +++ /dev/null @@ -1,12 +0,0 @@ ---- ---- - - - - - Astro - - -

Astro

- - diff --git a/examples/sitemap/basic/src/pages/second-page.astro b/examples/sitemap/basic/src/pages/second-page.astro deleted file mode 100644 index 77cfad9f8550..000000000000 --- a/examples/sitemap/basic/src/pages/second-page.astro +++ /dev/null @@ -1,13 +0,0 @@ ---- ---- - - - - - Second page - - -

Second page

- Back to Home - - diff --git a/examples/sitemap/basic/tsconfig.json b/examples/sitemap/basic/tsconfig.json deleted file mode 100644 index 7ac81809afda..000000000000 --- a/examples/sitemap/basic/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - // Enable top-level await, and other modern ESM features. - "target": "ESNext", - "module": "ESNext", - // Enable node-style module resolution, for things like npm package imports. - "moduleResolution": "node", - // Enable JSON imports. - "resolveJsonModule": true, - // Enable stricter transpilation for better output. - "isolatedModules": true, - // Add type definitions for our Vite runtime. - "types": ["vite/client"] - } -} diff --git a/examples/sitemap/i18n/.gitignore b/examples/sitemap/i18n/.gitignore deleted file mode 100644 index 6e9005893238..000000000000 --- a/examples/sitemap/i18n/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -# build output -dist/ - -# dependencies -node_modules/ - -# logs -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - -# environment variables -.env -.env.production - -# macOS-specific files -.DS_Store diff --git a/examples/sitemap/i18n/.npmrc b/examples/sitemap/i18n/.npmrc deleted file mode 100644 index ef83021af3ec..000000000000 --- a/examples/sitemap/i18n/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -# Expose Astro dependencies for `pnpm` users -shamefully-hoist=true diff --git a/examples/sitemap/i18n/.stackblitzrc b/examples/sitemap/i18n/.stackblitzrc deleted file mode 100644 index 0dfa8f1e0565..000000000000 --- a/examples/sitemap/i18n/.stackblitzrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "startCommand": "npm start", - "env": { - "ENABLE_CJS_IMPORTS": true - } -} diff --git a/examples/sitemap/i18n/README.md b/examples/sitemap/i18n/README.md deleted file mode 100644 index e053a3191062..000000000000 --- a/examples/sitemap/i18n/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Demo for @astrojs/sitemap integration - -This sample demonstrates the localization capabilities of `@astrojs/sitemap` integration. - -The `i18n.mjs` file contains the locales basic info. - -Its data is used for dynamic page generation, for language switch and as a source for the `@astrojs/sitemap` integration config. - -Play this demo [online](https://stackblitz.com/fork/github/withastro/astro/tree/main/examples/sitemap/i18n). diff --git a/examples/sitemap/i18n/astro.config.ts b/examples/sitemap/i18n/astro.config.ts deleted file mode 100644 index 6c2f39556f9b..000000000000 --- a/examples/sitemap/i18n/astro.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'astro/config'; -import sitemap from '@astrojs/sitemap'; - -import sitemapConfig from './sitemap.config'; - -// https://astro.build/config -export default defineConfig({ - site: 'https://another.com', - integrations: [sitemap(sitemapConfig)], -}); diff --git a/examples/sitemap/i18n/package.json b/examples/sitemap/i18n/package.json deleted file mode 100644 index 1eba1ccb5a8b..000000000000 --- a/examples/sitemap/i18n/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "@example/sitemap-i18n", - "version": "0.0.1", - "private": true, - "license": "MIT", - "scripts": { - "dev": "astro dev", - "start": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "devDependencies": { - "astro": "workspace:*", - "@astrojs/sitemap": "workspace:*" - } -} diff --git a/examples/sitemap/i18n/sandbox.config.json b/examples/sitemap/i18n/sandbox.config.json deleted file mode 100644 index 9178af77d7de..000000000000 --- a/examples/sitemap/i18n/sandbox.config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "infiniteLoopProtection": true, - "hardReloadOnChange": false, - "view": "browser", - "template": "node", - "container": { - "port": 3000, - "startScript": "start", - "node": "14" - } -} diff --git a/examples/sitemap/i18n/sitemap.config.ts b/examples/sitemap/i18n/sitemap.config.ts deleted file mode 100644 index 044c630df53e..000000000000 --- a/examples/sitemap/i18n/sitemap.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import i18n from './src/i18n.js'; - -/** @type {import('astro-sitemap').SitemapOptions} */ -const sitemapConfig = { - // added - i18n: { - defaultLocale: i18n.defaultLocale, - locales: Object.entries(i18n.locales).reduce((prev, [locale, { lang }]) => { - prev[locale] = lang; - return prev; - }, {}), - }, -}; - -export default sitemapConfig; diff --git a/examples/sitemap/i18n/src/components/LanguageSwitch.astro b/examples/sitemap/i18n/src/components/LanguageSwitch.astro deleted file mode 100644 index 9d25716241e3..000000000000 --- a/examples/sitemap/i18n/src/components/LanguageSwitch.astro +++ /dev/null @@ -1,45 +0,0 @@ ---- -import i18n from '../i18n'; - -export interface Props { - currentLocale: string; -} - -const { currentLocale } = Astro.props as Props; -const pathname = new URL(Astro.request.url).pathname; - -const getLink = (locale: string) => { - let path: string; - if (pathname === '/') { - path = '/'; - } else { - const a = pathname.split('/'); - if (i18n.locales[a[1]]) { - path = a.slice(2).join('/'); - } else { - path = pathname; - } - } - if (!path.startsWith('/')) { - path = '/' + path; - } - return locale === i18n.defaultLocale ? path : `/${locale}${path}`; -}; ---- -
    -{ - Object.keys(i18n.locales).map((locale) => ( -
  • - {locale === currentLocale ? ( - - {locale} - - ) : ( - - {locale} - - )} -
  • - )) -} -
diff --git a/examples/sitemap/i18n/src/i18n.ts b/examples/sitemap/i18n/src/i18n.ts deleted file mode 100644 index 25015676a31b..000000000000 --- a/examples/sitemap/i18n/src/i18n.ts +++ /dev/null @@ -1,25 +0,0 @@ -const i18n = { - defaultLocale: 'en', - locales: { - en: { - name: 'i18n test', - short_name: 'Test', - description: 'This is the application description', - lang: 'en-US', - }, - es: { - name: 'Prueba i18n', - short_name: 'Prueba', - description: 'Esta es la descripciĆ³n de la aplicaciĆ³n.', - lang: 'es-ES', - }, - fr: { - name: 'Test i18n', - short_name: 'Test', - description: "Ceci est la description de l'application", - lang: 'fr-CA', - }, - }, -}; - -export default i18n; diff --git a/examples/sitemap/i18n/src/images/logomark-light.png b/examples/sitemap/i18n/src/images/logomark-light.png deleted file mode 100644 index b77f87fc58e37bf7adf47edf300b603309bedfef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94580 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 - - - - - - - - - - - - - - diff --git a/examples/sitemap/i18n/src/pages/404.astro b/examples/sitemap/i18n/src/pages/404.astro deleted file mode 100644 index 95ef4a175609..000000000000 --- a/examples/sitemap/i18n/src/pages/404.astro +++ /dev/null @@ -1,17 +0,0 @@ ---- -import i18n from '../i18n'; - -const locale = i18n.defaultLocale; -const { lang } = i18n.locales[locale]; ---- - - - - - 404 - - -

404

-
- - diff --git a/examples/sitemap/i18n/src/pages/[locale]/404.astro b/examples/sitemap/i18n/src/pages/[locale]/404.astro deleted file mode 100644 index 270790f673b5..000000000000 --- a/examples/sitemap/i18n/src/pages/[locale]/404.astro +++ /dev/null @@ -1,32 +0,0 @@ ---- -import i18n from '../../i18n'; - -export async function getStaticPaths() { - const items = Object.entries(i18n.locales).filter(([locale]) => locale !== i18n.defaultLocale); - - const paths = items.map(([locale, { lang }]) => ({ - params: { locale }, - props: { lang }, - })); - - return paths; -} - -export interface Props { - lang: string; -} - -const { locale } = Astro.params; -const { lang } = Astro.props as Props; ---- - - - - - 404 - - -

404

- - - diff --git a/examples/sitemap/i18n/src/pages/[locale]/index.astro b/examples/sitemap/i18n/src/pages/[locale]/index.astro deleted file mode 100644 index d28571f09723..000000000000 --- a/examples/sitemap/i18n/src/pages/[locale]/index.astro +++ /dev/null @@ -1,38 +0,0 @@ ---- -import i18n from '../../i18n'; -import LanguageSwitch from '../../components/LanguageSwitch.astro'; - -export async function getStaticPaths() { - const items = Object.entries(i18n.locales).filter(([locale]) => locale !== i18n.defaultLocale); - - const paths = items.map(([locale, { name, lang }]) => ({ - params: { locale }, - props: { name, lang }, - })); - - return paths; -} - -export interface Props { - name: string; - description: string; - lang: string; -} - -const { locale } = Astro.params; -const { name, description, lang } = Astro.props as Props; ---- - - - - - Astro {locale} - - -

Astro {locale}

-

{name}

-

{description}

- #2 - - - diff --git a/examples/sitemap/i18n/src/pages/[locale]/second-page.astro b/examples/sitemap/i18n/src/pages/[locale]/second-page.astro deleted file mode 100644 index 97f04f58d893..000000000000 --- a/examples/sitemap/i18n/src/pages/[locale]/second-page.astro +++ /dev/null @@ -1,36 +0,0 @@ ---- -import i18n from '../../i18n'; -import LanguageSwitch from '../../components/LanguageSwitch.astro'; - -export async function getStaticPaths() { - const items = Object.entries(i18n.locales).filter(([locale]) => locale !== i18n.defaultLocale); - - const paths = items.map(([locale, { name, lang }]) => ({ - params: { locale }, - props: { name, lang }, - })); - - return paths; -} - -export interface Props { - name: string; - description: string; - lang: string; -} - -const { locale } = Astro.params; -const { lang } = Astro.props as Props; ---- - - - - - #2 {locale} - - -

#2 {locale}

- - - - diff --git a/examples/sitemap/i18n/src/pages/index.astro b/examples/sitemap/i18n/src/pages/index.astro deleted file mode 100644 index 71c0e1734255..000000000000 --- a/examples/sitemap/i18n/src/pages/index.astro +++ /dev/null @@ -1,21 +0,0 @@ ---- -import i18n from '../i18n'; -import LanguageSwitch from '../components/LanguageSwitch.astro'; - -const locale = i18n.defaultLocale; -const { lang, name, description } = i18n.locales[locale]; ---- - - - - - Astro {locale} - - -

Astro {locale}

-

{name}

-

{description}

- #2 - - - diff --git a/examples/sitemap/i18n/src/pages/second-page.astro b/examples/sitemap/i18n/src/pages/second-page.astro deleted file mode 100644 index 10dc0cac4fdd..000000000000 --- a/examples/sitemap/i18n/src/pages/second-page.astro +++ /dev/null @@ -1,19 +0,0 @@ ---- -import i18n from '../i18n'; -import LanguageSwitch from '../components/LanguageSwitch.astro'; - -const locale = i18n.defaultLocale; -const { lang } = i18n.locales[locale]; ---- - - - - - #2 {locale} - - -

#2 {locale}

- - - - diff --git a/examples/sitemap/i18n/tsconfig.json b/examples/sitemap/i18n/tsconfig.json deleted file mode 100644 index 7ac81809afda..000000000000 --- a/examples/sitemap/i18n/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - // Enable top-level await, and other modern ESM features. - "target": "ESNext", - "module": "ESNext", - // Enable node-style module resolution, for things like npm package imports. - "moduleResolution": "node", - // Enable JSON imports. - "resolveJsonModule": true, - // Enable stricter transpilation for better output. - "isolatedModules": true, - // Add type definitions for our Vite runtime. - "types": ["vite/client"] - } -} From c7898694347938d1dc10d72b01eb7ddec773e2cc Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Sun, 12 Jun 2022 11:46:49 +0300 Subject: [PATCH 3/8] docs: readme --- packages/integrations/sitemap/README.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/integrations/sitemap/README.md b/packages/integrations/sitemap/README.md index 1c6cb9fbc90d..601598a0117c 100644 --- a/packages/integrations/sitemap/README.md +++ b/packages/integrations/sitemap/README.md @@ -218,7 +218,14 @@ export default { ### serialize -Async or sync function called for each SiteMap item just before writing to disk. +Async or sync function called for each sitemap entry just before writing to disk. + +It receives as parameter `SitemapItem` object which consists of `url` (required, absolute URL of page) and optional `changefreq`, `lastmod`, `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). + +`serialize` function should return `SitemapItem`, touched or not. __astro.config.mjs__ @@ -244,12 +251,13 @@ export default { ### i18n -To localize sitemap, please, supply the integration config with the `i18n` options. The integration will check generated page paths on presence of locale keys in paths. +To localize sitemap you should supply the integration config with the `i18n` option. The integration will check generated page paths on presence of locale keys in paths. + +`i18n` object has two required properties: -`i18n` oject should have two required properties: +- `defaultLocale`: `String`. Its value must exist as one of `locales` keys. +- `locales`: `Record`, key/value - pairs. The key is used to look for a locale part in a page path. The value is a language attribute, only English alphabet and hyphen allowed. See more about language attribute on [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang). -- `defaultLocale`: `String`. Its value must exist as one of `locales` keys. -- `locales`: `Record`, key/value - pairs. The key is used to look for a locale part in a page path. The value is a language attribute, only English alphabet and hyphen allowed. See more on [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang). Read more about localization on Google in [Advanced SEO](https://developers.google.com/search/docs/advanced/crawling/localized-versions#all-method-guidelines). From 9ed2bd7c3af7750998730cd2dec48b33d43c651c Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Sun, 12 Jun 2022 15:52:38 +0300 Subject: [PATCH 4/8] feat: new sitemap --- .changeset/popular-cherries-float.md | 19 +++++++++++++++++++ package.json | 6 ------ pnpm-lock.yaml | 28 +--------------------------- 3 files changed, 20 insertions(+), 33 deletions(-) create mode 100644 .changeset/popular-cherries-float.md diff --git a/.changeset/popular-cherries-float.md b/.changeset/popular-cherries-float.md new file mode 100644 index 000000000000..4c04c4e5d958 --- /dev/null +++ b/.changeset/popular-cherries-float.md @@ -0,0 +1,19 @@ +--- +'@astrojs/sitemap': minor +--- + +# Key features + +- Split up your large sitemap into multiple sitemaps by custom limit. +- Ability to add sitemap specific attributes such as `lastmod` etc. +- Final output customization via JS function. +- Localization support. +- Automatically creates a link to sitemap in `` section of generated pages. +- Reliability: all config options are validated. + +## Important changes + +The integration always generates at least two files instead of one: + +- `sitemap-index.xml` - index file; +- `sitemap-{i}.xml` - actual sitemap. diff --git a/package.json b/package.json index 76339cd09113..3be9d8e87c05 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,6 @@ "build": "turbo run build --no-deps --scope=astro --scope=create-astro --scope=\"@astrojs/*\"", "build:ci": "turbo run build:ci --no-deps --scope=astro --scope=create-astro --scope=\"@astrojs/*\"", "build:examples": "turbo run build --scope=\"@example/*\"", - "build:0": "turbo run build --no-deps --scope=@astrojs/sitemap", - "build:ex-a": "turbo run build --no-deps --scope=\"@example/sitemap-*\"", - "build:s": "turbo run build --scope=@example/starter", - "build:a": "turbo run build --scope=@example/sitemap-advanced", - "build:b": "turbo run build --scope=@example/sitemap-basic", - "build:i": "turbo run build --scope=@example/sitemap-i18n", "dev": "turbo run dev --no-deps --no-cache --parallel --scope=astro --scope=create-astro --scope=\"@astrojs/*\"", "format": "pnpm run format:code", "format:ci": "pnpm run format:imports && pnpm run format:code", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 998afaa6e234..c5c4fd6c80c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -246,7 +246,7 @@ importers: '@astrojs/lit': ^0.1.5 '@astrojs/partytown': ^0.1.4 '@astrojs/react': ^0.1.3 - '@astrojs/sitemap': workspace:* + '@astrojs/sitemap': ^0.1.2 '@astrojs/solid-js': 0.1.4 '@astrojs/tailwind': ^0.2.1 '@astrojs/turbolinks': ^0.1.3 @@ -303,30 +303,6 @@ importers: astro: link:../../packages/astro sass: 1.52.2 - examples/sitemap/advanced: - specifiers: - '@astrojs/sitemap': workspace:* - astro: workspace:* - devDependencies: - '@astrojs/sitemap': link:../../../packages/integrations/sitemap - astro: link:../../../packages/astro - - examples/sitemap/basic: - specifiers: - '@astrojs/sitemap': workspace:* - astro: workspace:* - devDependencies: - '@astrojs/sitemap': link:../../../packages/integrations/sitemap - astro: link:../../../packages/astro - - examples/sitemap/i18n: - specifiers: - '@astrojs/sitemap': workspace:* - astro: workspace:* - devDependencies: - '@astrojs/sitemap': link:../../../packages/integrations/sitemap - astro: link:../../../packages/astro - examples/ssr: specifiers: '@astrojs/node': ^0.1.2 @@ -350,10 +326,8 @@ importers: examples/starter: specifiers: - '@astrojs/markdown-remark': ^0.11.2 astro: ^1.0.0-beta.44 devDependencies: - '@astrojs/markdown-remark': link:../../packages/markdown/remark astro: link:../../packages/astro examples/subpath: From 8ea53d0b58aa9b33f39bd0d41fd5ecdf90d3f7ee Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Thu, 16 Jun 2022 01:09:08 +0300 Subject: [PATCH 5/8] feat: createLinkInHead removed --- packages/integrations/sitemap/README.md | 40 +-- packages/integrations/sitemap/package.json | 3 +- .../sitemap/src/config-defaults.ts | 5 + .../integrations/sitemap/src/constants.ts | 10 +- .../sitemap/src/generate-sitemap.ts | 90 +++---- packages/integrations/sitemap/src/index.ts | 240 +++++++++--------- .../integrations/sitemap/src/process-pages.ts | 39 --- packages/integrations/sitemap/src/schema.ts | 85 +++---- .../sitemap/src/utils/is-object-empty.ts | 14 +- .../sitemap/src/utils/is-valid-url.ts | 20 +- .../integrations/sitemap/src/utils/logger.ts | 78 +++--- .../sitemap/src/utils/parse-url.ts | 65 +++-- .../sitemap/src/validate-options.ts | 22 ++ .../integrations/sitemap/src/validate-opts.ts | 16 -- .../integrations/sitemap/src/with-options.ts | 20 -- pnpm-lock.yaml | 21 +- 16 files changed, 341 insertions(+), 427 deletions(-) create mode 100644 packages/integrations/sitemap/src/config-defaults.ts delete mode 100644 packages/integrations/sitemap/src/process-pages.ts create mode 100644 packages/integrations/sitemap/src/validate-options.ts delete mode 100644 packages/integrations/sitemap/src/validate-opts.ts delete mode 100644 packages/integrations/sitemap/src/with-options.ts diff --git a/packages/integrations/sitemap/README.md b/packages/integrations/sitemap/README.md index 601598a0117c..ab880a075f0a 100644 --- a/packages/integrations/sitemap/README.md +++ b/packages/integrations/sitemap/README.md @@ -94,12 +94,6 @@ Generated sitemap content for two pages website: ``` -All pages generated during build will contain in `` section a link to sitemap: - -```html - -``` - You can also check our [Astro Integration Documentation][astro-integration] for more on integrations. ## Configuration @@ -164,26 +158,6 @@ export default { } ``` -### createLinkInHead - -`Boolean`, default is `true`, create a link on sitemap in `` section of generated pages. - -__astro.config.mjs__ - -```js -import sitemap from '@astrojs/sitemap'; - -export default { - site: 'https://stargazers.club', - integrations: [ - sitemap({ - // disable create links to sitemap in - createLinkInHead: false, - }), - ], -} -``` - ### changefreq, lastmod, priority `changefreq` - How frequently the page is likely to change. Available values: `always` \| `hourly` \| `daily` \| `weekly` \| `monthly` \| `yearly` \| `never`. @@ -197,7 +171,7 @@ export default { See detailed explanation of sitemap specific options on [sitemap.org](https://www.sitemaps.org/protocol.html). -:exclamation: This integration uses 'astro:build:done' hook. The hook exposes only generated page paths. So with present version of Astro the integration has no abilities to analyze a page source, frontmatter etc. The integration can add `changefreq`, `lastmod` and `priority` attributes only in a batch or nothing. +:exclamation: This integration uses 'astro:build:done' hook. The hook exposes generated page paths only. So with present version of Astro the integration has no abilities to analyze a page source, frontmatter etc. The integration can add `changefreq`, `lastmod` and `priority` attributes only in a batch or nothing. __astro.config.mjs__ @@ -210,7 +184,7 @@ export default { sitemap({ changefreq: 'weekly', priority: 0.7, - lastmod: new Date('2022-05-28'), + lastmod: new Date('2022-02-24'), }), ], } @@ -218,15 +192,17 @@ export default { ### serialize -Async or sync function called for each sitemap entry just before writing to disk. +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 URL of page) and optional `changefreq`, `lastmod`, `priority` and `links` properties. +It receives as parameter `SitemapItem` object which consists of `url` (required, absolute page URL) and optional `changefreq`, `lastmod`, `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). `serialize` function should return `SitemapItem`, touched or not. +The example below shows the ability to add the sitemap specific properties individually. + __astro.config.mjs__ ```js @@ -237,7 +213,7 @@ export default { integrations: [ sitemap({ serialize(item) { - if (/special-page/.test(item.url)) { + if (/your-special-page/.test(item.url)) { item.changefreq = 'daily'; item.lastmod = new Date(); item.priority = 0.9; @@ -251,7 +227,7 @@ export default { ### i18n -To localize sitemap you should supply the integration config with the `i18n` option. The integration will check generated page paths on presence of locale keys in paths. +To localize a sitemap you should supply the integration config with the `i18n` option. The integration will check generated page paths on presence of locale keys in paths. `i18n` object has two required properties: diff --git a/packages/integrations/sitemap/package.json b/packages/integrations/sitemap/package.json index 12b49ec4bad2..d61c608b3b54 100644 --- a/packages/integrations/sitemap/package.json +++ b/packages/integrations/sitemap/package.json @@ -31,9 +31,8 @@ "dev": "astro-scripts dev \"src/**/*.ts\"" }, "dependencies": { - "node-html-parser": "^5.3.3", "sitemap": "^7.1.1", - "zod": "^3.17.3" + "zod": "^3.17.3" }, "devDependencies": { "astro": "workspace:*", diff --git a/packages/integrations/sitemap/src/config-defaults.ts b/packages/integrations/sitemap/src/config-defaults.ts new file mode 100644 index 000000000000..22288fc119eb --- /dev/null +++ b/packages/integrations/sitemap/src/config-defaults.ts @@ -0,0 +1,5 @@ +import type { SitemapOptions } from './index'; + +export const SITEMAP_CONFIG_DEFAULTS: SitemapOptions & any = { + entryLimit: 45000, +}; diff --git a/packages/integrations/sitemap/src/constants.ts b/packages/integrations/sitemap/src/constants.ts index c983e1b1c427..431cc5954e13 100644 --- a/packages/integrations/sitemap/src/constants.ts +++ b/packages/integrations/sitemap/src/constants.ts @@ -1 +1,9 @@ -export const changefreqValues = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'] as const; +export const changefreqValues = [ + 'always', + 'hourly', + 'daily', + 'weekly', + 'monthly', + 'yearly', + 'never', +] as const; diff --git a/packages/integrations/sitemap/src/generate-sitemap.ts b/packages/integrations/sitemap/src/generate-sitemap.ts index f2c2ea7ce7e1..3c39e1f7ec45 100644 --- a/packages/integrations/sitemap/src/generate-sitemap.ts +++ b/packages/integrations/sitemap/src/generate-sitemap.ts @@ -7,49 +7,49 @@ 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 || {}; - // TODO: find way to respect 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 || {}); - - const getPath = (url: string) => { - const result = parseUrl(url, i18n?.defaultLocale || '', localeCodes, finalSiteUrl); - return result?.path; - }; - const getLocale = (url: string) => { - const result = parseUrl(url, i18n?.defaultLocale || '', localeCodes, finalSiteUrl); - return result?.locale; - }; - - const urlData = urls.map((url) => { - let links; - if (defaultLocale && locales) { - const currentPath = getPath(url); - if (currentPath) { - const filtered = urls.filter((subUrl) => getPath(subUrl) === currentPath); - if (filtered.length > 1) { - links = filtered.map((subUrl) => ({ - url: subUrl, - lang: locales[getLocale(subUrl)!], - })); - } - } - } - - return { - url, - links, - lastmod, - priority, - changefreq, // : changefreq as EnumChangefreq, - } as SitemapItemLoose; - }); - - return urlData; + const { changefreq, priority: prioritySrc, lastmod: lastmodSrc, i18n } = opts || {}; + // TODO: find way to respect 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 || {}); + + const getPath = (url: string) => { + const result = parseUrl(url, i18n?.defaultLocale || '', localeCodes, finalSiteUrl); + return result?.path; + }; + const getLocale = (url: string) => { + const result = parseUrl(url, i18n?.defaultLocale || '', localeCodes, finalSiteUrl); + return result?.locale; + }; + + const urlData = urls.map((url) => { + let links; + if (defaultLocale && locales) { + const currentPath = getPath(url); + if (currentPath) { + const filtered = urls.filter((subUrl) => getPath(subUrl) === currentPath); + if (filtered.length > 1) { + links = filtered.map((subUrl) => ({ + url: subUrl, + lang: locales[getLocale(subUrl)!], + })); + } + } + } + + return { + url, + links, + lastmod, + priority, + changefreq, // : changefreq as EnumChangefreq, + } as SitemapItemLoose; + }); + + return urlData; } diff --git a/packages/integrations/sitemap/src/index.ts b/packages/integrations/sitemap/src/index.ts index d0004ae91613..700f68876926 100644 --- a/packages/integrations/sitemap/src/index.ts +++ b/packages/integrations/sitemap/src/index.ts @@ -1,148 +1,138 @@ -import path from 'node:path'; import { fileURLToPath } from 'url'; import type { AstroConfig, AstroIntegration } from 'astro'; import { ZodError } from 'zod'; import { LinkItem as LinkItemBase, SitemapItemLoose, simpleSitemapAndIndex } from 'sitemap'; import { Logger } from './utils/logger'; -import { withOptions } from './with-options'; -import { validateOpts } from './validate-opts'; -import { generateSitemap } from './generate-sitemap'; import { changefreqValues } from './constants'; -import { processPages } from './process-pages'; +import { validateOptions } from './validate-options'; +import { generateSitemap } from './generate-sitemap'; export type ChangeFreq = typeof changefreqValues[number]; -export type SitemapItem = Pick; +export type SitemapItem = Pick< + SitemapItemLoose, + 'url' | 'lastmod' | 'changefreq' | 'priority' | 'links' +>; export type LinkItem = LinkItemBase; export type SitemapOptions = - | { - // the same with official - filter?(page: string): boolean; - customPages?: string[]; - canonicalURL?: string; - // added - i18n?: { - defaultLocale: string; - locales: Record; - }; - entryLimit?: number; - - createLinkInHead?: boolean; - serialize?(item: SitemapItemLoose): SitemapItemLoose; - // sitemap specific - changefreq?: ChangeFreq; - lastmod?: Date; - priority?: number; - } - | undefined; + | { + filter?(page: string): boolean; + customPages?: string[]; + canonicalURL?: string; + + i18n?: { + defaultLocale: string; + locales: Record; + }; + // number of entries per sitemap file + entryLimit?: number; + + // sitemap specific + changefreq?: ChangeFreq; + lastmod?: Date; + priority?: number; + + // called for each sitemap item just before to save them on disk, sync or async + serialize?(item: SitemapItemLoose): SitemapItemLoose; + } + | undefined; function formatConfigErrorMessage(err: ZodError) { - const errorList = err.issues.map((issue) => ` ${issue.path.join('.')} ${issue.message + '.'}`); - return errorList.join('\n'); + const errorList = err.issues.map((issue) => ` ${issue.path.join('.')} ${issue.message + '.'}`); + return errorList.join('\n'); } const PKG_NAME = '@astrojs/sitemap'; const OUTFILE = 'sitemap-index.xml'; const createPlugin = (options?: SitemapOptions): AstroIntegration => { - let config: AstroConfig; - return { - name: PKG_NAME, - - hooks: { - 'astro:config:done': async ({ config: cfg }) => { - config = cfg; - }, - - 'astro:build:done': async ({ dir, pages }) => { - const logger = new Logger(PKG_NAME); - - const opts = withOptions(options || {}); - - try { - validateOpts(config.site, opts); - - const { filter, customPages, canonicalURL, serialize, createLinkInHead, entryLimit } = opts; - - let finalSiteUrl: URL; - if (canonicalURL) { - finalSiteUrl = new URL(canonicalURL); - if (!finalSiteUrl.pathname.endsWith('/')) { - finalSiteUrl.pathname += '/'; // normalizes the final url since it's provided by user - } - } else { - // `validateOpts` forces to provide `canonicalURL` or `config.site` at least. - // So step to check on empty values of `canonicalURL` and `config.site` is dropped. - finalSiteUrl = new URL(config.base, config.site); - } - - let pageUrls = pages.map((p) => { - const path = finalSiteUrl.pathname + p.pathname; - return new URL(path, finalSiteUrl).href; - }); - - try { - if (filter) { - pageUrls = pageUrls.filter((url) => filter(url)); - } - } catch (err) { - logger.error(`Error filtering pages\n${(err as any).toString()}`); - return; - } - - if (customPages) { - pageUrls = [...pageUrls, ...customPages]; - } - - if (pageUrls.length === 0) { - logger.warn(`No data for sitemap.\n\`${OUTFILE}\` is not created.`); - return; - } - - let urlData = generateSitemap(pageUrls, finalSiteUrl.href, opts); - - let serializedUrls: SitemapItemLoose[]; - - if (serialize) { - serializedUrls = []; - try { - for (const item of urlData) { - const serialized = await Promise.resolve(serialize(item)); - serializedUrls.push(serialized); - } - urlData = serializedUrls; - } catch (err) { - logger.error(`Error serializing pages\n${(err as any).toString()}`); - return; - } - } - - await simpleSitemapAndIndex({ - hostname: finalSiteUrl.href, - destinationDir: fileURLToPath(dir), - sourceData: urlData, - limit: entryLimit, - gzip: false, - }); - logger.success(`\`${OUTFILE}\` is created.`); - - if (createLinkInHead) { - const sitemapHref = path.posix.join(config.base, OUTFILE); - const headHTML = ``; - await processPages(pages, dir, headHTML, config.build.format); - logger.success('Sitemap links are created in section of generated pages.'); - } - } catch (err) { - if (err instanceof ZodError) { - logger.warn(formatConfigErrorMessage(err)); - } else { - throw err; - } - } - }, - }, - }; + let config: AstroConfig; + return { + name: PKG_NAME, + + hooks: { + 'astro:config:done': async ({ config: cfg }) => { + config = cfg; + }, + + 'astro:build:done': async ({ dir, pages }) => { + const logger = new Logger(PKG_NAME); + + try { + const opts = validateOptions(config.site, options); + + const { filter, customPages, canonicalURL, serialize, entryLimit } = opts; + + let finalSiteUrl: URL; + if (canonicalURL) { + finalSiteUrl = new URL(canonicalURL); + if (!finalSiteUrl.pathname.endsWith('/')) { + finalSiteUrl.pathname += '/'; // normalizes the final url since it's provided by user + } + } else { + // `validateOptions` forces to provide `canonicalURL` or `config.site` at least. + // So step to check on empty values of `canonicalURL` and `config.site` is dropped. + finalSiteUrl = new URL(config.base, config.site); + } + + let pageUrls = pages.map((p) => { + const path = finalSiteUrl.pathname + p.pathname; + return new URL(path, finalSiteUrl).href; + }); + + try { + if (filter) { + pageUrls = pageUrls.filter(filter); + } + } catch (err) { + logger.error(`Error filtering pages\n${(err as any).toString()}`); + return; + } + + if (customPages) { + pageUrls = [...pageUrls, ...customPages]; + } + + if (pageUrls.length === 0) { + logger.warn(`No data for sitemap.\n\`${OUTFILE}\` is not created.`); + return; + } + + let urlData = generateSitemap(pageUrls, finalSiteUrl.href, opts); + + if (serialize) { + try { + const serializedUrls: SitemapItemLoose[] = []; + for (const item of urlData) { + const serialized = await Promise.resolve(serialize(item)); + serializedUrls.push(serialized); + } + urlData = serializedUrls; + } catch (err) { + logger.error(`Error serializing pages\n${(err as any).toString()}`); + return; + } + } + + await simpleSitemapAndIndex({ + hostname: finalSiteUrl.href, + destinationDir: fileURLToPath(dir), + sourceData: urlData, + limit: entryLimit, + gzip: false, + }); + logger.success(`\`${OUTFILE}\` is created.`); + } catch (err) { + if (err instanceof ZodError) { + logger.warn(formatConfigErrorMessage(err)); + } else { + throw err; + } + } + }, + }, + }; }; export default createPlugin; diff --git a/packages/integrations/sitemap/src/process-pages.ts b/packages/integrations/sitemap/src/process-pages.ts deleted file mode 100644 index c6a46218c889..000000000000 --- a/packages/integrations/sitemap/src/process-pages.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { promises as fs } from 'node:fs'; -import { parse, HTMLElement } from 'node-html-parser'; - -const addTailSlash = (s: string) => (s.endsWith('/') ? s : s + '/'); -const removeHeadingSlash = (s: string) => s.replace(/^\/+/, ''); -const removeTrailingSlash = (s: string) => s.replace(/\/+$/, ''); - -const getFileDir = (pathname: string) => { - const name = addTailSlash(pathname); - const file = name === '404/' ? '404.html' : `${name}index.html`; - return removeHeadingSlash(file); -}; - -const getFileFile = (pathname: string) => (pathname ? `${removeTrailingSlash(pathname)}.html` : 'index.html'); - -export async function processPages(pages: { pathname: string }[], dir: URL, headHTML: string, buildFormat: string) { - if (pages.length === 0) { - return; - } - if (buildFormat !== 'directory' && buildFormat !== 'file') { - throw new Error(`Unsupported build.format: '${buildFormat}' in your astro.config`); - } - - for (const page of pages) { - const fileUrl = new URL(buildFormat === 'directory' ? getFileDir(page.pathname) : getFileFile(page.pathname), dir); - - const html = await fs.readFile(fileUrl, 'utf-8'); - const root = parse(html); - let head = root.querySelector('head'); - if (!head) { - head = new HTMLElement('head', {}, '', root); - root.appendChild(head); - console.warn(`No found in \`${fileUrl.pathname}\`. will be created.`); - } - head.innerHTML = head.innerHTML + headHTML; - const inlined = root.toString(); - await fs.writeFile(fileUrl, inlined, 'utf-8'); - } -} diff --git a/packages/integrations/sitemap/src/schema.ts b/packages/integrations/sitemap/src/schema.ts index 6e58218c751e..723f9ac58494 100644 --- a/packages/integrations/sitemap/src/schema.ts +++ b/packages/integrations/sitemap/src/schema.ts @@ -1,52 +1,47 @@ import { z } from 'zod'; -import { isValidUrl } from './utils/is-valid-url'; import { changefreqValues } from './constants'; - -const urlSchema = () => - z - .string() - .min(1) - .refine((val) => !val || isValidUrl(val), 'Not valid url'); +import { SITEMAP_CONFIG_DEFAULTS } from './config-defaults'; 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(); - -export const SitemapOptionsSchema = z.object({ - filter: fnSchema(), - - customPages: urlSchema().array().optional(), - - canonicalURL: urlSchema().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(({ locales, defaultLocale }) => locales[defaultLocale], { - message: '`defaultLocale` must exists in `locales` keys', - }) - .optional(), - - createLinkInHead: z.boolean().optional(), - - entryLimit: z.number().nonnegative().optional(), - - serialize: fnSchema(), - - changefreq: z.enum(changefreqValues).optional(), - lastmod: z.date().optional(), - priority: z.number().min(0).max(1).optional(), -}); +const fnSchema = () => + z + .any() + .refine((val) => !val || isFunction(val), { message: 'Not a function' }) + .optional(); + +export const SitemapOptionsSchema = z + .object({ + filter: fnSchema(), + 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(), + + entryLimit: z.number().nonnegative().default(SITEMAP_CONFIG_DEFAULTS.entryLimit), + serialize: fnSchema(), + + changefreq: z.enum(changefreqValues).optional(), + lastmod: z.date().optional(), + priority: z.number().min(0).max(1).optional(), + }) + .strict() + .default(SITEMAP_CONFIG_DEFAULTS); diff --git a/packages/integrations/sitemap/src/utils/is-object-empty.ts b/packages/integrations/sitemap/src/utils/is-object-empty.ts index 2dbc0cfe9378..0d61810695a1 100644 --- a/packages/integrations/sitemap/src/utils/is-object-empty.ts +++ b/packages/integrations/sitemap/src/utils/is-object-empty.ts @@ -1,10 +1,10 @@ // @internal export const isObjectEmpty = (o: any) => { - if (!o) { - return true; - } - if (Array.isArray(o)) { - return o.length === 0; - } - return Object.keys(o).length === 0 && Object.getPrototypeOf(o) === Object.prototype; + if (!o) { + return true; + } + if (Array.isArray(o)) { + return o.length === 0; + } + return Object.keys(o).length === 0 && Object.getPrototypeOf(o) === Object.prototype; }; diff --git a/packages/integrations/sitemap/src/utils/is-valid-url.ts b/packages/integrations/sitemap/src/utils/is-valid-url.ts index 4bead70fdf92..b140623b090f 100644 --- a/packages/integrations/sitemap/src/utils/is-valid-url.ts +++ b/packages/integrations/sitemap/src/utils/is-valid-url.ts @@ -1,13 +1,13 @@ // @internal export const isValidUrl = (s: any) => { - if (typeof s !== 'string' || !s) { - return false; - } - try { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const dummy = new URL(s); - return true; - } catch { - return false; - } + if (typeof s !== 'string' || !s) { + return false; + } + try { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const dummy = new URL(s); + return true; + } catch { + return false; + } }; diff --git a/packages/integrations/sitemap/src/utils/logger.ts b/packages/integrations/sitemap/src/utils/logger.ts index ff6276a2ed91..203baeaa7a57 100644 --- a/packages/integrations/sitemap/src/utils/logger.ts +++ b/packages/integrations/sitemap/src/utils/logger.ts @@ -1,46 +1,46 @@ // @internal export interface ILogger { - info(msg: string): void; - success(msg: string): void; - warn(msg: string): void; - error(msg: string): void; + info(msg: string): void; + success(msg: string): void; + warn(msg: string): void; + error(msg: string): void; } // @internal export class Logger implements ILogger { - private colors = { - reset: '\x1b[0m', - fg: { - red: '\x1b[31m', - green: '\x1b[32m', - yellow: '\x1b[33m', - }, - } as const; - - private packageName: string; - - constructor(packageName: string) { - this.packageName = packageName; - } - - private log(msg: string, prefix: string = '') { - // eslint-disable-next-line no-console - console.log(`%s${this.packageName}:%s ${msg}\n`, prefix, prefix ? this.colors.reset : ''); - } - - info(msg: string) { - this.log(msg); - } - - success(msg: string) { - this.log(msg, this.colors.fg.green); - } - - warn(msg: string) { - this.log(`Skipped!\n${msg}`, this.colors.fg.yellow); - } - - error(msg: string) { - this.log(`Failed!\n${msg}`, this.colors.fg.red); - } + private colors = { + reset: '\x1b[0m', + fg: { + red: '\x1b[31m', + green: '\x1b[32m', + yellow: '\x1b[33m', + }, + } as const; + + private packageName: string; + + constructor(packageName: string) { + this.packageName = packageName; + } + + private log(msg: string, prefix: string = '') { + // eslint-disable-next-line no-console + console.log(`%s${this.packageName}:%s ${msg}\n`, prefix, prefix ? this.colors.reset : ''); + } + + info(msg: string) { + this.log(msg); + } + + success(msg: string) { + this.log(msg, this.colors.fg.green); + } + + warn(msg: string) { + this.log(`Skipped!\n${msg}`, this.colors.fg.yellow); + } + + error(msg: string) { + this.log(`Failed!\n${msg}`, this.colors.fg.red); + } } diff --git a/packages/integrations/sitemap/src/utils/parse-url.ts b/packages/integrations/sitemap/src/utils/parse-url.ts index 7d948923a1fb..f9189cf7d60d 100644 --- a/packages/integrations/sitemap/src/utils/parse-url.ts +++ b/packages/integrations/sitemap/src/utils/parse-url.ts @@ -1,28 +1,39 @@ -export const parseUrl = (url: string, defaultLocale: string, localeCodes: string[], base: string) => { - if (!url || !defaultLocale || localeCodes.length === 0 || localeCodes.some((key) => !key) || !base) { - throw new Error('parseUrl: some parameters are empty'); - } - if (url.indexOf(base) !== 0) { - return undefined; - } - let s = url.replace(base, ''); - if (!s || s === '/') { - return { locale: defaultLocale, path: '/' }; - } - if (!s.startsWith('/')) { - s = '/' + s; - } - const a = s.split('/'); - const locale = a[1]; - if (localeCodes.some((key) => key === locale)) { - let path = a.slice(2).join('/'); - if (path === '//') { - path = '/'; - } - if (path !== '/' && !path.startsWith('/')) { - path = '/' + path; - } - return { locale, path }; - } - return { locale: defaultLocale, path: s }; +export const parseUrl = ( + url: string, + defaultLocale: string, + localeCodes: string[], + base: string +) => { + if ( + !url || + !defaultLocale || + localeCodes.length === 0 || + localeCodes.some((key) => !key) || + !base + ) { + throw new Error('parseUrl: some parameters are empty'); + } + if (url.indexOf(base) !== 0) { + return undefined; + } + let s = url.replace(base, ''); + if (!s || s === '/') { + return { locale: defaultLocale, path: '/' }; + } + if (!s.startsWith('/')) { + s = '/' + s; + } + const a = s.split('/'); + const locale = a[1]; + if (localeCodes.some((key) => key === locale)) { + let path = a.slice(2).join('/'); + if (path === '//') { + path = '/'; + } + if (path !== '/' && !path.startsWith('/')) { + path = '/' + path; + } + return { locale, path }; + } + return { locale: defaultLocale, path: s }; }; diff --git a/packages/integrations/sitemap/src/validate-options.ts b/packages/integrations/sitemap/src/validate-options.ts new file mode 100644 index 000000000000..f89582d82747 --- /dev/null +++ b/packages/integrations/sitemap/src/validate-options.ts @@ -0,0 +1,22 @@ +import { z } from 'zod'; +import type { SitemapOptions } from './index'; +import { SitemapOptionsSchema } from './schema'; + +// @internal +export const validateOptions = (site: string | undefined, opts: SitemapOptions) => { + const result = SitemapOptionsSchema.parse(opts); + + z.object({ + site: z.string().optional(), // Astro takes care of `site`: how to validate, transform and refine + canonicalURL: z.string().optional(), // `canonicalURL` is already validated in prev step + }) + .refine(({ site, canonicalURL }) => site || canonicalURL, { + message: 'Required `site` astro.config option or `canonicalURL` integration option', + }) + .parse({ + site, + canonicalURL: result.canonicalURL, + }); + + return result; +}; diff --git a/packages/integrations/sitemap/src/validate-opts.ts b/packages/integrations/sitemap/src/validate-opts.ts deleted file mode 100644 index 2a9bfe66770c..000000000000 --- a/packages/integrations/sitemap/src/validate-opts.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { z } from 'zod'; -import type { SitemapOptions } from './index'; -import { SitemapOptionsSchema } from './schema'; - -// @internal -export const validateOpts = (site: string | undefined, opts: SitemapOptions) => { - const schema = SitemapOptionsSchema.extend({ - site: z.string().optional(), - }) - .strict() - .refine(({ site, canonicalURL }) => site || canonicalURL, { - message: 'Required `site` astro.config option or `canonicalURL` integration option', - }); - - schema.parse({ site: site || '', ...(opts || {}) }); -}; diff --git a/packages/integrations/sitemap/src/with-options.ts b/packages/integrations/sitemap/src/with-options.ts deleted file mode 100644 index 6e0982b7b1e4..000000000000 --- a/packages/integrations/sitemap/src/with-options.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { isObjectEmpty } from './utils/is-object-empty'; -import type { SitemapOptions } from './index'; - -const defaultOptions: Readonly = { - createLinkInHead: true, - entryLimit: 45000, -}; - -// @internal -export const withOptions = (pluginOptions: SitemapOptions) => { - if (isObjectEmpty(pluginOptions)) { - return defaultOptions; - } - const options: SitemapOptions = { - ...pluginOptions, - createLinkInHead: pluginOptions?.createLinkInHead ?? defaultOptions.createLinkInHead, - entryLimit: pluginOptions?.entryLimit || defaultOptions.entryLimit, - }; - return options; -}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5c4fd6c80c2..d8538418d5be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1800,11 +1800,9 @@ importers: specifiers: astro: workspace:* astro-scripts: workspace:* - node-html-parser: ^5.3.3 sitemap: ^7.1.1 zod: ^3.17.3 dependencies: - node-html-parser: 5.3.3 sitemap: 7.1.1 zod: 3.17.3 devDependencies: @@ -8075,16 +8073,6 @@ packages: engines: {node: '>=8'} dev: true - /css-select/4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 4.3.1 - domutils: 2.8.0 - nth-check: 2.1.1 - dev: false - /css-select/5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} dependencies: @@ -8101,6 +8089,7 @@ packages: /css-what/6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} + dev: true /cssesc/3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -9612,6 +9601,7 @@ packages: /he/1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + dev: true /hosted-git-info/2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -11123,13 +11113,6 @@ packages: hasBin: true dev: false - /node-html-parser/5.3.3: - resolution: {integrity: sha512-ncg1033CaX9UexbyA7e1N0aAoAYRDiV8jkTvzEnfd1GDvzFdrsXLzR4p4ik8mwLgnaKP/jyUFWDy9q3jvRT2Jw==} - dependencies: - css-select: 4.3.0 - he: 1.2.0 - dev: false - /node-pre-gyp/0.13.0: resolution: {integrity: sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==} deprecated: 'Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future' From b61e1f9ba3182301ea713f393dd7dfc56504f7f5 Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Thu, 16 Jun 2022 01:34:05 +0300 Subject: [PATCH 6/8] docs: updated changeset text --- .changeset/popular-cherries-float.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/popular-cherries-float.md b/.changeset/popular-cherries-float.md index 4c04c4e5d958..f04ab3f3ce54 100644 --- a/.changeset/popular-cherries-float.md +++ b/.changeset/popular-cherries-float.md @@ -8,7 +8,6 @@ - Ability to add sitemap specific attributes such as `lastmod` etc. - Final output customization via JS function. - Localization support. -- Automatically creates a link to sitemap in `` section of generated pages. - Reliability: all config options are validated. ## Important changes From 036bac730d235b96b218e4d8c97527fa922b044f Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Thu, 16 Jun 2022 09:46:44 +0300 Subject: [PATCH 7/8] refactor: 'zod' function() instead of self made refine() --- packages/integrations/sitemap/src/schema.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/integrations/sitemap/src/schema.ts b/packages/integrations/sitemap/src/schema.ts index 723f9ac58494..60c418e7496a 100644 --- a/packages/integrations/sitemap/src/schema.ts +++ b/packages/integrations/sitemap/src/schema.ts @@ -4,17 +4,9 @@ import { SITEMAP_CONFIG_DEFAULTS } from './config-defaults'; 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(); - export const SitemapOptionsSchema = z .object({ - filter: fnSchema(), + filter: z.function().optional(), customPages: z.string().url().array().optional(), canonicalURL: z.string().url().optional(), @@ -32,12 +24,12 @@ export const SitemapOptionsSchema = z ), }) .refine((val) => !val || val.locales[val.defaultLocale], { - message: '`defaultLocale` must exists in `locales` keys', + 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().optional(), changefreq: z.enum(changefreqValues).optional(), lastmod: z.date().optional(), From 5e2356b28241a181ac5a07bc3701ce775a69c5f3 Mon Sep 17 00:00:00 2001 From: Alex Tim Date: Thu, 16 Jun 2022 10:17:51 +0300 Subject: [PATCH 8/8] Revert "refactor: 'zod' function() instead of self made refine()" This reverts commit 036bac730d235b96b218e4d8c97527fa922b044f. undo function() --- packages/integrations/sitemap/src/schema.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/integrations/sitemap/src/schema.ts b/packages/integrations/sitemap/src/schema.ts index 60c418e7496a..723f9ac58494 100644 --- a/packages/integrations/sitemap/src/schema.ts +++ b/packages/integrations/sitemap/src/schema.ts @@ -4,9 +4,17 @@ import { SITEMAP_CONFIG_DEFAULTS } from './config-defaults'; 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(); + export const SitemapOptionsSchema = z .object({ - filter: z.function().optional(), + filter: fnSchema(), customPages: z.string().url().array().optional(), canonicalURL: z.string().url().optional(), @@ -24,12 +32,12 @@ export const SitemapOptionsSchema = z ), }) .refine((val) => !val || val.locales[val.defaultLocale], { - message: '`defaultLocale` must exist in `locales` keys', + message: '`defaultLocale` must exists in `locales` keys', }) .optional(), - entryLimit: z.number().nonnegative().optional().default(SITEMAP_CONFIG_DEFAULTS.entryLimit), - serialize: z.function().optional(), + entryLimit: z.number().nonnegative().default(SITEMAP_CONFIG_DEFAULTS.entryLimit), + serialize: fnSchema(), changefreq: z.enum(changefreqValues).optional(), lastmod: z.date().optional(),