mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-28 17:57:48 +02:00
feat(website): new plugin to load CHANGELOG and render as blog (#6414)
* 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
This commit is contained in:
parent
5c447b1ca3
commit
f6ff6474bc
24 changed files with 845 additions and 48 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -27,6 +27,7 @@ packages/stylelint-copyright/lib/
|
|||
packages/docusaurus-*/lib-next/
|
||||
|
||||
website/netlifyDeployPreview/*
|
||||
website/changelog
|
||||
!website/netlifyDeployPreview/index.html
|
||||
!website/netlifyDeployPreview/_redirects
|
||||
|
||||
|
|
60
CHANGELOG.md
60
CHANGELOG.md
|
@ -3686,7 +3686,7 @@ Failed release
|
|||
- ehsan jso ([@ehsanjso](https://github.com/ehsanjso))
|
||||
- matbub ([@hi-matbub](https://github.com/hi-matbub))
|
||||
|
||||
## 2.0.0-alpha.58
|
||||
## 2.0.0-alpha.58 (2020-06-18)
|
||||
|
||||
#### :rocket: New Feature
|
||||
|
||||
|
@ -3825,11 +3825,11 @@ Failed release
|
|||
- moonrailgun ([@moonrailgun](https://github.com/moonrailgun))
|
||||
- tetunori ([@tetunori](https://github.com/tetunori))
|
||||
|
||||
## 2.0.0-alpha.57
|
||||
## 2.0.0-alpha.57 (2020-06-18)
|
||||
|
||||
Bad release, check ## 2.0.0-alpha.58
|
||||
|
||||
## 2.0.0-alpha.56
|
||||
## 2.0.0-alpha.56 (2020-05-28)
|
||||
|
||||
#### :boom: Breaking Change
|
||||
|
||||
|
@ -3898,7 +3898,7 @@ Bad release, check ## 2.0.0-alpha.58
|
|||
- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815))
|
||||
- Sylvain Pace ([@s-pace](https://github.com/s-pace))
|
||||
|
||||
## 2.0.0-alpha.55
|
||||
## 2.0.0-alpha.55 (2020-05-19)
|
||||
|
||||
#### :boom: Breaking Change
|
||||
|
||||
|
@ -3991,7 +3991,7 @@ Bad release, check ## 2.0.0-alpha.58
|
|||
- Yamagishi Kazutoshi ([@ykzts](https://github.com/ykzts))
|
||||
- Yangshun Tay ([@yangshun](https://github.com/yangshun))
|
||||
|
||||
## 2.0.0-alpha.54
|
||||
## 2.0.0-alpha.54 (2020-04-28)
|
||||
|
||||
**HOTFIX for 2.0.0-alpha.53**.
|
||||
|
||||
|
@ -4012,7 +4012,7 @@ Bad release, check ## 2.0.0-alpha.58
|
|||
- Joe Previte ([@jsjoeio](https://github.com/jsjoeio))
|
||||
- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815))
|
||||
|
||||
## 2.0.0-alpha.53
|
||||
## 2.0.0-alpha.53 (2020-04-27)
|
||||
|
||||
**HOTFIX for 2.0.0-alpha.51**.
|
||||
|
||||
|
@ -4025,7 +4025,7 @@ Bad release, check ## 2.0.0-alpha.58
|
|||
|
||||
- Alexey Pyltsyn ([@lex111](https://github.com/lex111))
|
||||
|
||||
## 2.0.0-alpha.51
|
||||
## 2.0.0-alpha.51 (2020-04-27)
|
||||
|
||||
#### :boom: Breaking Change
|
||||
|
||||
|
@ -4593,7 +4593,7 @@ Bad release, check ## 2.0.0-alpha.58
|
|||
- Yangshun Tay ([@yangshun](https://github.com/yangshun))
|
||||
- t11s ([@TransmissionsDev](https://github.com/TransmissionsDev))
|
||||
|
||||
## 2.0.0-alpha.39
|
||||
## 2.0.0-alpha.39 (2019-12-07)
|
||||
|
||||
#### :bug: Bug Fix
|
||||
|
||||
|
@ -4613,7 +4613,7 @@ Bad release, check ## 2.0.0-alpha.58
|
|||
|
||||
- Endi ([@endiliey](https://github.com/endiliey))
|
||||
|
||||
## 2.0.0-alpha.38
|
||||
## 2.0.0-alpha.38 (2019-12-06)
|
||||
|
||||
#### :boom: Breaking Change
|
||||
|
||||
|
@ -4666,7 +4666,7 @@ For example, if you've swizzled `@theme/DocItem`. You'll have to update
|
|||
- Shivangna Kaistha ([@shivangna](https://github.com/shivangna))
|
||||
- kaichu ([@qshiwu](https://github.com/qshiwu))
|
||||
|
||||
## 2.0.0-alpha.37
|
||||
## 2.0.0-alpha.37 (2019-12-01)
|
||||
|
||||
#### :boom: Breaking Change
|
||||
|
||||
|
@ -4750,7 +4750,7 @@ For example, if you've swizzled `@theme/DocItem`. You'll have to update
|
|||
- Endi ([@endiliey](https://github.com/endiliey))
|
||||
- Wei Gao ([@wgao19](https://github.com/wgao19))
|
||||
|
||||
## 2.0.0-alpha.36
|
||||
## 2.0.0-alpha.36 (2019-11-22)
|
||||
|
||||
#### :boom: Breaking Change
|
||||
|
||||
|
@ -4796,7 +4796,7 @@ For example, if you've swizzled `@theme/DocItem`. You'll have to update
|
|||
- Endi ([@endiliey](https://github.com/endiliey))
|
||||
- Yangshun Tay ([@yangshun](https://github.com/yangshun))
|
||||
|
||||
## 2.0.0-alpha.35
|
||||
## 2.0.0-alpha.35 (2019-11-17)
|
||||
|
||||
#### :rocket: New Feature
|
||||
|
||||
|
@ -4871,7 +4871,7 @@ For example, if you've swizzled `@theme/DocItem`. You'll have to update
|
|||
- Nick McCormick ([@kenning](https://github.com/kenning))
|
||||
- Vincent van der Walt ([@vinnytheviking](https://github.com/vinnytheviking))
|
||||
|
||||
## 2.0.0-alpha.34
|
||||
## 2.0.0-alpha.34 (2019-11-11)
|
||||
|
||||
#### :rocket: New Feature
|
||||
|
||||
|
@ -4916,7 +4916,7 @@ For example, if you've swizzled `@theme/DocItem`. You'll have to update
|
|||
- Endi ([@endiliey](https://github.com/endiliey))
|
||||
- Yangshun Tay ([@yangshun](https://github.com/yangshun))
|
||||
|
||||
## 2.0.0-alpha.33
|
||||
## 2.0.0-alpha.33 (2019-11-08)
|
||||
|
||||
#### Features
|
||||
|
||||
|
@ -4946,7 +4946,7 @@ For example, if you've swizzled `@theme/DocItem`. You'll have to update
|
|||
- Misc dependency upgrades.
|
||||
- Stability improvement (more tests) & refactoring on docs plugin to prevent regression.
|
||||
|
||||
## 2.0.0-alpha.32
|
||||
## 2.0.0-alpha.32 (2019-11-04)
|
||||
|
||||
#### Features
|
||||
|
||||
|
@ -4993,7 +4993,7 @@ function Home() {
|
|||
- Convert sitemap plugin to TypeScript. ([#1894](https://github.com/facebook/Docusaurus/issues/1894))
|
||||
- Refactor dark mode toggle into a hook. ([#1899](https://github.com/facebook/Docusaurus/issues/1899))
|
||||
|
||||
## 2.0.0-alpha.31
|
||||
## 2.0.0-alpha.31 (2019-10-26)
|
||||
|
||||
- Footer is now sticky/ pinned to the bottom of the viewport in desktop browsers.
|
||||
- Footer is now also displayed in docs page for consistency.
|
||||
|
@ -5010,13 +5010,13 @@ function Home() {
|
|||
- Increase sidebar width
|
||||
- etc
|
||||
|
||||
## 2.0.0-alpha.30
|
||||
## 2.0.0-alpha.30 (2019-10-22)
|
||||
|
||||
- Fix babel transpilation include/exclude logic to be more efficient. This also fix a very weird bug `TypeError: Cannot assign to read only property 'exports' of object '#<Object>'`.([#1868](https://github.com/facebook/docusaurus/pull/1868))
|
||||
|
||||
If you are still encountering the error. Please check whether you use `module.exports` for your `.js` file instead of doing `export` (mixing CJS and ES). See https://github.com/webpack/webpack/issues/4039#issuecomment-477779322 and https://github.com/webpack/webpack/issues/4039#issuecomment-273804003 for more context.
|
||||
|
||||
## 2.0.0-alpha.29
|
||||
## 2.0.0-alpha.29 (2019-10-21)
|
||||
|
||||
**HOTFIX for 2.0.0-alpha.28**.
|
||||
|
||||
|
@ -5024,7 +5024,7 @@ If you are still encountering the error. Please check whether you use `module.ex
|
|||
- Fix wrong `@babel/env` preset configuration that causes build compilation error.
|
||||
- New UI for webpack compilation progress bar.
|
||||
|
||||
## 2.0.0-alpha.28
|
||||
## 2.0.0-alpha.28 (2019-10-21)
|
||||
|
||||
- Further reduce memory usage to avoid heap memory allocation failure.
|
||||
- Fix `keywords` frontmatter for SEO not working properly.
|
||||
|
@ -5039,14 +5039,14 @@ If you are still encountering the error. Please check whether you use `module.ex
|
|||
- Fix potential security vulnerability because we're exposing the directory structure of the host machine.
|
||||
- Upgrade dependencies.
|
||||
|
||||
## 2.0.0-alpha.27
|
||||
## 2.0.0-alpha.27 (2019-10-14)
|
||||
|
||||
- Add `@theme/Tabs` which can be used to implement multi-language code tabs.
|
||||
- Implement `custom_edit_url` and `hide_title` markdown header for docusaurus v1 feature parity.
|
||||
- Reduce memory usage and slightly faster production build.
|
||||
- Misc dependency upgrades.
|
||||
|
||||
## 2.0.0-alpha.26
|
||||
## 2.0.0-alpha.26 (2019-10-12)
|
||||
|
||||
- Docs, pages plugin is rewritten in TypeScript
|
||||
- Docs improvements and tweaks
|
||||
|
@ -5063,7 +5063,7 @@ If you are still encountering the error. Please check whether you use `module.ex
|
|||
- Add `scripts` and `stylesheets` field to `docusaurus.config.js`
|
||||
- More documentation...
|
||||
|
||||
## 2.0.0-alpha.25
|
||||
## 2.0.0-alpha.25 (2019-10-01)
|
||||
|
||||
- Blog plugin is rewritten in TypeScript and can now support CJK
|
||||
- Upgrade key direct dependencies such as webpack, mdx and babel to latest
|
||||
|
@ -5073,7 +5073,7 @@ If you are still encountering the error. Please check whether you use `module.ex
|
|||
- Add `truncateMarker` option to blog plugin, support string or regex.
|
||||
- Webpack `optimization.removeAvailableModules` is now disabled for performance gain. See https://github.com/webpack/webpack/releases/tag/v4.38.0 for more context.
|
||||
|
||||
## 2.0.0-alpha.24
|
||||
## 2.0.0-alpha.24 (2019-07-24)
|
||||
|
||||
- Remove unused metadata for pages. This minimize number of http request & smaller bundle size.
|
||||
- Upgrade dependencies of css-loader from 2.x to 3.x. Css modules localIdentName hash now only use the last 4 characters instead of 8.
|
||||
|
@ -5082,11 +5082,11 @@ If you are still encountering the error. Please check whether you use `module.ex
|
|||
- Use contenthash instead of chunkhash for better long term caching
|
||||
- Allow user to customize generated heading from MDX. Swizzle `@theme/Heading`
|
||||
|
||||
## 2.0.0-alpha.23
|
||||
## 2.0.0-alpha.23 (2019-07-21)
|
||||
|
||||
- Fix docusaurus route config generation for certain edge case
|
||||
|
||||
## 2.0.0-alpha.22
|
||||
## 2.0.0-alpha.22 (2019-07-20)
|
||||
|
||||
- Add missing dependencies on `@docusaurus/preset-classic`
|
||||
- New plugin `@docusaurus/plugin-ideal-image` to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder)
|
||||
|
@ -5097,11 +5097,11 @@ If you are still encountering the error. Please check whether you use `module.ex
|
|||
- `@docusaurus/theme-live-codeblock` is now much smaller in size and no longer only load on viewport
|
||||
- Blog markdown files now support using the id field to specify the path
|
||||
|
||||
## 2.0.0-alpha.21
|
||||
## 2.0.0-alpha.21 (2019-07-14)
|
||||
|
||||
- Fix babel-loader not transpiling docusaurus package
|
||||
|
||||
## 2.0.0-alpha.20
|
||||
## 2.0.0-alpha.20 (2019-07-14)
|
||||
|
||||
- Add copy codeblock button
|
||||
- Add Google analytics and Google gtag plugins.
|
||||
|
@ -5117,7 +5117,7 @@ If you are still encountering the error. Please check whether you use `module.ex
|
|||
- Drop cache-loader in CI and test environment because it has an initial overhead. We always start from scratch in vm instance like CI so cache-loader is useless
|
||||
- Better splitchunks and babel default webpack config
|
||||
|
||||
## 2.0.0-alpha.19
|
||||
## 2.0.0-alpha.19 (2019-06-07)
|
||||
|
||||
- Add a sensible default for browserslist config.
|
||||
- UI
|
||||
|
@ -5156,7 +5156,7 @@ presets: [
|
|||
- Minify css for production build
|
||||
- Fix weird scrolling problem when navigating to a route with a `hash` location
|
||||
|
||||
## V2 Changelog
|
||||
## V2 Changelog (2019-04-10)
|
||||
|
||||
### `siteConfig.js` changes
|
||||
|
||||
|
@ -5189,7 +5189,7 @@ themeConfig: {
|
|||
}
|
||||
```
|
||||
|
||||
# Migration Guide
|
||||
### Migration Guide
|
||||
|
||||
_Work in Progress_
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
title: Docusaurus 2 Changelog
|
||||
hide_title: true
|
||||
sidebar_label: Changelog
|
||||
---
|
||||
|
||||
```mdx-code-block
|
||||
import Changelog, {toc as ChangelogTOC} from "@site/../CHANGELOG.md"
|
||||
|
||||
<Changelog />
|
||||
|
||||
export const toc = ChangelogTOC;
|
||||
```
|
|
@ -112,6 +112,27 @@ const config = {
|
|||
],
|
||||
themes: ['live-codeblock'],
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('./src/plugins/changelog/index.js'),
|
||||
{
|
||||
blogTitle: 'Docusaurus changelog',
|
||||
blogDescription: 'Keep yourself up-to-date about new features in every release',
|
||||
blogSidebarCount: 'ALL',
|
||||
blogSidebarTitle: 'Changelog',
|
||||
routeBasePath: '/changelog',
|
||||
showReadingTime: false,
|
||||
postsPerPage: 20,
|
||||
archiveBasePath: null,
|
||||
authorsMapPath: 'authors.json',
|
||||
feedOptions: {
|
||||
type: 'all',
|
||||
title: 'Docusaurus changelog',
|
||||
description: 'Keep yourself up-to-date about new features in every release',
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`,
|
||||
language: 'en',
|
||||
}
|
||||
},
|
||||
],
|
||||
[
|
||||
'content-docs',
|
||||
/** @type {import('@docusaurus/plugin-content-docs').Options} */
|
||||
|
@ -456,6 +477,10 @@ const config = {
|
|||
label: 'Blog',
|
||||
to: 'blog',
|
||||
},
|
||||
{
|
||||
label: 'Changelog',
|
||||
to: '/changelog',
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/facebook/docusaurus',
|
||||
|
@ -510,7 +535,7 @@ const config = {
|
|||
|
||||
async function createConfig() {
|
||||
const FeatureRequestsPlugin = (
|
||||
await import('./src/featureRequests/FeatureRequestsPlugin.mjs')
|
||||
await import('./src/plugins/featureRequests/FeatureRequestsPlugin.mjs')
|
||||
).default;
|
||||
const configTabs = (await import('./src/remark/configTabs.mjs')).default;
|
||||
const lightTheme = (await import('./src/utils/prismLight.mjs')).default;
|
||||
|
|
|
@ -41,7 +41,9 @@
|
|||
"@docusaurus/theme-common": "2.0.0-beta.15",
|
||||
"@docusaurus/theme-live-codeblock": "2.0.0-beta.15",
|
||||
"@docusaurus/utils": "2.0.0-beta.15",
|
||||
"@docusaurus/utils-common": "2.0.0-beta.15",
|
||||
"@popperjs/core": "^2.10.2",
|
||||
"axios": "^0.25.0",
|
||||
"clsx": "^1.1.1",
|
||||
"color": "^4.0.1",
|
||||
"esbuild-loader": "2.16.0",
|
||||
|
|
|
@ -11,6 +11,11 @@ module.exports = {
|
|||
type: 'autogenerated',
|
||||
dirName: '.',
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/changelog',
|
||||
label: 'Changelog',
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/showcase',
|
||||
|
|
158
website/src/plugins/changelog/index.js
Normal file
158
website/src/plugins/changelog/index.js
Normal file
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* 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;
|
88
website/src/plugins/changelog/syncAvatars.js
Normal file
88
website/src/plugins/changelog/syncAvatars.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* 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 */
|
||||
|
||||
// @ts-check
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
// const axios = require('axios').default;
|
||||
|
||||
// TODO not sure how the syncing should be done at all... for now it always
|
||||
// pretends the limit is reached. We should only fetch a portion of the avatars
|
||||
// at a time. But seems avatars.githubusercontent.com API doesn't like HTTP requests?
|
||||
/**
|
||||
* @param {string} username
|
||||
* @param {Record<string, number>} lastUpdateCache
|
||||
* @param {Record<string, {imageURL: string; url: string}>} authorsMap
|
||||
* @returns true if saved successfully (including not found); false if limited reached
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async function fetchImage(username, lastUpdateCache, authorsMap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to keep track of all committers that are in the changelog, and fetch
|
||||
* their avatars beforehand. This prevents sending too many requests to GitHub
|
||||
* every time one visits a page. Avatar refreshing is done incrementally across
|
||||
* each build.
|
||||
*
|
||||
* This method mutates the authorsMap. If the avatar fails to be fetched, the
|
||||
* imageURL is re-written with the github remote URL. The authors map is then
|
||||
* written to FS.
|
||||
*
|
||||
* @param {Record<string, {name: string, url: string, alias: string, imageURL: string}>} authorsMap
|
||||
* @param {string} generateDir
|
||||
*/
|
||||
async function syncAvatars(authorsMap, generateDir) {
|
||||
const imagePath = path.join(generateDir, 'img');
|
||||
const lastUpdateCachePath = path.join(imagePath, 'lastUpdate.json');
|
||||
const authorsPath = path.join(generateDir, 'authors.json');
|
||||
if (!(await fs.pathExists(lastUpdateCachePath))) {
|
||||
await fs.outputFile(lastUpdateCachePath, '{}');
|
||||
}
|
||||
/**
|
||||
* Records the last time an avatar was successfully updated.
|
||||
* If an entry doesn't exist, the file won't exist either.
|
||||
* @type {Record<string, number>}
|
||||
*/
|
||||
const lastUpdateCache = await fs.readJSON(lastUpdateCachePath);
|
||||
let limitReached = false;
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const username of Object.keys(authorsMap)) {
|
||||
if (!limitReached && !lastUpdateCache[username]) {
|
||||
if (!(await fetchImage(username, lastUpdateCache, authorsMap))) {
|
||||
limitReached = true;
|
||||
}
|
||||
}
|
||||
if (limitReached) {
|
||||
authorsMap[username].imageURL = `https://github.com/${username}.png`;
|
||||
}
|
||||
}
|
||||
const usersByLastUpdate = Object.entries(lastUpdateCache)
|
||||
.sort((a, b) => a[1] - b[1])
|
||||
.map((a) => a[0]);
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const username of usersByLastUpdate) {
|
||||
if (
|
||||
!limitReached &&
|
||||
lastUpdateCache[username] < Date.now() - 24 * 3600 * 1000
|
||||
) {
|
||||
if (!(await fetchImage(username, lastUpdateCache, authorsMap))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
await fs.outputFile(
|
||||
lastUpdateCachePath,
|
||||
JSON.stringify(lastUpdateCache, null, 2),
|
||||
);
|
||||
await fs.outputFile(authorsPath, JSON.stringify(authorsMap, null, 2));
|
||||
}
|
||||
|
||||
module.exports = syncAvatars;
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* 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 React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import type {Props} from '@theme/BlogPostAuthor';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function ChangelogAuthor({author}: Props): JSX.Element {
|
||||
const {name, url, imageURL} = author;
|
||||
return (
|
||||
<div className="avatar margin-bottom--sm">
|
||||
{imageURL && (
|
||||
<Link className="avatar__photo-link avatar__photo" href={url}>
|
||||
<img
|
||||
className={styles.image}
|
||||
src={imageURL}
|
||||
alt={name}
|
||||
onError={(e) => {
|
||||
// Image returns 404 if the user's handle changes. We display a fallback instead.
|
||||
e.currentTarget.src =
|
||||
'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" fill="none" stroke="%2325c2a0" stroke-width="30" version="1.1"><circle cx="300" cy="230" r="115"/><path stroke-linecap="butt" d="M106.81863443903,481.4 a205,205 1 0,1 386.36273112194,0"/></svg>';
|
||||
}}
|
||||
/>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChangelogAuthor;
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* 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 React, {useState} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import type {Props} from '@theme/BlogPostAuthors';
|
||||
import ChangelogAuthor from '@theme/ChangelogAuthor';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import IconExpand from '@theme/IconExpand';
|
||||
|
||||
// Component responsible for the authors layout
|
||||
export default function BlogPostAuthors({
|
||||
authors,
|
||||
assets,
|
||||
}: Props): JSX.Element | null {
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const authorsCount = authors.length;
|
||||
if (authorsCount === 0) {
|
||||
return null;
|
||||
}
|
||||
const filteredAuthors = authors.slice(0, expanded ? authors.length : 10);
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'margin-top--md margin-bottom--sm',
|
||||
styles.imageOnlyAuthorRow,
|
||||
)}>
|
||||
{filteredAuthors.map((author, idx) => (
|
||||
<div className={styles.imageOnlyAuthorCol} key={idx}>
|
||||
<ChangelogAuthor
|
||||
author={{
|
||||
...author,
|
||||
// Handle author images using relative paths
|
||||
imageURL: assets.authorsImageUrls[idx] ?? author.imageURL,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{authors.length > 10 && (
|
||||
<button
|
||||
className={clsx('clean-btn', styles.toggleButton)}
|
||||
type="button"
|
||||
onClick={() => setExpanded((v) => !v)}
|
||||
aria-label="expand">
|
||||
<IconExpand expanded={expanded} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.authorCol {
|
||||
max-width: inherit !important;
|
||||
flex-grow: 1 !important;
|
||||
}
|
||||
|
||||
.imageOnlyAuthorRow {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
.imageOnlyAuthorCol {
|
||||
margin-left: 0.3rem;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
|
||||
.imageOnlyAuthorCol [class^='image'] {
|
||||
background-color: var(--ifm-color-emphasis-100);
|
||||
}
|
||||
|
||||
.toggleButton {
|
||||
margin-left: 0.3rem;
|
||||
margin-right: 0.3rem;
|
||||
border-radius: 50%;
|
||||
width: var(--ifm-avatar-photo-size-md);
|
||||
height: var(--ifm-avatar-photo-size-md);
|
||||
background-color: var(--ifm-color-emphasis-100);
|
||||
}
|
||||
|
||||
.toggleButtonIconExpanded {
|
||||
transform: rotate(180deg);
|
||||
}
|
79
website/src/plugins/changelog/theme/ChangelogItem/index.tsx
Normal file
79
website/src/plugins/changelog/theme/ChangelogItem/index.tsx
Normal file
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* 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 React from 'react';
|
||||
import clsx from 'clsx';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import {MDXProvider} from '@mdx-js/react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
||||
import {blogPostContainerID} from '@docusaurus/utils-common';
|
||||
import MDXComponents from '@theme/MDXComponents';
|
||||
import type {Props} from '@theme/BlogPostItem';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import ChangelogAuthors from '@theme/ChangelogAuthors';
|
||||
|
||||
function ChangelogItem(props: Props): JSX.Element {
|
||||
const {withBaseUrl} = useBaseUrlUtils();
|
||||
const {
|
||||
children,
|
||||
frontMatter,
|
||||
assets,
|
||||
metadata,
|
||||
isBlogPostPage = false,
|
||||
} = props;
|
||||
const {date, formattedDate, permalink, title, authors} = metadata;
|
||||
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
|
||||
const TitleHeading = isBlogPostPage ? 'h1' : 'h2';
|
||||
|
||||
return (
|
||||
<article
|
||||
className={!isBlogPostPage ? 'margin-bottom--md' : undefined}
|
||||
itemProp="blogPost"
|
||||
itemScope
|
||||
itemType="http://schema.org/BlogPosting">
|
||||
<header>
|
||||
<TitleHeading
|
||||
className={clsx(
|
||||
isBlogPostPage ? styles.blogPostPageTitle : styles.blogPostTitle,
|
||||
)}
|
||||
itemProp="headline">
|
||||
{isBlogPostPage ? (
|
||||
title
|
||||
) : (
|
||||
<Link itemProp="url" to={permalink}>
|
||||
{title}
|
||||
</Link>
|
||||
)}
|
||||
</TitleHeading>
|
||||
<div className={clsx(styles.blogPostData, 'margin-vert--md')}>
|
||||
<time dateTime={date} itemProp="datePublished">
|
||||
{formattedDate}
|
||||
</time>
|
||||
</div>
|
||||
<ChangelogAuthors authors={authors} assets={assets} />
|
||||
</header>
|
||||
|
||||
{image && (
|
||||
<meta itemProp="image" content={withBaseUrl(image, {absolute: true})} />
|
||||
)}
|
||||
|
||||
<div
|
||||
// This ID is used for the feed generation to locate the main content
|
||||
id={isBlogPostPage ? blogPostContainerID : undefined}
|
||||
className="markdown"
|
||||
itemProp="articleBody">
|
||||
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChangelogItem;
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.blogPostTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.blogPostPageTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.blogPostData {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.blogPostDetailsFull {
|
||||
flex-direction: column;
|
||||
}
|
92
website/src/plugins/changelog/theme/ChangelogList/index.tsx
Normal file
92
website/src/plugins/changelog/theme/ChangelogList/index.tsx
Normal file
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* 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 React from 'react';
|
||||
import BlogLayout from '@theme/BlogLayout';
|
||||
import BlogListPaginator from '@theme/BlogListPaginator';
|
||||
import type {Props} from '@theme/BlogListPage';
|
||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||
import Link from '@docusaurus/Link';
|
||||
import ChangelogItem from '@theme/ChangelogItem';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function ChangelogList(props: Props): JSX.Element {
|
||||
const {metadata, items, sidebar} = props;
|
||||
const {blogDescription, blogTitle} = metadata;
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
title={blogTitle}
|
||||
description={blogDescription}
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogListPage}
|
||||
searchMetadata={{
|
||||
// assign unique search tag to exclude this page from search results!
|
||||
tag: 'blog_posts_list',
|
||||
}}
|
||||
sidebar={sidebar}>
|
||||
<header className="margin-bottom--lg">
|
||||
<h1 style={{fontSize: '3rem'}}>{blogTitle}</h1>
|
||||
<p>
|
||||
Subscribe through{' '}
|
||||
<Link href="pathname:///changelog/rss.xml" className={styles.rss}>
|
||||
<b>RSS feeds</b>
|
||||
<svg
|
||||
style={{
|
||||
fill: '#f26522',
|
||||
position: 'relative',
|
||||
left: 4,
|
||||
top: 1,
|
||||
marginRight: 8,
|
||||
}}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24">
|
||||
<path d="M6.503 20.752c0 1.794-1.456 3.248-3.251 3.248-1.796 0-3.252-1.454-3.252-3.248 0-1.794 1.456-3.248 3.252-3.248 1.795.001 3.251 1.454 3.251 3.248zm-6.503-12.572v4.811c6.05.062 10.96 4.966 11.022 11.009h4.817c-.062-8.71-7.118-15.758-15.839-15.82zm0-3.368c10.58.046 19.152 8.594 19.183 19.188h4.817c-.03-13.231-10.755-23.954-24-24v4.812z" />
|
||||
</svg>
|
||||
</Link>{' '}
|
||||
or follow us on{' '}
|
||||
<Link
|
||||
href="https://twitter.com/docusaurus"
|
||||
className={styles.twitter}>
|
||||
<b>Twitter</b>
|
||||
<svg
|
||||
style={{
|
||||
fill: '#1da1f2',
|
||||
position: 'relative',
|
||||
left: 4,
|
||||
top: 1,
|
||||
marginRight: 8,
|
||||
}}
|
||||
width="16"
|
||||
height="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512">
|
||||
<path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z" />
|
||||
</svg>
|
||||
</Link>{' '}
|
||||
to stay up-to-date with new releases!
|
||||
</p>
|
||||
</header>
|
||||
{items.map(({content: BlogPostContent}) => (
|
||||
<ChangelogItem
|
||||
key={BlogPostContent.metadata.permalink}
|
||||
frontMatter={BlogPostContent.frontMatter}
|
||||
assets={BlogPostContent.assets}
|
||||
metadata={BlogPostContent.metadata}
|
||||
truncated={BlogPostContent.metadata.truncated}>
|
||||
<BlogPostContent />
|
||||
</ChangelogItem>
|
||||
))}
|
||||
<BlogListPaginator metadata={metadata} />
|
||||
</BlogLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChangelogList;
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.blogPostTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.blogPostData {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.blogPostDetailsFull {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.rss,
|
||||
.rss:hover {
|
||||
color: #f26522;
|
||||
}
|
||||
|
||||
.twitter,
|
||||
.twitter:hover {
|
||||
color: #1da1f2;
|
||||
}
|
102
website/src/plugins/changelog/theme/ChangelogPage/index.tsx
Normal file
102
website/src/plugins/changelog/theme/ChangelogPage/index.tsx
Normal file
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* 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 React from 'react';
|
||||
import Seo from '@theme/Seo';
|
||||
import BlogLayout from '@theme/BlogLayout';
|
||||
import ChangelogItem from '@theme/ChangelogItem';
|
||||
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
||||
import type {Props} from '@theme/BlogPostPage';
|
||||
import {ThemeClassNames} from '@docusaurus/theme-common';
|
||||
import TOC from '@theme/TOC';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
// This page doesn't change anything. It's just swapping BlogPostItem with our
|
||||
// own ChangelogItem. We don't want to apply the swizzled item to the actual blog.
|
||||
function BlogPostPage(props: Props): JSX.Element {
|
||||
const {content: BlogPostContents, sidebar} = props;
|
||||
const {assets, metadata} = BlogPostContents;
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
nextItem,
|
||||
prevItem,
|
||||
date,
|
||||
tags,
|
||||
authors,
|
||||
frontMatter,
|
||||
// @ts-expect-error: we injected this
|
||||
listPageLink,
|
||||
} = metadata;
|
||||
const {
|
||||
hide_table_of_contents: hideTableOfContents,
|
||||
keywords,
|
||||
toc_min_heading_level: tocMinHeadingLevel,
|
||||
toc_max_heading_level: tocMaxHeadingLevel,
|
||||
} = frontMatter;
|
||||
|
||||
const image = assets.image ?? frontMatter.image;
|
||||
|
||||
return (
|
||||
<BlogLayout
|
||||
wrapperClassName={ThemeClassNames.wrapper.blogPages}
|
||||
pageClassName={ThemeClassNames.page.blogPostPage}
|
||||
sidebar={sidebar}
|
||||
toc={
|
||||
!hideTableOfContents &&
|
||||
BlogPostContents.toc &&
|
||||
BlogPostContents.toc.length > 0 ? (
|
||||
<TOC
|
||||
toc={BlogPostContents.toc}
|
||||
minHeadingLevel={tocMinHeadingLevel}
|
||||
maxHeadingLevel={tocMaxHeadingLevel}
|
||||
/>
|
||||
) : undefined
|
||||
}>
|
||||
<Seo
|
||||
title={title}
|
||||
description={description}
|
||||
keywords={keywords}
|
||||
image={image}>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="article:published_time" content={date} />
|
||||
|
||||
{authors.some((author) => author.url) && (
|
||||
<meta
|
||||
property="article:author"
|
||||
content={authors
|
||||
.map((author) => author.url)
|
||||
.filter(Boolean)
|
||||
.join(',')}
|
||||
/>
|
||||
)}
|
||||
{tags.length > 0 && (
|
||||
<meta
|
||||
property="article:tag"
|
||||
content={tags.map((tag) => tag.label).join(',')}
|
||||
/>
|
||||
)}
|
||||
</Seo>
|
||||
|
||||
<Link to={listPageLink}>← Back to index page</Link>
|
||||
|
||||
<ChangelogItem
|
||||
frontMatter={frontMatter}
|
||||
assets={assets}
|
||||
metadata={metadata}
|
||||
isBlogPostPage>
|
||||
<BlogPostContents />
|
||||
</ChangelogItem>
|
||||
|
||||
{(nextItem || prevItem) && (
|
||||
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
||||
)}
|
||||
</BlogLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export default BlogPostPage;
|
37
website/src/plugins/changelog/theme/IconExpand/index.tsx
Normal file
37
website/src/plugins/changelog/theme/IconExpand/index.tsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* 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 React from 'react';
|
||||
|
||||
import type {Props} from '@theme/IconExpand';
|
||||
|
||||
function IconExpand({expanded, ...props}: Props): JSX.Element {
|
||||
if (expanded) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
width="20"
|
||||
height="20"
|
||||
fill="currentColor"
|
||||
{...props}>
|
||||
<path d="M783.915092 1009.031953l-271.898251-277.615587-271.930737 277.550617a49.214558 49.214558 0 0 1-70.752018 0 51.780862 51.780862 0 0 1 0-72.246322l307.274261-313.706262a49.279528 49.279528 0 0 1 70.784503 0l307.33923 313.706262a51.975771 51.975771 0 0 1 0 72.311292 49.409467 49.409467 0 0 1-70.816988 0z m-307.306745-608.05155L169.269117 87.274141A51.975771 51.975771 0 0 1 169.269117 14.96285a49.409467 49.409467 0 0 1 70.816987 0l271.930737 277.615586L783.850122 14.96285a49.409467 49.409467 0 0 1 70.816988 0 51.975771 51.975771 0 0 1 0 72.311291l-307.33923 313.706262a49.376982 49.376982 0 0 1-70.719533 0z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
width="20"
|
||||
height="20"
|
||||
fill="currentColor"
|
||||
{...props}>
|
||||
<path d="M476.612887 1009.12034L169.240699 695.380437a51.981345 51.981345 0 0 1 0-72.319045 49.382277 49.382277 0 0 1 70.824582 0l271.959897 277.645356 271.862433-277.645356a49.382277 49.382277 0 0 1 70.824582 0 51.981345 51.981345 0 0 1 0 72.319045l-307.307212 313.739903a49.447254 49.447254 0 0 1-70.792094 0z m307.274724-608.116755L511.99269 123.455693l-271.959897 277.645357a49.382277 49.382277 0 0 1-70.824582 0 51.981345 51.981345 0 0 1 0-72.319045L476.580399 15.042102a49.382277 49.382277 0 0 1 70.727117 0l307.372188 313.739903a51.981345 51.981345 0 0 1 0 72.319045 49.414766 49.414766 0 0 1-70.824582 0z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default IconExpand;
|
20
website/src/plugins/changelog/theme/types.d.ts
vendored
Normal file
20
website/src/plugins/changelog/theme/types.d.ts
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare module '@theme/ChangelogItem';
|
||||
declare module '@theme/ChangelogAuthors';
|
||||
declare module '@theme/ChangelogAuthor';
|
||||
declare module '@theme/IconExpand' {
|
||||
import type {ComponentProps} from 'react';
|
||||
|
||||
export interface Props extends ComponentProps<'svg'> {
|
||||
expanded?: boolean;
|
||||
}
|
||||
|
||||
const IconExpand: (props: Props) => JSX.Element;
|
||||
export default IconExpand;
|
||||
}
|
|
@ -19,13 +19,16 @@ export default function FeatureRequestsPlugin(context) {
|
|||
context.baseUrl,
|
||||
'/feature-requests',
|
||||
]);
|
||||
await actions.createData('paths.json', JSON.stringify(basePath));
|
||||
const paths = await actions.createData(
|
||||
'paths.json',
|
||||
JSON.stringify(basePath),
|
||||
);
|
||||
actions.addRoute({
|
||||
path: basePath,
|
||||
exact: false,
|
||||
component: '@site/src/featureRequests/FeatureRequestsPage',
|
||||
component: '@site/src/plugins/featureRequests/FeatureRequestsPage',
|
||||
modules: {
|
||||
basePath: './feature-requests-plugin/default/paths.json',
|
||||
basePath: paths,
|
||||
},
|
||||
});
|
||||
},
|
|
@ -5303,6 +5303,13 @@ axios@^0.21.1:
|
|||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
axios@^0.25.0:
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a"
|
||||
integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.7"
|
||||
|
||||
axobject-query@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
||||
|
@ -9182,7 +9189,7 @@ folder-walker@^3.2.0:
|
|||
dependencies:
|
||||
from2 "^2.1.0"
|
||||
|
||||
follow-redirects@^1.0.0, follow-redirects@^1.14.0:
|
||||
follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.7:
|
||||
version "1.14.7"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
|
||||
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
|
||||
|
|
Loading…
Add table
Reference in a new issue