From 84f404039f5d379267a8979cddc7396ce0c473fe Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Wed, 25 Mar 2020 02:16:40 +0300 Subject: [PATCH] feat(v2): add @theme-init alias to give access to initial components --- .../src/theme/CodeBlock/index.js | 8 +- .../src/theme/hooks/usePrismTheme.js | 26 +++ .../src/theme/CodeBlock/index.js | 155 +++--------------- .../src/theme/CodeBlock/styles.module.css | 45 ----- .../src/theme/Playground/index.js | 2 +- .../src/server/themes/__tests__/index.ts | 1 + .../docusaurus/src/server/themes/index.ts | 5 + 7 files changed, 57 insertions(+), 185 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/hooks/usePrismTheme.js delete mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/styles.module.css diff --git a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.js b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.js index 4921105531aa..339e19719b0c 100644 --- a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.js +++ b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.js @@ -8,11 +8,10 @@ import React, {useEffect, useState, useRef} from 'react'; import classnames from 'classnames'; import Highlight, {defaultProps} from 'prism-react-renderer'; -import defaultTheme from 'prism-react-renderer/themes/palenight'; import Clipboard from 'clipboard'; import rangeParser from 'parse-numeric-range'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import useThemeContext from '@theme/hooks/useThemeContext'; +import usePrismTheme from '@theme/hooks/usePrismTheme'; import styles from './styles.module.css'; @@ -42,10 +41,7 @@ export default ({children, className: languageClassName, metastring}) => { const button = useRef(null); let highlightLines = []; - const {isDarkTheme} = useThemeContext(); - const lightModeTheme = prism.theme || defaultTheme; - const darkModeTheme = prism.darkTheme || lightModeTheme; - const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme; + const prismTheme = usePrismTheme(); if (metastring && highlightLinesRangeRegex.test(metastring)) { const highlightLinesRange = metastring.match(highlightLinesRangeRegex)[1]; diff --git a/packages/docusaurus-theme-classic/src/theme/hooks/usePrismTheme.js b/packages/docusaurus-theme-classic/src/theme/hooks/usePrismTheme.js new file mode 100644 index 000000000000..bc3b28f6f3b9 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/hooks/usePrismTheme.js @@ -0,0 +1,26 @@ +/** + * 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 defaultTheme from 'prism-react-renderer/themes/palenight'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import useThemeContext from '@theme/hooks/useThemeContext'; + +const usePrismTheme = () => { + const { + siteConfig: { + themeConfig: {prism = {}}, + }, + } = useDocusaurusContext(); + const {isDarkTheme} = useThemeContext(); + const lightModeTheme = prism.theme || defaultTheme; + const darkModeTheme = prism.darkTheme || lightModeTheme; + const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme; + + return prismTheme; +}; + +export default usePrismTheme; diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.js b/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.js index 776a6141ff05..386161784877 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.js +++ b/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.js @@ -5,143 +5,32 @@ * LICENSE file in the root directory of this source tree. */ -import React, {useEffect, useState, useRef} from 'react'; -import classnames from 'classnames'; -import Highlight, {defaultProps} from 'prism-react-renderer'; -import defaultTheme from 'prism-react-renderer/themes/palenight'; -import Clipboard from 'clipboard'; -import rangeParser from 'parse-numeric-range'; +import React from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import useThemeContext from '@theme/hooks/useThemeContext'; +import usePrismTheme from '@theme/hooks/usePrismTheme'; import Playground from '@theme/Playground'; - -import styles from './styles.module.css'; - -const highlightLinesRangeRegex = /{([\d,-]+)}/; - -export default ({ - children, - className: languageClassName, - live, - metastring, - ...props -}) => { - const { - siteConfig: { - themeConfig: {prism = {}}, - }, - } = useDocusaurusContext(); - - const [showCopied, setShowCopied] = useState(false); - const [mounted, setMounted] = useState(false); - // The Prism theme on SSR is always the default theme but the site theme - // can be in a different mode. React hydration doesn't update DOM styles - // that come from SSR. Hence force a re-render after mounting to apply the - // current relevant styles. There will be a flash seen of the original - // styles seen using this current approach but that's probably ok. Fixing - // the flash will require changing the theming approach and is not worth it - // at this point. - useEffect(() => { - setMounted(true); - }, []); - - const target = useRef(null); - const button = useRef(null); - let highlightLines = []; - - const {isDarkTheme} = useThemeContext(); - const lightModeTheme = prism.theme || defaultTheme; - const darkModeTheme = prism.darkTheme || lightModeTheme; - const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme; - - if (metastring && highlightLinesRangeRegex.test(metastring)) { - const highlightLinesRange = metastring.match(highlightLinesRangeRegex)[1]; - highlightLines = rangeParser.parse(highlightLinesRange).filter(n => n > 0); - } - - useEffect(() => { - let clipboard; - - if (button.current) { - clipboard = new Clipboard(button.current, { - target: () => target.current, - }); +import CodeBlock from '@theme-init/CodeBlock'; + +const withLiveEditor = Component => { + const WrappedComponent = props => { + const {isClient} = useDocusaurusContext(); + const prismTheme = usePrismTheme(); + + if (props.live) { + return ( + + ); } - return () => { - if (clipboard) { - clipboard.destroy(); - } - }; - }, [button.current, target.current]); - - if (live) { - return ( - - ); - } - - let language = - languageClassName && languageClassName.replace(/language-/, ''); - - if (!language && prism.defaultLanguage) { - language = prism.defaultLanguage; - } - - const handleCopyCode = () => { - window.getSelection().empty(); - setShowCopied(true); - - setTimeout(() => setShowCopied(false), 2000); + return ; }; - return ( - - {({className, style, tokens, getLineProps, getTokenProps}) => ( -
-          
-
-          
- {tokens.map((line, i) => { - if (line.length === 1 && line[0].content === '') { - line[0].content = '\n'; // eslint-disable-line no-param-reassign - } - - const lineProps = getLineProps({line, key: i}); - - if (highlightLines.includes(i + 1)) { - lineProps.className = `${lineProps.className} docusaurus-highlight-code-line`; - } - - return ( -
- {line.map((token, key) => ( - - ))} -
- ); - })} -
-
- )} -
- ); + return WrappedComponent; }; + +export default withLiveEditor(CodeBlock); diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/styles.module.css b/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/styles.module.css deleted file mode 100644 index 27ad74c05079..000000000000 --- a/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/styles.module.css +++ /dev/null @@ -1,45 +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. - */ - -.codeBlock { - overflow: auto; - display: block; - padding: 0; - margin: 0; -} - -.copyButton { - background: rgb(1, 22, 39); - border: 1px solid rgb(214, 222, 235); - border-radius: var(--ifm-global-radius); - color: rgb(214, 222, 235); - cursor: pointer; - line-height: 12px; - opacity: 0; - outline: none; - padding: 4px 8px; - position: absolute; - right: var(--ifm-pre-padding); - top: var(--ifm-pre-padding); - visibility: hidden; - transition: opacity 200ms ease-in-out, visibility 200ms ease-in-out, - bottom 200ms ease-in-out; -} - -.codeBlock:hover > .copyButton { - visibility: visible; - opacity: 1; -} - -.codeBlockLines { - background-color: transparent; - border-radius: 0; - margin-bottom: 0; - float: left; - min-width: 100%; - padding: var(--ifm-pre-padding); -} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js index 7ad4f2dcff48..e426bc981462 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js @@ -14,7 +14,7 @@ import styles from './styles.module.css'; function Playground({children, theme, transformCode, ...props}) { return ( `${code};`)} theme={theme} {...props}> diff --git a/packages/docusaurus/src/server/themes/__tests__/index.ts b/packages/docusaurus/src/server/themes/__tests__/index.ts index 40032cc5abf2..68f8eed25641 100644 --- a/packages/docusaurus/src/server/themes/__tests__/index.ts +++ b/packages/docusaurus/src/server/themes/__tests__/index.ts @@ -16,6 +16,7 @@ describe('loadThemeAlias', () => { const alias = loadThemeAlias([theme1Path, theme2Path]); expect(alias).toEqual({ + '@theme-init/Layout': path.join(theme1Path, 'Layout.js'), // TODO: Write separate test case for this? '@theme/Footer': path.join(theme1Path, 'Footer/index.js'), '@theme-original/Footer': path.join(theme1Path, 'Footer/index.js'), '@theme/Navbar': path.join(theme2Path, 'Navbar.js'), diff --git a/packages/docusaurus/src/server/themes/index.ts b/packages/docusaurus/src/server/themes/index.ts index fb2da680e0f8..7a488c9498a3 100644 --- a/packages/docusaurus/src/server/themes/index.ts +++ b/packages/docusaurus/src/server/themes/index.ts @@ -17,6 +17,11 @@ export function loadThemeAlias( themePaths.forEach(themePath => { const themeAliases = themeAlias(themePath); Object.keys(themeAliases).forEach(aliasKey => { + if (aliasKey in aliases) { + const componentName = aliasKey.substring(aliasKey.indexOf('/') + 1); + aliases[`@theme-init/${componentName}`] = aliases[aliasKey]; + } + aliases[aliasKey] = themeAliases[aliasKey]; }); });