From a1dab35dd7782d936930148ed90e53943a2b82e8 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 13:14:04 +0800 Subject: [PATCH 01/16] Add dark/light style fields to config --- .../src/theme/Toggle/index.tsx | 20 ++++++++++++++----- .../src/theme/Toggle/styles.module.css | 4 ++-- website/docusaurus.config.js | 12 +++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx index a73e95e05551..44c38e53f839 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx @@ -13,17 +13,27 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import clsx from 'clsx'; import styles from './styles.module.css'; -const Moon = () => ; -const Sun = () => ; +const Dark = ({style}) => ( + +); +const Light = ({style}) => ( + +); export default function (props: ComponentProps): JSX.Element { - const {isClient} = useDocusaurusContext(); + const {isClient, siteConfig = {}} = useDocusaurusContext(); + + const { + themeConfig: { + switchConfig: {darkIconStyle, lightIconStyle}, + }, + } = siteConfig; return ( , - unchecked: , + checked: , + unchecked: , }} {...props} /> diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css b/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css index 42619f0251f6..603ac6380cb6 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css @@ -16,10 +16,10 @@ .toggle::before { position: absolute; } -.moon::before { +.dark::before { content: '\1F31C'; } -.sun::before { +.light::before { content: '\1F31E'; } diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 2a8b5ae15a99..4bf02be2bc79 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -147,6 +147,18 @@ module.exports = { defaultMode: 'light', disableSwitch: false, respectPrefersColorScheme: true, + switchConfig: { + darkIconStyle: ` + content: '\\1F319'; + margin-top: 1px; + margin-left: 2px; + `, + lightIconStyle: ` + content: '\\2600'; + color: #ffd557; + margin-left: 1px; + `, + }, }, announcementBar: { id: 'supportus', From c3d40086a9ff537822904f11b9f70463ffcd191a Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 13:14:40 +0800 Subject: [PATCH 02/16] Update yarn.lock --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index c26fa9797bfa..38de797416b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17578,7 +17578,7 @@ react-dev-utils@^9.1.0: strip-ansi "5.2.0" text-table "0.2.0" -react-dom@^16.10.2, react-dom@^16.8.4: +react-dom@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== @@ -17739,7 +17739,7 @@ react-waypoint@^9.0.2: prop-types "^15.0.0" react-is "^16.6.3" -react@^16.10.2, react@^16.8.4: +react@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== From 241d71b6152ad280098ed6447ac2af4c9a38d7d6 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 15:07:26 +0800 Subject: [PATCH 03/16] Remove css content --- .../src/theme/Toggle/styles.module.css | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css b/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css index 603ac6380cb6..1ac128ce8cf1 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/styles.module.css @@ -16,12 +16,6 @@ .toggle::before { position: absolute; } -.dark::before { - content: '\1F31C'; -} -.light::before { - content: '\1F31E'; -} /** * styles for React Toggle From 470c490813d150283485906072ff7b61c49be674 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 15:22:03 +0800 Subject: [PATCH 04/16] Add documentation --- website/docs/docusaurus.config.js.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/website/docs/docusaurus.config.js.md b/website/docs/docusaurus.config.js.md index e15c83d4d124..5ed55560bb9e 100644 --- a/website/docs/docusaurus.config.js.md +++ b/website/docs/docusaurus.config.js.md @@ -158,6 +158,21 @@ Example: ```js title="docusaurus.config.js" module.exports = { themeConfig: { + colorMode: { + defaultMode: 'light', + disableSwitch: false, + respectPrefersColorScheme: true, + switchConfig: { + darkIcon: '🌙', + darkIconStyle: { + marginLeft: '2px', + }, + lightIcon: '☀️', + lightIconStyle: { + marginLeft: '1px', + }, + }, + }, navbar: { title: 'Site Title', logo: { From ac125e7647bf030a94f53d05992dee1777647b3b Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 15:23:08 +0800 Subject: [PATCH 05/16] Add icon fields to toggle component --- .../src/theme/Toggle/index.tsx | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx index 44c38e53f839..582eba7b60f7 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx @@ -13,11 +13,15 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import clsx from 'clsx'; import styles from './styles.module.css'; -const Dark = ({style}) => ( - +const Dark = ({icon, style}) => ( + + {icon} + ); -const Light = ({style}) => ( - +const Light = ({icon, style}) => ( + + {icon} + ); export default function (props: ComponentProps): JSX.Element { @@ -25,15 +29,17 @@ export default function (props: ComponentProps): JSX.Element { const { themeConfig: { - switchConfig: {darkIconStyle, lightIconStyle}, + colorMode: { + switchConfig: {darkIcon, darkIconStyle, lightIcon, lightIconStyle}, + }, }, } = siteConfig; return ( , - unchecked: , + checked: , + unchecked: , }} {...props} /> From a150f0142c665c1ec9af394e747dce59b5ae320a Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 15:24:41 +0800 Subject: [PATCH 06/16] Add config validation fields --- .../docusaurus-theme-classic/src/themeConfigSchema.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/docusaurus-theme-classic/src/themeConfigSchema.js b/packages/docusaurus-theme-classic/src/themeConfigSchema.js index 38af74c70e0b..511a64b2f284 100644 --- a/packages/docusaurus-theme-classic/src/themeConfigSchema.js +++ b/packages/docusaurus-theme-classic/src/themeConfigSchema.js @@ -102,6 +102,15 @@ const ColorModeSchema = Joi.object({ defaultMode: Joi.string().equal('dark', 'light').default('light'), disableSwitch: Joi.bool().default(false), respectPrefersColorScheme: Joi.bool().default(false), + switchConfig: Joi.object({ + darkIcon: Joi.string().default('🌜'), + darkIconStyle: Joi.object(), + lightIcon: Joi.string().default('🌞'), + lightIconStyle: Joi.object(), + }).default({ + darkIcon: '🌜', + lightIcon: '🌞', + }), }).default({ defaultMode: 'light', disableSwitch: false, From c753320ff793f63cb8819b8abd623c383ed24a79 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 15:25:43 +0800 Subject: [PATCH 07/16] Remove changes from docusaurus.config --- website/docusaurus.config.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 4bf02be2bc79..2a8b5ae15a99 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -147,18 +147,6 @@ module.exports = { defaultMode: 'light', disableSwitch: false, respectPrefersColorScheme: true, - switchConfig: { - darkIconStyle: ` - content: '\\1F319'; - margin-top: 1px; - margin-left: 2px; - `, - lightIconStyle: ` - content: '\\2600'; - color: #ffd557; - margin-left: 1px; - `, - }, }, announcementBar: { id: 'supportus', From 4846ae11c4904eeec1cd6484eb7f1789d87d3837 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Mon, 27 Jul 2020 15:55:34 +0800 Subject: [PATCH 08/16] Add unicode documentation example --- website/docs/docusaurus.config.js.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/docusaurus.config.js.md b/website/docs/docusaurus.config.js.md index 5ed55560bb9e..9788f92458c2 100644 --- a/website/docs/docusaurus.config.js.md +++ b/website/docs/docusaurus.config.js.md @@ -167,7 +167,7 @@ module.exports = { darkIconStyle: { marginLeft: '2px', }, - lightIcon: '☀️', + lightIcon: '\u2600', lightIconStyle: { marginLeft: '1px', }, From fb9150c320627e26fb532dc8ec2e5e65b906034f Mon Sep 17 00:00:00 2001 From: Drewbi Date: Tue, 28 Jul 2020 15:58:28 +0800 Subject: [PATCH 09/16] Fix default values --- .../docusaurus-theme-classic/src/theme/Toggle/index.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx index 582eba7b60f7..12656b94c6c1 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx @@ -30,8 +30,13 @@ export default function (props: ComponentProps): JSX.Element { const { themeConfig: { colorMode: { - switchConfig: {darkIcon, darkIconStyle, lightIcon, lightIconStyle}, - }, + switchConfig: { + darkIcon = '🌜', + darkIconStyle = {}, + lightIcon = '🌞', + lightIconStyle = {}, + } = {}, + } = {}, }, } = siteConfig; return ( From 94a91c34ad69842445eb7204e89164421158e8d1 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Wed, 29 Jul 2020 11:13:57 +0800 Subject: [PATCH 10/16] Add color mode config default --- .../src/theme/Toggle/index.tsx | 22 +++++--- .../src/themeConfigSchema.js | 50 +++++++++++++------ 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx index 12656b94c6c1..8f3026f34afb 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx @@ -13,6 +13,8 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import clsx from 'clsx'; import styles from './styles.module.css'; +import {DEFAULT_COLOR_MODE_CONFIG} from '../../themeConfigSchema.js'; + const Dark = ({icon, style}) => ( {icon} @@ -27,16 +29,24 @@ const Light = ({icon, style}) => ( export default function (props: ComponentProps): JSX.Element { const {isClient, siteConfig = {}} = useDocusaurusContext(); + const { + switchConfig: { + darkIcon: defaultDarkIcon, + darkIconStyle: defaultDarkIconStyle, + lightIcon: defaultLightIcon, + lightIconStyle: defaultLightIconStyle, + }, + } = DEFAULT_COLOR_MODE_CONFIG; const { themeConfig: { colorMode: { switchConfig: { - darkIcon = '🌜', - darkIconStyle = {}, - lightIcon = '🌞', - lightIconStyle = {}, - } = {}, - } = {}, + darkIcon = defaultDarkIcon, + darkIconStyle = defaultDarkIconStyle, + lightIcon = defaultLightIcon, + lightIconStyle = defaultLightIconStyle, + } = DEFAULT_COLOR_MODE_CONFIG.switchConfig, + } = DEFAULT_COLOR_MODE_CONFIG, }, } = siteConfig; return ( diff --git a/packages/docusaurus-theme-classic/src/themeConfigSchema.js b/packages/docusaurus-theme-classic/src/themeConfigSchema.js index cf35d7c3db56..db6d65117874 100644 --- a/packages/docusaurus-theme-classic/src/themeConfigSchema.js +++ b/packages/docusaurus-theme-classic/src/themeConfigSchema.js @@ -7,6 +7,19 @@ const Joi = require('@hapi/joi'); +const DEFAULT_COLOR_MODE_CONFIG = { + defaultMode: 'light', + disableSwitch: false, + respectPrefersColorScheme: false, + switchConfig: { + darkIcon: '🌜', + darkIconStyle: {}, + lightIcon: '🌞', + lightIconStyle: {}, + }, +}; +exports.DEFAULT_COLOR_MODE_CONFIG = DEFAULT_COLOR_MODE_CONFIG; + const NavbarItemPosition = Joi.string().equal('left', 'right').default('left'); // TODO we should probably create a custom navbar item type "dropdown" @@ -99,23 +112,28 @@ const NavbarItemSchema = Joi.object().when('type', { */ const ColorModeSchema = Joi.object({ - defaultMode: Joi.string().equal('dark', 'light').default('light'), - disableSwitch: Joi.bool().default(false), - respectPrefersColorScheme: Joi.bool().default(false), + defaultMode: Joi.string() + .equal('dark', 'light') + .default(DEFAULT_COLOR_MODE_CONFIG.defaultMode), + disableSwitch: Joi.bool().default(DEFAULT_COLOR_MODE_CONFIG.disableSwitch), + respectPrefersColorScheme: Joi.bool().default( + DEFAULT_COLOR_MODE_CONFIG.respectPrefersColorScheme, + ), switchConfig: Joi.object({ - darkIcon: Joi.string().default('🌜'), - darkIconStyle: Joi.object(), - lightIcon: Joi.string().default('🌞'), - lightIconStyle: Joi.object(), - }).default({ - darkIcon: '🌜', - lightIcon: '🌞', - }), -}).default({ - defaultMode: 'light', - disableSwitch: false, - respectPrefersColorScheme: false, -}); + darkIcon: Joi.string().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.darkIcon, + ), + darkIconStyle: Joi.object().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.darkIconStyle, + ), + lightIcon: Joi.string().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.lightIcon, + ), + lightIconStyle: Joi.object().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.lightIconStyle, + ), + }).default(DEFAULT_COLOR_MODE_CONFIG.switchConfig), +}).default(DEFAULT_COLOR_MODE_CONFIG); const ThemeConfigSchema = Joi.object({ // TODO temporary (@alpha-58) From a4537534074462bcff8890dd2e4311a52ecfbf7c Mon Sep 17 00:00:00 2001 From: Drewbi Date: Thu, 30 Jul 2020 17:24:58 +0800 Subject: [PATCH 11/16] Add lodash to theme-classic --- packages/docusaurus-theme-classic/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 4c081d6e2531..6addc19fd648 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -20,6 +20,7 @@ "clsx": "^1.1.1", "copy-text-to-clipboard": "^2.2.0", "infima": "0.2.0-alpha.12", + "lodash": "^4.17.19", "parse-numeric-range": "^0.0.2", "prism-react-renderer": "^1.1.0", "prismjs": "^1.20.0", From 44c4d6760a354b3c1c4e7f790ef7913b42efc692 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Thu, 30 Jul 2020 17:25:34 +0800 Subject: [PATCH 12/16] Change themeConfigSchema name to match other packages --- .../docusaurus-theme-classic/src/index.js | 6 +- .../src/themeConfigSchema.js | 202 ------------------ 2 files changed, 2 insertions(+), 206 deletions(-) delete mode 100644 packages/docusaurus-theme-classic/src/themeConfigSchema.js diff --git a/packages/docusaurus-theme-classic/src/index.js b/packages/docusaurus-theme-classic/src/index.js index cff72869155f..8d0653830b34 100644 --- a/packages/docusaurus-theme-classic/src/index.js +++ b/packages/docusaurus-theme-classic/src/index.js @@ -7,7 +7,7 @@ const path = require('path'); const Module = require('module'); -const ThemeConfigSchema = require('./themeConfigSchema'); +const {validateThemeConfig} = require('./validateThemeConfig'); const createRequire = Module.createRequire || Module.createRequireFromPath; const requireFromDocusaurusCore = createRequire( @@ -120,6 +120,4 @@ module.exports = function (context, options) { }; }; -module.exports.validateThemeConfig = ({validate, themeConfig}) => { - return validate(ThemeConfigSchema, themeConfig); -}; +module.exports.validateThemeConfig = validateThemeConfig; diff --git a/packages/docusaurus-theme-classic/src/themeConfigSchema.js b/packages/docusaurus-theme-classic/src/themeConfigSchema.js deleted file mode 100644 index db6d65117874..000000000000 --- a/packages/docusaurus-theme-classic/src/themeConfigSchema.js +++ /dev/null @@ -1,202 +0,0 @@ -/** - * 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. - */ - -const Joi = require('@hapi/joi'); - -const DEFAULT_COLOR_MODE_CONFIG = { - defaultMode: 'light', - disableSwitch: false, - respectPrefersColorScheme: false, - switchConfig: { - darkIcon: '🌜', - darkIconStyle: {}, - lightIcon: '🌞', - lightIconStyle: {}, - }, -}; -exports.DEFAULT_COLOR_MODE_CONFIG = DEFAULT_COLOR_MODE_CONFIG; - -const NavbarItemPosition = Joi.string().equal('left', 'right').default('left'); - -// TODO we should probably create a custom navbar item type "dropdown" -// having this recursive structure is bad because we only support 2 levels -// + parent/child don't have exactly the same props -const DefaultNavbarItemSchema = Joi.object({ - items: Joi.array().optional().items(Joi.link('...')), - to: Joi.string(), - href: Joi.string().uri(), - label: Joi.string(), - position: NavbarItemPosition, - activeBasePath: Joi.string(), - activeBaseRegex: Joi.string(), - className: Joi.string(), - 'aria-label': Joi.string(), -}); -// TODO the dropdown parent item can have no href/to -// should check should not apply to dropdown parent item -// .xor('href', 'to'); - -const DocsVersionNavbarItemSchema = Joi.object({ - type: Joi.string().equal('docsVersion').required(), - position: NavbarItemPosition, - label: Joi.string(), - to: Joi.string(), - docsPluginId: Joi.string(), - nextVersionLabel: Joi.string().default('Next'), -}); - -const DocsVersionDropdownNavbarItemSchema = Joi.object({ - type: Joi.string().equal('docsVersionDropdown').required(), - position: NavbarItemPosition, - docsPluginId: Joi.string(), - nextVersionLabel: Joi.string().default('Next'), -}); - -// Can this be made easier? :/ -const isOfType = (type) => { - let typeSchema = Joi.string().required(); - // because equal(undefined) is not supported :/ - if (type) { - typeSchema = typeSchema.equal(type); - } - return Joi.object({ - type: typeSchema, - }) - .unknown() - .required(); -}; - -const NavbarItemSchema = Joi.object().when({ - switch: [ - { - is: isOfType('docsVersion'), - then: DocsVersionNavbarItemSchema, - }, - { - is: isOfType('docsVersionDropdown'), - then: DocsVersionDropdownNavbarItemSchema, - }, - { - is: isOfType(undefined), - then: Joi.forbidden().messages({ - 'any.unknown': 'Bad nav item type {.type}', - }), - }, - ], - otherwise: DefaultNavbarItemSchema, -}); - -/* -const NavbarItemSchema = Joi.object({ - type: Joi.string().only(['docsVersion']) -}) - .when(Joi.object({ type: 'docsVersion' }).unknown(), { - then: Joi.object({ pepperoni: Joi.boolean() }) - }) - .when(Joi.object().unknown(), { - then: Joi.object({ croutons: Joi.boolean() }) - }) - - */ - -/* -const NavbarItemSchema = Joi.object().when('type', { - is: Joi.valid('docsVersion'), - then: DocsVersionNavbarItemSchema, - otherwise: DefaultNavbarItemSchema, -}); - */ - -const ColorModeSchema = Joi.object({ - defaultMode: Joi.string() - .equal('dark', 'light') - .default(DEFAULT_COLOR_MODE_CONFIG.defaultMode), - disableSwitch: Joi.bool().default(DEFAULT_COLOR_MODE_CONFIG.disableSwitch), - respectPrefersColorScheme: Joi.bool().default( - DEFAULT_COLOR_MODE_CONFIG.respectPrefersColorScheme, - ), - switchConfig: Joi.object({ - darkIcon: Joi.string().default( - DEFAULT_COLOR_MODE_CONFIG.switchConfig.darkIcon, - ), - darkIconStyle: Joi.object().default( - DEFAULT_COLOR_MODE_CONFIG.switchConfig.darkIconStyle, - ), - lightIcon: Joi.string().default( - DEFAULT_COLOR_MODE_CONFIG.switchConfig.lightIcon, - ), - lightIconStyle: Joi.object().default( - DEFAULT_COLOR_MODE_CONFIG.switchConfig.lightIconStyle, - ), - }).default(DEFAULT_COLOR_MODE_CONFIG.switchConfig), -}).default(DEFAULT_COLOR_MODE_CONFIG); - -const ThemeConfigSchema = Joi.object({ - // TODO temporary (@alpha-58) - disableDarkMode: Joi.any().forbidden(false).messages({ - 'any.unknown': - 'disableDarkMode theme config is deprecated. Please use the new colorMode attribute. You likely want: config.themeConfig.colorMode.disableSwitch = true', - }), - // TODO temporary (@alpha-58) - defaultDarkMode: Joi.any().forbidden(false).messages({ - 'any.unknown': - 'defaultDarkMode theme config is deprecated. Please use the new colorMode attribute. You likely want: config.themeConfig.colorMode.defaultMode = "dark"', - }), - colorMode: ColorModeSchema, - image: Joi.string(), - announcementBar: Joi.object({ - id: Joi.string(), - content: Joi.string(), - backgroundColor: Joi.string().default('#fff'), - textColor: Joi.string().default('#000'), - }).optional(), - navbar: Joi.object({ - hideOnScroll: Joi.bool().default(false), - // TODO temporary (@alpha-58) - links: Joi.any().forbidden().messages({ - 'any.unknown': - 'themeConfig.navbar.links has been renamed as themeConfig.navbar.items', - }), - items: Joi.array().items(NavbarItemSchema), - title: Joi.string().allow('', null), - logo: Joi.object({ - alt: Joi.string(), - src: Joi.string().required(), - srcDark: Joi.string(), - href: Joi.string(), - target: Joi.string(), - }), - }), - footer: Joi.object({ - style: Joi.string().equal('dark', 'light').default('light'), - logo: Joi.object({ - alt: Joi.string(), - src: Joi.string(), - href: Joi.string(), - }), - copyright: Joi.string(), - links: Joi.array().items( - Joi.object({ - title: Joi.string().required(), - items: Joi.array().items( - Joi.object({ - to: Joi.string(), - href: Joi.string().uri(), - html: Joi.string(), - label: Joi.string(), - }) - .xor('to', 'href', 'html') - .with('to', 'label') - .with('href', 'label') - .nand('html', 'label'), - ), - }), - ), - }), -}); - -module.exports = ThemeConfigSchema; From d876a85fc24c4c17039a0ddb493be7dc6fb2c4b9 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Thu, 30 Jul 2020 17:26:09 +0800 Subject: [PATCH 13/16] Add themeConfig color-mode tests --- .../src/__tests__/validateThemeConfig.test.js | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js diff --git a/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js new file mode 100644 index 000000000000..7d95ad098915 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js @@ -0,0 +1,83 @@ +/** + * 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. + */ +const { + validateThemeConfig, + DEFAULT_COLOR_MODE_CONFIG, + mergeDefault, +} = require('../validateThemeConfig'); + +function testValidateThemeConfig(themeConfig) { + function validate(schema, cfg) { + const {value, error} = schema.validate(cfg, { + convert: false, + }); + if (error) { + throw error; + } + return value; + } + + return validateThemeConfig({themeConfig, validate}); +} + +describe('color mode config', () => { + test('minimal config', () => { + const colorMode = { + switchConfig: { + darkIcon: '🌙', + }, + }; + expect(testValidateThemeConfig({colorMode})).toEqual({ + colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + }); + }); + + test('max config', () => { + const colorMode = { + defaultMode: 'dark', + disableSwitch: false, + respectPrefersColorScheme: true, + switchConfig: { + darkIcon: '🌙', + darkIconStyle: { + marginTop: '1px', + marginLeft: '2px', + }, + lightIcon: '☀️', + lightIconStyle: { + marginLeft: '1px', + }, + }, + }; + expect(testValidateThemeConfig({colorMode})).toEqual({ + colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + }); + }); + + test('undefined config', () => { + const colorMode = undefined; + expect(testValidateThemeConfig({colorMode})).toEqual({ + colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + }); + }); + + test('empty config', () => { + const colorMode = {}; + expect(testValidateThemeConfig({colorMode})).toEqual({ + colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + }); + }); + + test('empty switch config', () => { + const colorMode = { + switchConfig: {}, + }; + expect(testValidateThemeConfig({colorMode})).toEqual({ + colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + }); + }); +}); From 95214df8739d289021f704fd6da775951c02c31a Mon Sep 17 00:00:00 2001 From: Drewbi Date: Thu, 30 Jul 2020 17:26:22 +0800 Subject: [PATCH 14/16] Add default config merge function --- .../src/theme/Toggle/index.tsx | 31 ++- .../src/validateThemeConfig.js | 209 ++++++++++++++++++ 2 files changed, 222 insertions(+), 18 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/validateThemeConfig.js diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx index 8f3026f34afb..b535c559dfc4 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx @@ -13,7 +13,10 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import clsx from 'clsx'; import styles from './styles.module.css'; -import {DEFAULT_COLOR_MODE_CONFIG} from '../../themeConfigSchema.js'; +import { + DEFAULT_COLOR_MODE_CONFIG, + mergeDefault +} from '../../validateThemeConfig'; const Dark = ({icon, style}) => ( @@ -28,27 +31,19 @@ const Light = ({icon, style}) => ( export default function (props: ComponentProps): JSX.Element { const {isClient, siteConfig = {}} = useDocusaurusContext(); - - const { - switchConfig: { - darkIcon: defaultDarkIcon, - darkIconStyle: defaultDarkIconStyle, - lightIcon: defaultLightIcon, - lightIconStyle: defaultLightIconStyle, - }, - } = DEFAULT_COLOR_MODE_CONFIG; const { themeConfig: { - colorMode: { - switchConfig: { - darkIcon = defaultDarkIcon, - darkIconStyle = defaultDarkIconStyle, - lightIcon = defaultLightIcon, - lightIconStyle = defaultLightIconStyle, - } = DEFAULT_COLOR_MODE_CONFIG.switchConfig, - } = DEFAULT_COLOR_MODE_CONFIG, + colorMode }, } = siteConfig; + + const { switchConfig: { + darkIcon, + darkIconStyle, + lightIcon, + lightIconStyle + } } = mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG) + return ( { + return merge({}, defaultConfig, config); +}; + +const NavbarItemPosition = Joi.string().equal('left', 'right').default('left'); + +// TODO we should probably create a custom navbar item type "dropdown" +// having this recursive structure is bad because we only support 2 levels +// + parent/child don't have exactly the same props +const DefaultNavbarItemSchema = Joi.object({ + items: Joi.array().optional().items(Joi.link('...')), + to: Joi.string(), + href: Joi.string().uri(), + label: Joi.string(), + position: NavbarItemPosition, + activeBasePath: Joi.string(), + activeBaseRegex: Joi.string(), + className: Joi.string(), + 'aria-label': Joi.string(), +}); +// TODO the dropdown parent item can have no href/to +// should check should not apply to dropdown parent item +// .xor('href', 'to'); + +const DocsVersionNavbarItemSchema = Joi.object({ + type: Joi.string().equal('docsVersion').required(), + position: NavbarItemPosition, + label: Joi.string(), + to: Joi.string(), + docsPluginId: Joi.string(), + nextVersionLabel: Joi.string().default('Next'), +}); + +const DocsVersionDropdownNavbarItemSchema = Joi.object({ + type: Joi.string().equal('docsVersionDropdown').required(), + position: NavbarItemPosition, + docsPluginId: Joi.string(), + nextVersionLabel: Joi.string().default('Next'), +}); + +// Can this be made easier? :/ +const isOfType = (type) => { + let typeSchema = Joi.string().required(); + // because equal(undefined) is not supported :/ + if (type) { + typeSchema = typeSchema.equal(type); + } + return Joi.object({ + type: typeSchema, + }) + .unknown() + .required(); +}; + +const NavbarItemSchema = Joi.object().when({ + switch: [ + { + is: isOfType('docsVersion'), + then: DocsVersionNavbarItemSchema, + }, + { + is: isOfType('docsVersionDropdown'), + then: DocsVersionDropdownNavbarItemSchema, + }, + { + is: isOfType(undefined), + then: Joi.forbidden().messages({ + 'any.unknown': 'Bad nav item type {.type}', + }), + }, + ], + otherwise: DefaultNavbarItemSchema, +}); + +/* +const NavbarItemSchema = Joi.object({ + type: Joi.string().only(['docsVersion']) +}) + .when(Joi.object({ type: 'docsVersion' }).unknown(), { + then: Joi.object({ pepperoni: Joi.boolean() }) + }) + .when(Joi.object().unknown(), { + then: Joi.object({ croutons: Joi.boolean() }) + }) + + */ + +/* +const NavbarItemSchema = Joi.object().when('type', { + is: Joi.valid('docsVersion'), + then: DocsVersionNavbarItemSchema, + otherwise: DefaultNavbarItemSchema, +}); + */ + +const ColorModeSchema = Joi.object({ + defaultMode: Joi.string() + .equal('dark', 'light') + .default(DEFAULT_COLOR_MODE_CONFIG.defaultMode), + disableSwitch: Joi.bool().default(DEFAULT_COLOR_MODE_CONFIG.disableSwitch), + respectPrefersColorScheme: Joi.bool().default( + DEFAULT_COLOR_MODE_CONFIG.respectPrefersColorScheme, + ), + switchConfig: Joi.object({ + darkIcon: Joi.string().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.darkIcon, + ), + darkIconStyle: Joi.object().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.darkIconStyle, + ), + lightIcon: Joi.string().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.lightIcon, + ), + lightIconStyle: Joi.object().default( + DEFAULT_COLOR_MODE_CONFIG.switchConfig.lightIconStyle, + ), + }).default(DEFAULT_COLOR_MODE_CONFIG.switchConfig), +}).default(DEFAULT_COLOR_MODE_CONFIG); + +const ThemeConfigSchema = Joi.object({ + // TODO temporary (@alpha-58) + disableDarkMode: Joi.any().forbidden(false).messages({ + 'any.unknown': + 'disableDarkMode theme config is deprecated. Please use the new colorMode attribute. You likely want: config.themeConfig.colorMode.disableSwitch = true', + }), + // TODO temporary (@alpha-58) + defaultDarkMode: Joi.any().forbidden(false).messages({ + 'any.unknown': + 'defaultDarkMode theme config is deprecated. Please use the new colorMode attribute. You likely want: config.themeConfig.colorMode.defaultMode = "dark"', + }), + colorMode: ColorModeSchema, + image: Joi.string(), + announcementBar: Joi.object({ + id: Joi.string(), + content: Joi.string(), + backgroundColor: Joi.string().default('#fff'), + textColor: Joi.string().default('#000'), + }).optional(), + navbar: Joi.object({ + hideOnScroll: Joi.bool().default(false), + // TODO temporary (@alpha-58) + links: Joi.any().forbidden().messages({ + 'any.unknown': + 'themeConfig.navbar.links has been renamed as themeConfig.navbar.items', + }), + items: Joi.array().items(NavbarItemSchema), + title: Joi.string().allow('', null), + logo: Joi.object({ + alt: Joi.string(), + src: Joi.string().required(), + srcDark: Joi.string(), + href: Joi.string(), + target: Joi.string(), + }), + }), + footer: Joi.object({ + style: Joi.string().equal('dark', 'light').default('light'), + logo: Joi.object({ + alt: Joi.string(), + src: Joi.string(), + href: Joi.string(), + }), + copyright: Joi.string(), + links: Joi.array().items( + Joi.object({ + title: Joi.string().required(), + items: Joi.array().items( + Joi.object({ + to: Joi.string(), + href: Joi.string().uri(), + html: Joi.string(), + label: Joi.string(), + }) + .xor('to', 'href', 'html') + .with('to', 'label') + .with('href', 'label') + .nand('html', 'label'), + ), + }), + ), + }), +}); + +exports.validateThemeConfig = ({validate, themeConfig}) => { + return validate(ThemeConfigSchema, themeConfig); +}; From 51a129e72eeaa5e0ca503c637a4069fac0470aa5 Mon Sep 17 00:00:00 2001 From: Drewbi Date: Thu, 30 Jul 2020 23:54:16 +0800 Subject: [PATCH 15/16] Remove unneeded object merging --- .../src/__tests__/validateThemeConfig.test.js | 15 +++++---- .../src/theme/Toggle/index.tsx | 31 +++++++++---------- .../src/validateThemeConfig.js | 5 --- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js index 7d95ad098915..44531fe179c9 100644 --- a/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js +++ b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.js @@ -4,12 +4,15 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ +import merge from 'lodash/merge'; + const { validateThemeConfig, DEFAULT_COLOR_MODE_CONFIG, - mergeDefault, } = require('../validateThemeConfig'); +const mergeDefault = (config) => merge({}, DEFAULT_COLOR_MODE_CONFIG, config); + function testValidateThemeConfig(themeConfig) { function validate(schema, cfg) { const {value, error} = schema.validate(cfg, { @@ -32,7 +35,7 @@ describe('color mode config', () => { }, }; expect(testValidateThemeConfig({colorMode})).toEqual({ - colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + colorMode: mergeDefault(colorMode), }); }); @@ -54,21 +57,21 @@ describe('color mode config', () => { }, }; expect(testValidateThemeConfig({colorMode})).toEqual({ - colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + colorMode: mergeDefault(colorMode), }); }); test('undefined config', () => { const colorMode = undefined; expect(testValidateThemeConfig({colorMode})).toEqual({ - colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + colorMode: mergeDefault(colorMode), }); }); test('empty config', () => { const colorMode = {}; expect(testValidateThemeConfig({colorMode})).toEqual({ - colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + colorMode: mergeDefault(colorMode), }); }); @@ -77,7 +80,7 @@ describe('color mode config', () => { switchConfig: {}, }; expect(testValidateThemeConfig({colorMode})).toEqual({ - colorMode: mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG), + colorMode: mergeDefault(colorMode), }); }); }); diff --git a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx index b535c559dfc4..3ab914e4a242 100644 --- a/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Toggle/index.tsx @@ -13,11 +13,6 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import clsx from 'clsx'; import styles from './styles.module.css'; -import { - DEFAULT_COLOR_MODE_CONFIG, - mergeDefault -} from '../../validateThemeConfig'; - const Dark = ({icon, style}) => ( {icon} @@ -30,19 +25,21 @@ const Light = ({icon, style}) => ( ); export default function (props: ComponentProps): JSX.Element { - const {isClient, siteConfig = {}} = useDocusaurusContext(); const { - themeConfig: { - colorMode - }, - } = siteConfig; - - const { switchConfig: { - darkIcon, - darkIconStyle, - lightIcon, - lightIconStyle - } } = mergeDefault(colorMode, DEFAULT_COLOR_MODE_CONFIG) + siteConfig: { + themeConfig: { + colorMode: { + switchConfig: { + darkIcon, + darkIconStyle, + lightIcon, + lightIconStyle, + }, + }, + }, + }, + isClient + } = useDocusaurusContext(); return ( { - return merge({}, defaultConfig, config); -}; - const NavbarItemPosition = Joi.string().equal('left', 'right').default('left'); // TODO we should probably create a custom navbar item type "dropdown" From d804f8a5237aff81587cab99ed9ebc1d2f2a21dc Mon Sep 17 00:00:00 2001 From: Drewbi Date: Thu, 30 Jul 2020 23:54:25 +0800 Subject: [PATCH 16/16] Add more documentation --- website/docs/docusaurus.config.js.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/docusaurus.config.js.md b/website/docs/docusaurus.config.js.md index 9788f92458c2..20a0914c822a 100644 --- a/website/docs/docusaurus.config.js.md +++ b/website/docs/docusaurus.config.js.md @@ -164,7 +164,8 @@ module.exports = { respectPrefersColorScheme: true, switchConfig: { darkIcon: '🌙', - darkIconStyle: { + darkIconStyle: { // Style object passed to inline CSS + // For more information about styling options visit: https://reactjs.org/docs/dom-elements.html#style marginLeft: '2px', }, lightIcon: '\u2600',