From 8d07613902b95b762364359146bf6af72e8ab42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Sun, 14 Dec 2025 22:08:07 -0300 Subject: [PATCH 1/6] feat: create sitemap generator --- src/generators/index.mjs | 2 + src/generators/sitemap/index.mjs | 75 ++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/generators/sitemap/index.mjs diff --git a/src/generators/index.mjs b/src/generators/index.mjs index 09a4c1a0..24294f92 100644 --- a/src/generators/index.mjs +++ b/src/generators/index.mjs @@ -14,6 +14,7 @@ import llmsTxt from './llms-txt/index.mjs'; import manPage from './man-page/index.mjs'; import metadata from './metadata/index.mjs'; import oramaDb from './orama-db/index.mjs'; +import sitemap from './sitemap/index.mjs'; import web from './web/index.mjs'; export const publicGenerators = { @@ -27,6 +28,7 @@ export const publicGenerators = { 'api-links': apiLinks, 'orama-db': oramaDb, 'llms-txt': llmsTxt, + sitemap, web, }; diff --git a/src/generators/sitemap/index.mjs b/src/generators/sitemap/index.mjs new file mode 100644 index 00000000..9ad00d69 --- /dev/null +++ b/src/generators/sitemap/index.mjs @@ -0,0 +1,75 @@ +import { writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; + +import { BASE_URL } from '../../constants.mjs'; + +/** + * This generator generates a sitemap.xml file for search engine optimization + * + * @typedef {Array} Input + * + * @type {GeneratorMetadata} + */ +export default { + name: 'sitemap', + + version: '1.0.0', + + description: 'Generates a sitemap.xml file for search engine optimization', + + dependsOn: 'metadata', + + /** + * Generates a sitemap.xml file + * + * @param {Input} entries + * @param {Partial} options + * @returns {Promise} + */ + async generate(entries, { output }) { + const apiPages = entries + .filter(entry => entry.heading.depth === 1) + .map(entry => { + const path = entry.api_doc_source.replace(/^doc\//, '/docs/latest/'); + const url = new URL(path, BASE_URL).href; + + return { + loc: url, + lastmod: new Date().toISOString().split('T')[0], + changefreq: 'weekly', + priority: '0.8', + }; + }); + + const mainPages = [ + { + loc: new URL('/docs/latest/api/', BASE_URL).href, + lastmod: new Date().toISOString().split('T')[0], + changefreq: 'daily', + priority: '1.0', + }, + ]; + + const allPages = [...mainPages, ...apiPages]; + + const sitemap = ` + +${allPages + .map( + page => ` + ${page.loc} + ${page.lastmod} + ${page.changefreq} + ${page.priority} + ` + ) + .join('\n')} +`; + + if (output) { + await writeFile(join(output, 'sitemap.xml'), sitemap, 'utf-8'); + } + + return sitemap; + }, +}; From 18c93577cc2426638f84616650e4ef048ec23fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Thu, 25 Dec 2025 15:42:00 -0300 Subject: [PATCH 2/6] refactor: review --- src/generators/sitemap/index.mjs | 42 ++++++++++++++++++----------- src/generators/sitemap/template.xml | 4 +++ 2 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 src/generators/sitemap/template.xml diff --git a/src/generators/sitemap/index.mjs b/src/generators/sitemap/index.mjs index 9ad00d69..1ecf48e2 100644 --- a/src/generators/sitemap/index.mjs +++ b/src/generators/sitemap/index.mjs @@ -1,6 +1,8 @@ -import { writeFile } from 'node:fs/promises'; +import { readFile, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; +import dedent from 'dedent'; + import { BASE_URL } from '../../constants.mjs'; /** @@ -27,6 +29,8 @@ export default { * @returns {Promise} */ async generate(entries, { output }) { + const lastmod = new Date().toISOString().split('T')[0]; + const apiPages = entries .filter(entry => entry.heading.depth === 1) .map(entry => { @@ -35,7 +39,7 @@ export default { return { loc: url, - lastmod: new Date().toISOString().split('T')[0], + lastmod, changefreq: 'weekly', priority: '0.8', }; @@ -44,7 +48,7 @@ export default { const mainPages = [ { loc: new URL('/docs/latest/api/', BASE_URL).href, - lastmod: new Date().toISOString().split('T')[0], + lastmod, changefreq: 'daily', priority: '1.0', }, @@ -52,19 +56,25 @@ export default { const allPages = [...mainPages, ...apiPages]; - const sitemap = ` - -${allPages - .map( - page => ` - ${page.loc} - ${page.lastmod} - ${page.changefreq} - ${page.priority} - ` - ) - .join('\n')} -`; + const template = await readFile( + join(import.meta.dirname, 'template.xml'), + 'utf-8' + ); + + const urlset = allPages + .map( + page => dedent` + + ${page.loc} + ${page.lastmod} + ${page.changefreq} + ${page.priority} + + ` + ) + .join('\n'); + + const sitemap = template.replace('__URLSET__', urlset); if (output) { await writeFile(join(output, 'sitemap.xml'), sitemap, 'utf-8'); diff --git a/src/generators/sitemap/template.xml b/src/generators/sitemap/template.xml new file mode 100644 index 00000000..84771792 --- /dev/null +++ b/src/generators/sitemap/template.xml @@ -0,0 +1,4 @@ + + +__URLSET__ + From 914652cbc4efdd1e4531dd1f95c0a0461ca031bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Thu, 25 Dec 2025 15:53:43 -0300 Subject: [PATCH 3/6] refactor: review --- src/generators/sitemap/index.mjs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/generators/sitemap/index.mjs b/src/generators/sitemap/index.mjs index 1ecf48e2..a6b9d590 100644 --- a/src/generators/sitemap/index.mjs +++ b/src/generators/sitemap/index.mjs @@ -45,23 +45,19 @@ export default { }; }); - const mainPages = [ - { - loc: new URL('/docs/latest/api/', BASE_URL).href, - lastmod, - changefreq: 'daily', - priority: '1.0', - }, - ]; - - const allPages = [...mainPages, ...apiPages]; + apiPages.push({ + loc: new URL('/docs/latest/api/', BASE_URL).href, + lastmod, + changefreq: 'daily', + priority: '1.0', + }); const template = await readFile( join(import.meta.dirname, 'template.xml'), 'utf-8' ); - const urlset = allPages + const urlset = apiPages .map( page => dedent` From 6fa782a9d8475f17e2df281491ded7b95c49716a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Fri, 26 Dec 2025 15:25:22 -0300 Subject: [PATCH 4/6] refactor: review --- npm-shrinkwrap.json | 18 +++++------ .../llms-txt/utils/buildApiDocLink.mjs | 5 ++- src/generators/sitemap/index.mjs | 13 ++------ src/generators/sitemap/types.d.ts | 13 ++++++++ .../sitemap/utils/buildApiDocUrl.mjs | 14 ++++++++ src/utils/__tests__/url.test.mjs | 32 +++++++++++++++++++ src/utils/url.mjs | 19 +++++++++++ 7 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 src/generators/sitemap/types.d.ts create mode 100644 src/generators/sitemap/utils/buildApiDocUrl.mjs create mode 100644 src/utils/__tests__/url.test.mjs create mode 100644 src/utils/url.mjs diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index aa327fb6..415bf6dc 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1068,7 +1068,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "license": "MIT", - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -1169,7 +1168,6 @@ "resolved": "https://registry.npmjs.org/@orama/cuid2/-/cuid2-2.2.3.tgz", "integrity": "sha512-Lcak3chblMejdlSHgYU2lS2cdOhDpU6vkfIJH4m+YKvqQyLqs1bB8+w6NT1MG5bO12NUK2GFc34Mn2xshMIQ1g==", "license": "MIT", - "peer": true, "dependencies": { "@noble/hashes": "^1.1.5" } @@ -1187,8 +1185,7 @@ "version": "0.0.5", "resolved": "https://registry.npmjs.org/@orama/oramacore-events-parser/-/oramacore-events-parser-0.0.5.tgz", "integrity": "sha512-yAuSwog+HQBAXgZ60TNKEwu04y81/09mpbYBCmz1RCxnr4ObNY2JnPZI7HmALbjAhLJ8t5p+wc2JHRK93ubO4w==", - "license": "AGPL-3.0", - "peer": true + "license": "AGPL-3.0" }, "node_modules/@orama/stopwords": { "version": "3.1.16", @@ -3495,6 +3492,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4030,8 +4028,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", @@ -4231,6 +4228,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -7133,6 +7131,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -7182,6 +7181,7 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-11.0.0-beta.0.tgz", "integrity": "sha512-IcODoASASYwJ9kxz7+MJeiJhvLriwSb4y4mHIyxdgaRZp6kPUud7xytrk/6GZw8U3y6EFJaRb5wi9SrEK+8+lg==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -7681,8 +7681,7 @@ "version": "0.26.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/semver": { "version": "7.7.3", @@ -8271,6 +8270,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -8636,6 +8636,7 @@ "integrity": "sha512-VUyWiTNQD7itdiMuJy+EuLEErLj3uwX/EpHQF8EOf33Dq3Ju6VW1GXm+swk6+1h7a49uv9fKZ+dft9jU7esdLA==", "dev": true, "hasInstallScript": true, + "peer": true, "dependencies": { "napi-postinstall": "^0.2.4" }, @@ -9062,7 +9063,6 @@ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", "license": "ISC", - "peer": true, "peerDependencies": { "zod": "^3.24.1" } diff --git a/src/generators/llms-txt/utils/buildApiDocLink.mjs b/src/generators/llms-txt/utils/buildApiDocLink.mjs index 1177e6be..d7714c6d 100644 --- a/src/generators/llms-txt/utils/buildApiDocLink.mjs +++ b/src/generators/llms-txt/utils/buildApiDocLink.mjs @@ -1,5 +1,5 @@ -import { BASE_URL } from '../../../constants.mjs'; import { transformNodeToString } from '../../../utils/unist.mjs'; +import { buildApiDocURL } from '../../../utils/url.mjs'; /** * Retrieves the description of a given API doc entry. It first checks whether @@ -38,8 +38,7 @@ export const getEntryDescription = entry => { export const buildApiDocLink = entry => { const title = entry.heading.data.name; - const path = entry.api_doc_source.replace(/^doc\//, '/docs/latest/'); - const url = new URL(path, BASE_URL); + const url = buildApiDocURL(entry); const link = `[${title}](${url})`; diff --git a/src/generators/sitemap/index.mjs b/src/generators/sitemap/index.mjs index a6b9d590..f8c03f77 100644 --- a/src/generators/sitemap/index.mjs +++ b/src/generators/sitemap/index.mjs @@ -4,6 +4,7 @@ import { join } from 'node:path'; import dedent from 'dedent'; import { BASE_URL } from '../../constants.mjs'; +import { buildApiDocUrl } from './utils/buildApiDocUrl.mjs'; /** * This generator generates a sitemap.xml file for search engine optimization @@ -33,17 +34,7 @@ export default { const apiPages = entries .filter(entry => entry.heading.depth === 1) - .map(entry => { - const path = entry.api_doc_source.replace(/^doc\//, '/docs/latest/'); - const url = new URL(path, BASE_URL).href; - - return { - loc: url, - lastmod, - changefreq: 'weekly', - priority: '0.8', - }; - }); + .map(entry => buildApiDocUrl(entry, lastmod)); apiPages.push({ loc: new URL('/docs/latest/api/', BASE_URL).href, diff --git a/src/generators/sitemap/types.d.ts b/src/generators/sitemap/types.d.ts new file mode 100644 index 00000000..33269e8f --- /dev/null +++ b/src/generators/sitemap/types.d.ts @@ -0,0 +1,13 @@ +export interface SitemapUrl { + loc: string; + lastmod?: string; + changefreq?: + | 'always' + | 'hourly' + | 'daily' + | 'weekly' + | 'monthly' + | 'yearly' + | 'never'; + priority?: string; +} diff --git a/src/generators/sitemap/utils/buildApiDocUrl.mjs b/src/generators/sitemap/utils/buildApiDocUrl.mjs new file mode 100644 index 00000000..eb0b1362 --- /dev/null +++ b/src/generators/sitemap/utils/buildApiDocUrl.mjs @@ -0,0 +1,14 @@ +import { buildApiDocURL } from '../../../utils/url.mjs'; + +/** + * Builds an API doc sitemap url. + * + * @param {ApiDocMetadataEntry} entry + * @param {string} lastmod + * @returns {import('../types').SitemapUrl} + */ +export const buildApiDocUrl = (entry, lastmod) => { + const { href } = buildApiDocURL(entry, true); + + return { loc: href, lastmod, changefreq: 'weekly', priority: '0.8' }; +}; diff --git a/src/utils/__tests__/url.test.mjs b/src/utils/__tests__/url.test.mjs new file mode 100644 index 00000000..4b43b75e --- /dev/null +++ b/src/utils/__tests__/url.test.mjs @@ -0,0 +1,32 @@ +import assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; + +import { buildApiDocURL } from '../url.mjs'; + +const BASE = 'https://nodejs.org/'; + +describe('buildApiDocURL', () => { + it('builds markdown doc URLs from doc/ sources', () => { + const entry = { api_doc_source: 'doc/api/fs.md' }; + + const result = buildApiDocURL(entry); + + assert.equal(result.href, `${BASE}docs/latest/api/fs.md`); + }); + + it('builds html doc URLs when requested', () => { + const entry = { api_doc_source: 'doc/api/path.md' }; + + const result = buildApiDocURL(entry, true); + + assert.equal(result.href, `${BASE}docs/latest/api/path.html`); + }); + + it('leaves non doc/ sources untouched', () => { + const entry = { api_doc_source: 'api/crypto.md' }; + + const result = buildApiDocURL(entry); + + assert.equal(result.href, `${BASE}api/crypto.md`); + }); +}); diff --git a/src/utils/url.mjs b/src/utils/url.mjs new file mode 100644 index 00000000..4d9cb7c5 --- /dev/null +++ b/src/utils/url.mjs @@ -0,0 +1,19 @@ +import { BASE_URL } from '../constants.mjs'; + +/** + * Builds the url of a api doc entry. + * + * @param {ApiDocMetadataEntry} entry + * @param {boolean} [useHtml] + * @returns {URL} + */ +export const buildApiDocURL = (entry, useHtml = false) => { + const path = entry.api_doc_source.replace(/^doc\//, '/docs/latest/'); + + if (useHtml) { + const htmlPath = path.replace(/\.md$/, '.html'); + return new URL(htmlPath, BASE_URL); + } + + return new URL(path, BASE_URL); +}; From 71b6c243980bc94a31fdb737db1b76b83fcaa437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Sat, 27 Dec 2025 12:05:28 -0300 Subject: [PATCH 5/6] refactor: review --- src/generators/sitemap/index.mjs | 13 +++++++++---- src/generators/sitemap/types.d.ts | 2 +- ...uildApiDocUrl.mjs => createPageSitemapEntry.mjs} | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) rename src/generators/sitemap/utils/{buildApiDocUrl.mjs => createPageSitemapEntry.mjs} (73%) diff --git a/src/generators/sitemap/index.mjs b/src/generators/sitemap/index.mjs index f8c03f77..d2f871a9 100644 --- a/src/generators/sitemap/index.mjs +++ b/src/generators/sitemap/index.mjs @@ -4,7 +4,7 @@ import { join } from 'node:path'; import dedent from 'dedent'; import { BASE_URL } from '../../constants.mjs'; -import { buildApiDocUrl } from './utils/buildApiDocUrl.mjs'; +import { createPageSitemapEntry } from './utils/createPageSitemapEntry.mjs'; /** * This generator generates a sitemap.xml file for search engine optimization @@ -34,14 +34,19 @@ export default { const apiPages = entries .filter(entry => entry.heading.depth === 1) - .map(entry => buildApiDocUrl(entry, lastmod)); + .map(entry => createPageSitemapEntry(entry, lastmod)); - apiPages.push({ + /** + * @typedef {import('./types').SitemapEntry} + */ + const mainPage = { loc: new URL('/docs/latest/api/', BASE_URL).href, lastmod, changefreq: 'daily', priority: '1.0', - }); + }; + + apiPages.push(mainPage); const template = await readFile( join(import.meta.dirname, 'template.xml'), diff --git a/src/generators/sitemap/types.d.ts b/src/generators/sitemap/types.d.ts index 33269e8f..0353c9cc 100644 --- a/src/generators/sitemap/types.d.ts +++ b/src/generators/sitemap/types.d.ts @@ -1,4 +1,4 @@ -export interface SitemapUrl { +export interface SitemapEntry { loc: string; lastmod?: string; changefreq?: diff --git a/src/generators/sitemap/utils/buildApiDocUrl.mjs b/src/generators/sitemap/utils/createPageSitemapEntry.mjs similarity index 73% rename from src/generators/sitemap/utils/buildApiDocUrl.mjs rename to src/generators/sitemap/utils/createPageSitemapEntry.mjs index eb0b1362..cbd8ff46 100644 --- a/src/generators/sitemap/utils/buildApiDocUrl.mjs +++ b/src/generators/sitemap/utils/createPageSitemapEntry.mjs @@ -5,9 +5,9 @@ import { buildApiDocURL } from '../../../utils/url.mjs'; * * @param {ApiDocMetadataEntry} entry * @param {string} lastmod - * @returns {import('../types').SitemapUrl} + * @returns {import('../types').SitemapEntry} */ -export const buildApiDocUrl = (entry, lastmod) => { +export const createPageSitemapEntry = (entry, lastmod) => { const { href } = buildApiDocURL(entry, true); return { loc: href, lastmod, changefreq: 'weekly', priority: '0.8' }; From 21ad2b971537abb50130406dabe81d431033e94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Ara=C3=BAjo?= Date: Sat, 27 Dec 2025 16:35:25 -0300 Subject: [PATCH 6/6] refactor: review --- src/generators/sitemap/entry-template.xml | 6 ++++ src/generators/sitemap/index.mjs | 38 ++++++++++++----------- src/utils/url.mjs | 5 ++- 3 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 src/generators/sitemap/entry-template.xml diff --git a/src/generators/sitemap/entry-template.xml b/src/generators/sitemap/entry-template.xml new file mode 100644 index 00000000..d646ff63 --- /dev/null +++ b/src/generators/sitemap/entry-template.xml @@ -0,0 +1,6 @@ + + __LOC__ + __LASTMOD__ + __CHANGEFREQ__ + __PRIORITY__ + diff --git a/src/generators/sitemap/index.mjs b/src/generators/sitemap/index.mjs index d2f871a9..0ed7156b 100644 --- a/src/generators/sitemap/index.mjs +++ b/src/generators/sitemap/index.mjs @@ -1,8 +1,6 @@ import { readFile, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; -import dedent from 'dedent'; - import { BASE_URL } from '../../constants.mjs'; import { createPageSitemapEntry } from './utils/createPageSitemapEntry.mjs'; @@ -30,17 +28,29 @@ export default { * @returns {Promise} */ async generate(entries, { output }) { + const template = await readFile( + join(import.meta.dirname, 'template.xml'), + 'utf-8' + ); + + const entryTemplate = await readFile( + join(import.meta.dirname, 'entry-template.xml'), + 'utf-8' + ); + const lastmod = new Date().toISOString().split('T')[0]; const apiPages = entries .filter(entry => entry.heading.depth === 1) .map(entry => createPageSitemapEntry(entry, lastmod)); + const { href: loc } = new URL('/docs/latest/api/', BASE_URL); + /** * @typedef {import('./types').SitemapEntry} */ const mainPage = { - loc: new URL('/docs/latest/api/', BASE_URL).href, + loc, lastmod, changefreq: 'daily', priority: '1.0', @@ -48,23 +58,15 @@ export default { apiPages.push(mainPage); - const template = await readFile( - join(import.meta.dirname, 'template.xml'), - 'utf-8' - ); - const urlset = apiPages - .map( - page => dedent` - - ${page.loc} - ${page.lastmod} - ${page.changefreq} - ${page.priority} - - ` + .map(page => + entryTemplate + .replace('__LOC__', page.loc) + .replace('__LASTMOD__', page.lastmod) + .replace('__CHANGEFREQ__', page.changefreq) + .replace('__PRIORITY__', page.priority) ) - .join('\n'); + .join(''); const sitemap = template.replace('__URLSET__', urlset); diff --git a/src/utils/url.mjs b/src/utils/url.mjs index 4d9cb7c5..6a03d305 100644 --- a/src/utils/url.mjs +++ b/src/utils/url.mjs @@ -11,9 +11,8 @@ export const buildApiDocURL = (entry, useHtml = false) => { const path = entry.api_doc_source.replace(/^doc\//, '/docs/latest/'); if (useHtml) { - const htmlPath = path.replace(/\.md$/, '.html'); - return new URL(htmlPath, BASE_URL); + return URL.parse(path.replace(/\.md$/, '.html'), BASE_URL); } - return new URL(path, BASE_URL); + return URL.parse(path, BASE_URL); };