/
githubmirror
/
docusaurus
Обзор
Документация
Войти
/
githubmirror
/
docusaurus
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
website/src/plugins/changelog/index.ts
118 строк
4 KB
Sébastien Lorber
chore(website): split changelog per version + adjust changelog plugin implementation (#11287)
24 июн 2025, 18:05
Не верифицирован
24 июн 2025, 18:05
e82cd48
Код
Авторство
О чём код?
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import path from 'path'; import fs from 'fs-extra'; import pluginContentBlog from '@docusaurus/plugin-content-blog'; import { aliasedSitePath, docuHash, normalizeUrl, safeGlobby, } from '@docusaurus/utils'; import {createBlogFiles, toChangelogEntries} from './utils'; export {validateOptions} from '@docusaurus/plugin-content-blog'; const MonorepoRoot = path.resolve(path.join(__dirname, '../../../..')); const ChangelogFilePattern = 'CHANGELOG(-v[0-9]*)?.md'; async function getChangelogFiles() { const files = await safeGlobby([ChangelogFilePattern], { cwd: MonorepoRoot, }); // As of today, there are 2 changelog files // and this is only going to increase if (files.length < 2) { throw new Error( "Looks like the changelog plugin didn't detect Docusaurus changelog files", ); } // Note: the returned file order doesn't matter. return files; } function readChangelogFile(filename: string) { return fs.readFile(path.join(MonorepoRoot, filename), 'utf-8'); } async function loadChangelogEntries(changelogFiles: string[]) { const filesContent = await Promise.all(changelogFiles.map(readChangelogFile)); return toChangelogEntries(filesContent); } const ChangelogPlugin: typeof pluginContentBlog = async function ChangelogPlugin(context, options) { const generateDir = path.join(context.siteDir, 'changelog/source'); const blogPlugin = await pluginContentBlog(context, { ...options, path: generateDir, id: 'changelog', blogListComponent: '@theme/ChangelogList', blogPostComponent: '@theme/ChangelogPage', }); const changelogFiles = await getChangelogFiles(); return { ...blogPlugin, name: 'changelog-plugin', async loadContent() { const changelogEntries = await loadChangelogEntries(changelogFiles); // We have to create intermediate files here // Unfortunately Docusaurus doesn't have yet any concept of virtual file await createBlogFiles(generateDir, changelogEntries); // Read the files we actually just wrote const content = (await blogPlugin.loadContent?.())!; content.blogPosts.forEach((post, index) => { const pageIndex = Math.floor( index / (options.postsPerPage as number), ); // @ts-expect-error: TODO Docusaurus use interface declaration merging post.metadata.listPageLink = normalizeUrl([ context.baseUrl, options.routeBasePath, pageIndex === 0 ? '/' : `/page/${pageIndex + 1}`, ]); }); return content; }, configureWebpack(...args) { const config = blogPlugin.configureWebpack?.(...args); const pluginDataDirRoot = path.join( context.generatedFilesDir, 'changelog-plugin', 'default', ); // Redirect the metadata path to our folder // @ts-expect-error: unsafe but works const mdxLoader = config.module.rules[0].use[0]; mdxLoader.options.metadataPath = (mdxPath: string) => { // Note that metadataPath must be the same/in-sync as // the path from createData for each MDX. const aliasedPath = aliasedSitePath(mdxPath, context.siteDir); return path.join(pluginDataDirRoot, `${docuHash(aliasedPath)}.json`); }; return config; }, getThemePath() { return './theme'; }, getPathsToWatch() { return [path.join(MonorepoRoot, ChangelogFilePattern)]; }, }; }; export default ChangelogPlugin;