From 5359d61d9e6aad824b8185117ed167e0aadecd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 1 Sep 2020 19:38:11 +0200 Subject: [PATCH] fix(v2): allow using classic theme/preset without the docs plugin (#3382) * deprecated nextVersionLabel option * useActivePlugin failfast option * remove deprecated option nextVersionLabel * routeBasePath: '' should be forbidden * routeBasePath: '' should be forbidden * Docs: do not show version badge if there is only 1 version: https://github.com/facebook/docusaurus/issues/3362 * allow sidebars file to not exist: fallback to empty sidebars https://githu.com/facebook/docusaurus/issues/3366 * Ability to use classic theme/preset while not using docs/pages without trouble. https://github.com/facebook/docusaurus/issues/3360 * fix netlify redirects * do not throw if useDocs do not load? * netlify deploy typo * try to fix useDocs * docs(v2): update Deploy to Vercel guide (#3344) * filter annoying useDocs conditional require warning * netlify deploy preview homepage * typo * try to trigger again CLA bot Co-authored-by: Sam Ko --- .gitignore | 2 +- package.json | 2 + .../docusaurus-preset-bootstrap/src/index.js | 18 +++++- .../docusaurus-preset-classic/src/index.js | 21 +++++-- .../docusaurus-theme-classic/src/index.js | 7 +++ .../src/theme/NavbarItem/index.tsx | 21 ++++--- .../src/theme/hooks/useDocs.ts | 24 +++++++ packages/docusaurus/src/server/config.ts | 6 +- packages/docusaurus/src/webpack/utils.ts | 32 ++++++++-- website/docusaurus.config-blog-only.js | 63 +++++++++++++++++++ website/netlify.toml | 9 ++- website/netlifyDeployPreview/_redirects | 4 ++ website/netlifyDeployPreview/index.html | 31 +++++++++ website/package.json | 10 +-- 14 files changed, 223 insertions(+), 27 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/hooks/useDocs.ts create mode 100644 website/docusaurus.config-blog-only.js create mode 100644 website/netlifyDeployPreview/_redirects create mode 100644 website/netlifyDeployPreview/index.html diff --git a/.gitignore b/.gitignore index 00ec5b8ba6e5..83d670a967da 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,6 @@ packages/docusaurus-plugin-ideal-image/lib/ packages/docusaurus-theme-classic/lib/ packages/docusaurus-migrate/lib/ -website/netlifyDeploy +website/netlifyDeployPreview website-1.x-migrated diff --git a/package.json b/package.json index f6fd53c3887b..c526e81043be 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,13 @@ "start:v2:watch": "nodemon --watch \"./packages/*/lib/**/*.*\" --exec \"yarn start:v2\"", "start:v2:baseUrl": "yarn workspace docusaurus-2-website start:baseUrl", "start:v2:bootstrap": "yarn workspace docusaurus-2-website start:bootstrap", + "start:v2:blogOnly": "yarn workspace docusaurus-2-website start:blogOnly", "build": "yarn build:packages && yarn build:v2", "build:packages": "lerna run build --no-private", "build:v1": "yarn workspace docusaurus-1-website build", "build:v2": "yarn workspace docusaurus-2-website build", "build:v2:baseUrl": "yarn workspace docusaurus-2-website build:baseUrl", + "build:v2:blogOnly": "yarn workspace docusaurus-2-website build:blogOnly", "serve:v1": "serve website-1.x/build/docusaurus", "serve:v2": "serve website/build", "serve:v2:baseUrl": "serve website", diff --git a/packages/docusaurus-preset-bootstrap/src/index.js b/packages/docusaurus-preset-bootstrap/src/index.js index 66f4363b667a..7fde410869c5 100644 --- a/packages/docusaurus-preset-bootstrap/src/index.js +++ b/packages/docusaurus-preset-bootstrap/src/index.js @@ -9,9 +9,21 @@ module.exports = function preset(context, opts = {}) { return { themes: [[require.resolve('@docusaurus/theme-bootstrap'), opts.theme]], plugins: [ - [require.resolve('@docusaurus/plugin-content-pages'), opts.pages], - [require.resolve('@docusaurus/plugin-content-blog'), opts.blog], - [require.resolve('@docusaurus/plugin-content-docs'), opts.docs], + [ + opts.pages !== false && + require.resolve('@docusaurus/plugin-content-pages'), + opts.pages, + ], + [ + opts.blog !== false && + require.resolve('@docusaurus/plugin-content-blog'), + opts.blog, + ], + [ + opts.docs !== false && + require.resolve('@docusaurus/plugin-content-docs'), + opts.docs, + ], ], }; }; diff --git a/packages/docusaurus-preset-classic/src/index.js b/packages/docusaurus-preset-classic/src/index.js index 47f65208f1d3..7bd010a3b438 100644 --- a/packages/docusaurus-preset-classic/src/index.js +++ b/packages/docusaurus-preset-classic/src/index.js @@ -21,15 +21,28 @@ module.exports = function preset(context, opts = {}) { algolia && require.resolve('@docusaurus/theme-search-algolia'), ], plugins: [ - [require.resolve('@docusaurus/plugin-content-docs'), opts.docs], - [require.resolve('@docusaurus/plugin-content-blog'), opts.blog], - [require.resolve('@docusaurus/plugin-content-pages'), opts.pages], + opts.docs !== false && [ + require.resolve('@docusaurus/plugin-content-docs'), + opts.docs, + ], + opts.blog !== false && [ + require.resolve('@docusaurus/plugin-content-blog'), + opts.blog, + ], + opts.pages !== false && [ + require.resolve('@docusaurus/plugin-content-pages'), + opts.pages, + ], isProd && googleAnalytics && require.resolve('@docusaurus/plugin-google-analytics'), debug && require.resolve('@docusaurus/plugin-debug'), isProd && gtag && require.resolve('@docusaurus/plugin-google-gtag'), - isProd && [require.resolve('@docusaurus/plugin-sitemap'), opts.sitemap], + isProd && + opts.sitemap !== false && [ + require.resolve('@docusaurus/plugin-sitemap'), + opts.sitemap, + ], ], }; }; diff --git a/packages/docusaurus-theme-classic/src/index.js b/packages/docusaurus-theme-classic/src/index.js index f659f6532eb8..844f272bca04 100644 --- a/packages/docusaurus-theme-classic/src/index.js +++ b/packages/docusaurus-theme-classic/src/index.js @@ -95,6 +95,13 @@ module.exports = function (context, options) { .join('|'); return { + stats: { + warningsFilter: [ + // See https://github.com/facebook/docusaurus/pull/3382 + (warning) => + warning.includes("Can't resolve '@theme-init/hooks/useDocs"), + ], + }, plugins: [ new ContextReplacementPlugin( /prismjs[\\/]components$/, diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx index 04e7f3afad67..dd5257dd998b 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx @@ -6,25 +6,30 @@ */ import React from 'react'; -import DocsVersionNavbarItem from '@theme/NavbarItem/DocsVersionNavbarItem'; import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem'; -import DocsVersionDropdownNavbarItem from '@theme/NavbarItem/DocsVersionDropdownNavbarItem'; import type {Props} from '@theme/NavbarItem'; const NavbarItemComponents = { - default: DefaultNavbarItem, - docsVersion: DocsVersionNavbarItem, - docsVersionDropdown: DocsVersionDropdownNavbarItem, + default: () => DefaultNavbarItem, + + // Need to lazy load these items as we don't know for sure the docs plugin is loaded + // See https://github.com/facebook/docusaurus/issues/3360 + docsVersion: () => + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('@theme/NavbarItem/DocsVersionNavbarItem').default, + docsVersionDropdown: () => + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('@theme/NavbarItem/DocsVersionDropdownNavbarItem').default, } as const; const getNavbarItemComponent = ( type: keyof typeof NavbarItemComponents = 'default', ) => { - const NavbarItemComponent = NavbarItemComponents[type]; - if (!NavbarItemComponent) { + const navbarItemComponent = NavbarItemComponents[type]; + if (!navbarItemComponent) { throw new Error(`No NavbarItem component found for type=${type}.`); } - return NavbarItemComponent; + return navbarItemComponent(); }; export default function NavbarItem({type, ...props}: Props): JSX.Element { diff --git a/packages/docusaurus-theme-classic/src/theme/hooks/useDocs.ts b/packages/docusaurus-theme-classic/src/theme/hooks/useDocs.ts new file mode 100644 index 000000000000..15323456e6b7 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/hooks/useDocs.ts @@ -0,0 +1,24 @@ +/** + * 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. + */ + +// See https://github.com/facebook/docusaurus/issues/3360 +// TODO find a better solution, this shouldn't be needed + +// TODO this is not ideal and produce a warning! +// see https://github.com/webpack/webpack/issues/7713#issuecomment-467888437 +// note: warning can be filtered: https://github.com/facebook/docusaurus/pull/3382#issuecomment-684966924 +try { + module.exports = require('@theme-init/hooks/useDocs'); +} catch (e) { + module.exports = {}; +} + +/* +throw new Error( + "The docs plugin is not used, so you can't require the useDocs hooks. ", +); + */ diff --git a/packages/docusaurus/src/server/config.ts b/packages/docusaurus/src/server/config.ts index 88c14560fc63..6891ad0c3975 100644 --- a/packages/docusaurus/src/server/config.ts +++ b/packages/docusaurus/src/server/config.ts @@ -13,7 +13,11 @@ import {CONFIG_FILE_NAME} from '../constants'; import {validateConfig} from './configValidation'; export default function loadConfig(siteDir: string): DocusaurusConfig { - const configPath = path.resolve(siteDir, CONFIG_FILE_NAME); + // TODO temporary undocumented env variable: we should be able to use a cli option instead! + const loadedConfigFileName = + process.env.DOCUSAURUS_CONFIG || CONFIG_FILE_NAME; + + const configPath = path.resolve(siteDir, loadedConfigFileName); if (!fs.existsSync(configPath)) { throw new Error(`${CONFIG_FILE_NAME} not found`); diff --git a/packages/docusaurus/src/webpack/utils.ts b/packages/docusaurus/src/webpack/utils.ts index 0c1c15f39a29..a2988e6b3988 100644 --- a/packages/docusaurus/src/webpack/utils.ts +++ b/packages/docusaurus/src/webpack/utils.ts @@ -139,6 +139,31 @@ export function applyConfigureWebpack( return config; } +// See https://webpack.js.org/configuration/stats/#statswarningsfilter +// @slorber: note sure why we have to re-implement this logic +// just know that legacy had this only partially implemented, so completed it +type WarningFilter = string | RegExp | Function; +function filterWarnings( + warningsFilter: WarningFilter[], + warnings: string[], +): string[] { + function isWarningFiltered(warning: string): boolean { + return warningsFilter.some((warningFilter) => { + if (typeof warningFilter === 'string') { + return warning.includes(warningFilter); + } else if (warningFilter instanceof RegExp) { + return !!warning.match(warningFilter); + } else if (warningFilter instanceof Function) { + return warningFilter(warning); + } else { + throw new Error(`Unknown warningFilter type = ${typeof warningFilter}`); + } + }); + } + + return warnings.filter((warning) => !isWarningFiltered(warning)); +} + export function compile(config: Configuration[]): Promise { return new Promise((resolve, reject) => { const compiler = webpack(config); @@ -155,13 +180,12 @@ export function compile(config: Configuration[]): Promise { if (stats.hasWarnings()) { // Custom filtering warnings (see https://github.com/webpack/webpack/issues/7841). let {warnings} = stats.toJson('errors-warnings'); + const warningsFilter = ((config[0].stats as Stats.ToJsonOptionsObject) - ?.warningsFilter || []) as any[]; + ?.warningsFilter || []) as WarningFilter[]; if (Array.isArray(warningsFilter)) { - warnings = warnings.filter((warning) => - warningsFilter.every((str) => !warning.includes(str)), - ); + warnings = filterWarnings(warningsFilter, warnings); } warnings.forEach((warning) => { diff --git a/website/docusaurus.config-blog-only.js b/website/docusaurus.config-blog-only.js new file mode 100644 index 000000000000..dba0207c9eda --- /dev/null +++ b/website/docusaurus.config-blog-only.js @@ -0,0 +1,63 @@ +/** + * 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. + */ + +module.exports = { + title: 'Docusaurus blog only!', + tagline: 'Build optimized websites quickly, focus on your content', + organizationName: 'facebook', + projectName: 'docusaurus', + baseUrl: '/blog-only/', + url: 'https://v2.docusaurus.io', + onBrokenLinks: 'throw', + favicon: 'img/docusaurus.ico', + themes: ['@docusaurus/theme-live-codeblock'], + plugins: [], + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: false, + pages: false, + blog: { + routeBasePath: '/', + path: '../website-1.x/blog', + editUrl: + 'https://github.com/facebook/docusaurus/edit/master/website-1.x/', + postsPerPage: 3, + feedOptions: { + type: 'all', + copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`, + }, + }, + theme: { + customCss: require.resolve('./src/css/custom.css'), + }, + }, + ], + ], + themeConfig: { + image: 'img/docusaurus-soc.png', + navbar: { + hideOnScroll: true, + title: 'Docusaurus', + logo: { + alt: 'Docusaurus Logo', + src: 'img/docusaurus.svg', + srcDark: 'img/docusaurus_keytar.svg', + }, + }, + footer: { + style: 'dark', + logo: { + alt: 'Facebook Open Source Logo', + src: 'img/oss_logo.png', + href: 'https://opensource.facebook.com', + }, + copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc. Built with Docusaurus.`, + }, + }, +}; diff --git a/website/netlify.toml b/website/netlify.toml index ff54fb65fadb..66ad9d6706da 100644 --- a/website/netlify.toml +++ b/website/netlify.toml @@ -11,11 +11,12 @@ # permits to test that baseUrl works fine (this often breaks!) [context.deploy-preview] command = "yarn workspace docusaurus-2-website netlify:build:deployPreview" - publish = "website/netlifyDeploy" + publish = "website/netlifyDeployPreview" # TODO this does not seem to work - # workaroud: a _redirect file is created in website/netlifyDeploy + # workaroud: a _redirect file is created in npm/yarn scripts # can't we have context-based redirects with Netlify? :'( + [[context.deploy-preview.redirects]] from = "/classic/*" to = "/classic/404.html" @@ -24,6 +25,10 @@ from = "/bootstrap/*" to = "/bootstrap/404.html" status = 200 + [[context.deploy-preview.redirects]] + from = "/blog-only/*" + to = "/blog-only/404.html" + status = 200 [[context.deploy-preview.redirects]] from = "/*" to = "/classic/" diff --git a/website/netlifyDeployPreview/_redirects b/website/netlifyDeployPreview/_redirects new file mode 100644 index 000000000000..c197c7144889 --- /dev/null +++ b/website/netlifyDeployPreview/_redirects @@ -0,0 +1,4 @@ +/classic/* /classic/404.html 200 +/bootstrap/* /bootstrap/404.html 200 +/blog-only/* /blog-only/404.html 200 +/* /classic/ diff --git a/website/netlifyDeployPreview/index.html b/website/netlifyDeployPreview/index.html new file mode 100644 index 000000000000..9c00d2394875 --- /dev/null +++ b/website/netlifyDeployPreview/index.html @@ -0,0 +1,31 @@ + + + + +

+ Docusaurus deploy previews +

+
+

+ We deploy the Docusaurus site with various configurations. It helps us + find potential regressions. +

+

When in doubt, try the classic preview

+
+
+

Available deploy previews:

+
    +
  • + classic: the regular site +
  • +
  • + bootstrap: the regular site with the + bootstrap theme (WIP) +
  • +
  • + blog-only: the regular site in blog-only mode +
  • +
+
+ + diff --git a/website/package.json b/website/package.json index 018bdc092261..9c7982992286 100644 --- a/website/package.json +++ b/website/package.json @@ -12,11 +12,13 @@ "build:baseUrl": "BASE_URL='/build/' yarn build", "start:bootstrap": "DOCUSAURUS_PRESET=bootstrap yarn start", "build:bootstrap": "DOCUSAURUS_PRESET=bootstrap yarn build", + "start:blogOnly": "DOCUSAURUS_CONFIG='docusaurus.config-blog-only.js' yarn start", + "build:blogOnly": "DOCUSAURUS_CONFIG='docusaurus.config-blog-only.js' yarn build", "netlify:build:production": "yarn build", - "netlify:build:deployPreview": "yarn rimraf netlifyDeploy && yarn netlify:build:deployPreview:classic && yarn netlify:build:deployPreview:bootstrap && yarn netlify:build:deployPreview:redirects", - "netlify:build:deployPreview:classic": "BASE_URL='/classic/' yarn build --out-dir netlifyDeploy/classic", - "netlify:build:deployPreview:bootstrap": "BASE_URL='/bootstrap/' DOCUSAURUS_PRESET=bootstrap DISABLE_VERSIONING=true yarn build --out-dir netlifyDeploy/bootstrap", - "netlify:build:deployPreview:redirects": "echo 'Writing Netlify baseUrl deployPreview _redirects file' && echo '/classic/* /classic/404.html 200' >> netlifyDeploy/_redirects && echo '/bootstrap/* /bootstrap/404.html 200' >> netlifyDeploy/_redirects && echo '/* /classic/' >> netlifyDeploy/_redirects", + "netlify:build:deployPreview": "yarn netlify:build:deployPreview:classic && yarn netlify:build:deployPreview:bootstrap && yarn netlify:build:deployPreview:blogOnly", + "netlify:build:deployPreview:classic": "BASE_URL='/classic/' yarn build --out-dir netlifyDeployPreview/classic", + "netlify:build:deployPreview:bootstrap": "BASE_URL='/bootstrap/' DOCUSAURUS_PRESET=bootstrap DISABLE_VERSIONING=true yarn build --out-dir netlifyDeployPreview/bootstrap", + "netlify:build:deployPreview:blogOnly": "yarn build:blogOnly --out-dir netlifyDeployPreview/blog-only", "netlify:test": "yarn netlify:build:deployPreview && yarn netlify dev --debug" }, "dependencies": {