Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/generators/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -27,6 +28,7 @@ export const publicGenerators = {
'api-links': apiLinks,
'orama-db': oramaDb,
'llms-txt': llmsTxt,
sitemap,
web,
};

Expand Down
81 changes: 81 additions & 0 deletions src/generators/sitemap/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { readFile, writeFile } from 'node:fs/promises';
import { join } from 'node:path';

import dedent from 'dedent';

import { BASE_URL } from '../../constants.mjs';

/**
* This generator generates a sitemap.xml file for search engine optimization
*
* @typedef {Array<ApiDocMetadataEntry>} Input
*
* @type {GeneratorMetadata<Input, string>}
*/
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<GeneratorOptions>} options
* @returns {Promise<string>}
*/
async generate(entries, { output }) {
const lastmod = new Date().toISOString().split('T')[0];

const apiPages = entries
.filter(entry => entry.heading.depth === 1)
.map(entry => {
Comment thread
araujogui marked this conversation as resolved.
Outdated
const path = entry.api_doc_source.replace(/^doc\//, '/docs/latest/');
Comment thread
araujogui marked this conversation as resolved.
Outdated
const url = new URL(path, BASE_URL).href;
Comment thread
araujogui marked this conversation as resolved.
Outdated

return {
Comment thread
araujogui marked this conversation as resolved.
Outdated
loc: url,
lastmod,
changefreq: 'weekly',
priority: '0.8',
};
});

apiPages.push({
loc: new URL('/docs/latest/api/', BASE_URL).href,
Comment thread
araujogui marked this conversation as resolved.
Outdated
lastmod,
changefreq: 'daily',
priority: '1.0',
});

const template = await readFile(
join(import.meta.dirname, 'template.xml'),
'utf-8'
);

const urlset = apiPages
.map(
page => dedent`
<url>
Copy link
Copy Markdown
Member

@ovflowd ovflowd Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use template files for this and then do simple key->value substitution. Or use proper rss/feed libraries OR xml libraries.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or use proper rss/feed libraries OR xml libraries.

You can probably use hast (but I'm also fine with it this way), seeing as the majority of it is a template

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use hast, we are probably going to need https://github.com/syntax-tree/hast-util-to-xast too

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with whatever that uses the least amount of dependencies. We can also just use yet another template file, we can also simply use another dependency, like the xast one, or rss/feeds or whatever.

Comment thread
araujogui marked this conversation as resolved.
Outdated
<loc>${page.loc}</loc>
<lastmod>${page.lastmod}</lastmod>
<changefreq>${page.changefreq}</changefreq>
<priority>${page.priority}</priority>
</url>
`
)
.join('\n');

const sitemap = template.replace('__URLSET__', urlset);

if (output) {
Comment thread
avivkeller marked this conversation as resolved.
Outdated
await writeFile(join(output, 'sitemap.xml'), sitemap, 'utf-8');
}

return sitemap;
},
};
4 changes: 4 additions & 0 deletions src/generators/sitemap/template.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
__URLSET__
</urlset>
Loading