diff --git a/.gitignore b/.gitignore index 04d22349cf..e923cdb4c2 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ packages/stylelint-copyright/lib/ packages/docusaurus-*/lib-next/ website/netlifyDeployPreview/* +website/changelog !website/netlifyDeployPreview/index.html !website/netlifyDeployPreview/_redirects diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f104ed1d1..97970472aa 100644 --- a/CHANGELOG.md +++ b/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 '#'`.([#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_ diff --git a/website/community/5-changelog.md b/website/community/5-changelog.md deleted file mode 100644 index 468dbaefb6..0000000000 --- a/website/community/5-changelog.md +++ /dev/null @@ -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" - - - -export const toc = ChangelogTOC; -``` diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index bb6c17d820..7fc0bad551 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -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; diff --git a/website/package.json b/website/package.json index 1ac8c4bc22..ab6da04211 100644 --- a/website/package.json +++ b/website/package.json @@ -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", diff --git a/website/sidebarsCommunity.js b/website/sidebarsCommunity.js index 472c48590f..62f542cee5 100644 --- a/website/sidebarsCommunity.js +++ b/website/sidebarsCommunity.js @@ -11,6 +11,11 @@ module.exports = { type: 'autogenerated', dirName: '.', }, + { + type: 'link', + href: '/changelog', + label: 'Changelog', + }, { type: 'link', href: '/showcase', diff --git a/website/src/plugins/changelog/index.js b/website/src/plugins/changelog/index.js new file mode 100644 index 0000000000..c8e5cfdf2b --- /dev/null +++ b/website/src/plugins/changelog/index.js @@ -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} */ +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( + /- (?:(?.*?) \()?\[@(?.*)\]\((?.*?)\)\)?/, + ).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(/ \(.*\)/, '')} + + + +${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; diff --git a/website/src/plugins/changelog/syncAvatars.js b/website/src/plugins/changelog/syncAvatars.js new file mode 100644 index 0000000000..bbcf3d5e59 --- /dev/null +++ b/website/src/plugins/changelog/syncAvatars.js @@ -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} lastUpdateCache + * @param {Record} 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} 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} + */ + 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; diff --git a/website/src/plugins/changelog/theme/ChangelogAuthor/index.tsx b/website/src/plugins/changelog/theme/ChangelogAuthor/index.tsx new file mode 100644 index 0000000000..c5f10ab95a --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogAuthor/index.tsx @@ -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 ( +
+ {imageURL && ( + + {name} { + // Image returns 404 if the user's handle changes. We display a fallback instead. + e.currentTarget.src = + 'data:image/svg+xml,'; + }} + /> + + )} +
+ ); +} + +export default ChangelogAuthor; diff --git a/website/src/plugins/changelog/theme/ChangelogAuthor/styles.module.css b/website/src/plugins/changelog/theme/ChangelogAuthor/styles.module.css new file mode 100644 index 0000000000..aae60add2d --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogAuthor/styles.module.css @@ -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; +} diff --git a/website/src/plugins/changelog/theme/ChangelogAuthors/index.tsx b/website/src/plugins/changelog/theme/ChangelogAuthors/index.tsx new file mode 100644 index 0000000000..0ca25fbe7c --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogAuthors/index.tsx @@ -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 ( +
+ {filteredAuthors.map((author, idx) => ( +
+ +
+ ))} + {authors.length > 10 && ( + + )} +
+ ); +} diff --git a/website/src/plugins/changelog/theme/ChangelogAuthors/styles.module.css b/website/src/plugins/changelog/theme/ChangelogAuthors/styles.module.css new file mode 100644 index 0000000000..08d003d4e0 --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogAuthors/styles.module.css @@ -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); +} diff --git a/website/src/plugins/changelog/theme/ChangelogItem/index.tsx b/website/src/plugins/changelog/theme/ChangelogItem/index.tsx new file mode 100644 index 0000000000..6749a3c5f3 --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogItem/index.tsx @@ -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 ( +
+
+ + {isBlogPostPage ? ( + title + ) : ( + + {title} + + )} + +
+ +
+ +
+ + {image && ( + + )} + +
+ {children} +
+
+ ); +} + +export default ChangelogItem; diff --git a/website/src/plugins/changelog/theme/ChangelogItem/styles.module.css b/website/src/plugins/changelog/theme/ChangelogItem/styles.module.css new file mode 100644 index 0000000000..b3e827c96f --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogItem/styles.module.css @@ -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; +} diff --git a/website/src/plugins/changelog/theme/ChangelogList/index.tsx b/website/src/plugins/changelog/theme/ChangelogList/index.tsx new file mode 100644 index 0000000000..342dc80d0e --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogList/index.tsx @@ -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 ( + +
+

{blogTitle}

+

+ Subscribe through{' '} + + RSS feeds + + + + {' '} + or follow us on{' '} + + Twitter + + + + {' '} + to stay up-to-date with new releases! +

+
+ {items.map(({content: BlogPostContent}) => ( + + + + ))} + +
+ ); +} + +export default ChangelogList; diff --git a/website/src/plugins/changelog/theme/ChangelogList/styles.module.css b/website/src/plugins/changelog/theme/ChangelogList/styles.module.css new file mode 100644 index 0000000000..1537857cf3 --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogList/styles.module.css @@ -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; +} diff --git a/website/src/plugins/changelog/theme/ChangelogPage/index.tsx b/website/src/plugins/changelog/theme/ChangelogPage/index.tsx new file mode 100644 index 0000000000..aebe4eed29 --- /dev/null +++ b/website/src/plugins/changelog/theme/ChangelogPage/index.tsx @@ -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 ( + 0 ? ( + + ) : undefined + }> + + + + + {authors.some((author) => author.url) && ( + author.url) + .filter(Boolean) + .join(',')} + /> + )} + {tags.length > 0 && ( + tag.label).join(',')} + /> + )} + + + ← Back to index page + + + + + + {(nextItem || prevItem) && ( + + )} + + ); +} + +export default BlogPostPage; diff --git a/website/src/plugins/changelog/theme/IconExpand/index.tsx b/website/src/plugins/changelog/theme/IconExpand/index.tsx new file mode 100644 index 0000000000..f41d7c0207 --- /dev/null +++ b/website/src/plugins/changelog/theme/IconExpand/index.tsx @@ -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 ( + + + + ); + } + return ( + + + + ); +} + +export default IconExpand; diff --git a/website/src/plugins/changelog/theme/types.d.ts b/website/src/plugins/changelog/theme/types.d.ts new file mode 100644 index 0000000000..d8cd21490e --- /dev/null +++ b/website/src/plugins/changelog/theme/types.d.ts @@ -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; +} diff --git a/website/src/featureRequests/FeatureRequestsPage.tsx b/website/src/plugins/featureRequests/FeatureRequestsPage.tsx similarity index 100% rename from website/src/featureRequests/FeatureRequestsPage.tsx rename to website/src/plugins/featureRequests/FeatureRequestsPage.tsx diff --git a/website/src/featureRequests/FeatureRequestsPlugin.mjs b/website/src/plugins/featureRequests/FeatureRequestsPlugin.mjs similarity index 77% rename from website/src/featureRequests/FeatureRequestsPlugin.mjs rename to website/src/plugins/featureRequests/FeatureRequestsPlugin.mjs index 6e1b9aa4f7..0d40466d17 100644 --- a/website/src/featureRequests/FeatureRequestsPlugin.mjs +++ b/website/src/plugins/featureRequests/FeatureRequestsPlugin.mjs @@ -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, }, }); }, diff --git a/website/src/featureRequests/cannyScript.js b/website/src/plugins/featureRequests/cannyScript.js similarity index 100% rename from website/src/featureRequests/cannyScript.js rename to website/src/plugins/featureRequests/cannyScript.js diff --git a/website/src/featureRequests/styles.module.css b/website/src/plugins/featureRequests/styles.module.css similarity index 100% rename from website/src/featureRequests/styles.module.css rename to website/src/plugins/featureRequests/styles.module.css diff --git a/yarn.lock b/yarn.lock index f35378b92a..a37cab7b87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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==