mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 10:17:55 +02:00
* feat(website): new plugin to load CHANGELOG and render as blog * use CJS * move footer links * better design * fixes * correctly order posts * add authors * Add axios * Update styles * oops * oops * add expand button * back to index page link * fix styles * add feed options * fix * fix * Add fallback * fix * fixes
158 lines
4.5 KiB
JavaScript
158 lines
4.5 KiB
JavaScript
/**
|
|
* 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.
|
|
*/
|
|
/* eslint-disable import/no-extraneous-dependencies */
|
|
|
|
const path = require('path');
|
|
const fs = require('fs-extra');
|
|
const pluginContentBlog = require('@docusaurus/plugin-content-blog');
|
|
const {aliasedSitePath, docuHash, normalizeUrl} = require('@docusaurus/utils');
|
|
const syncAvatars = require('./syncAvatars');
|
|
|
|
/**
|
|
* Multiple versions may be published on the same day, causing the order to be
|
|
* the reverse. Therefore, our publish time has a "fake hour" to order them.
|
|
*/
|
|
const publishTimes = new Set();
|
|
/** @type {Record<string, {name: string, url: string, alias: string, imageURL: string}>} */
|
|
const authorsMap = {};
|
|
|
|
/**
|
|
* @param {string} section
|
|
*/
|
|
function processSection(section) {
|
|
const title = section
|
|
.match(/\n## .*/)?.[0]
|
|
.trim()
|
|
.replace('## ', '');
|
|
if (!title) {
|
|
return null;
|
|
}
|
|
const content = section
|
|
.replace(/\n## .*/, '')
|
|
.trim()
|
|
.replace('running_woman', 'running');
|
|
|
|
let authors = content.match(/## Committers: \d+.*/ms);
|
|
if (authors) {
|
|
authors = authors[0]
|
|
.match(/- .*/g)
|
|
.map(
|
|
(line) =>
|
|
line.match(
|
|
/- (?:(?<name>.*?) \()?\[@(?<alias>.*)\]\((?<url>.*?)\)\)?/,
|
|
).groups,
|
|
)
|
|
.map((author) => ({
|
|
...author,
|
|
name: author.name ?? author.alias,
|
|
imageURL: `./img/${author.alias}.png`,
|
|
}))
|
|
.sort((a, b) => a.url.localeCompare(b.url));
|
|
|
|
authors.forEach((author) => {
|
|
authorsMap[author.alias] = author;
|
|
});
|
|
}
|
|
let hour = 20;
|
|
const date = title.match(/ \((.*)\)/)[1];
|
|
while (publishTimes.has(`${date}T${hour}:00`)) {
|
|
hour -= 1;
|
|
}
|
|
publishTimes.add(`${date}T${hour}:00`);
|
|
|
|
return {
|
|
title: title.replace(/ \(.*\)/, ''),
|
|
content: `---
|
|
date: ${`${date}T${hour}:00`}${
|
|
authors
|
|
? `
|
|
authors:
|
|
${authors.map((author) => ` - '${author.alias}'`).join('\n')}`
|
|
: ''
|
|
}
|
|
---
|
|
|
|
# ${title.replace(/ \(.*\)/, '')}
|
|
|
|
<!-- truncate -->
|
|
|
|
${content.replace(/####/g, '##')}`,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {import('@docusaurus/types').LoadContext} context
|
|
* @returns {import('@docusaurus/types').Plugin}
|
|
*/
|
|
async function ChangelogPlugin(context, options) {
|
|
const generateDir = path.join(context.siteDir, 'changelog/source');
|
|
const blogPlugin = await pluginContentBlog.default(context, {
|
|
...options,
|
|
path: generateDir,
|
|
id: 'changelog',
|
|
blogListComponent: '@theme/ChangelogList',
|
|
blogPostComponent: '@theme/ChangelogPage',
|
|
});
|
|
const changelogPath = path.join(__dirname, '../../../../CHANGELOG.md');
|
|
return {
|
|
...blogPlugin,
|
|
name: 'changelog-plugin',
|
|
async loadContent() {
|
|
const fileContent = await fs.readFile(changelogPath, 'utf-8');
|
|
const sections = fileContent
|
|
.split(/(?=\n## )/ms)
|
|
.map(processSection)
|
|
.filter(Boolean);
|
|
await Promise.all(
|
|
sections.map((section) =>
|
|
fs.outputFile(
|
|
path.join(generateDir, `${section.title}.md`),
|
|
section.content,
|
|
),
|
|
),
|
|
);
|
|
await syncAvatars(authorsMap, generateDir);
|
|
const content = await blogPlugin.loadContent();
|
|
content.blogPosts.forEach((post, index) => {
|
|
const pageIndex = Math.floor(index / options.postsPerPage);
|
|
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
|
|
config.module.rules[0].use[1].options.metadataPath = (mdxPath) => {
|
|
// 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 path.join(__dirname, './theme');
|
|
},
|
|
getPathsToWatch() {
|
|
// Don't watch the generated dir
|
|
return [changelogPath];
|
|
},
|
|
};
|
|
}
|
|
|
|
ChangelogPlugin.validateOptions = pluginContentBlog.validateOptions;
|
|
|
|
module.exports = ChangelogPlugin;
|